From 00a2e0971bd1efdd3123f961ee1306618217bd71 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Sat, 21 Oct 2023 13:01:11 -0400 Subject: [PATCH 01/41] TCES-37 Add Ron Varshavsky to readme --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 6044faf5..fa6c284b 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Find out more about TCES by visiting the following page: https://toronto-jobs.or - Daniel Dervishi - Jordan Janakievski - Emily Zhou +- Ron Varshavsky ## License [MIT](https://github.com/uoftblueprint/tces/blob/main/LICENSE) From 2e21561a2d623ba1fadfbc0969c5a3ad685c2495 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Wed, 25 Oct 2023 10:47:35 -0400 Subject: [PATCH 02/41] TCES-12 feat(auth): add skeleton endpoints for auth api --- server/index.js | 6 ++++++ server/src/routes/auth.js | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 server/src/routes/auth.js diff --git a/server/index.js b/server/index.js index 6a64136c..aee9fab2 100644 --- a/server/index.js +++ b/server/index.js @@ -6,6 +6,9 @@ const port = 8000; const mysql = require("mysql2"); const connection = mysql.createConnection(process.env.DATABASE_URL); +// Import router for all authentication API endpoints +const authRouter = require('./src/routes/auth'); + app.get("/", (req, res) => { res.send("Helloooo World!"); }); @@ -25,3 +28,6 @@ app.get("/users", (req, res) => { } }); }); + +// All endpoints within this API will be found under the /auth subdirectory +app.use('/auth', authRouter); \ No newline at end of file diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js new file mode 100644 index 00000000..abd2d0bb --- /dev/null +++ b/server/src/routes/auth.js @@ -0,0 +1,19 @@ +const express = require('express'); +const router = express.Router(); + +// User logs in with password +router.post('/login/password', () => { + return "TODO: Implement login functionality"; +}); + +// User signs up +router.post('/signup', () => { + return "TODO: Implement signup functionality"; +}); + +// User logs out +router.post('/logout', () => { + return "TODO: Implement logout functionality"; +}); + +module.exports = router; \ No newline at end of file From 1e80da7119f7fba0ed64ea015e56dccbc383c203 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Wed, 25 Oct 2023 11:09:14 -0400 Subject: [PATCH 03/41] TCES-12 fix(auth): send response on post request --- server/src/routes/auth.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index abd2d0bb..c1d1e6a5 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -2,18 +2,18 @@ const express = require('express'); const router = express.Router(); // User logs in with password -router.post('/login/password', () => { - return "TODO: Implement login functionality"; +router.post('/login/password', (req, res) => { + res.status(200).send("TODO: Implement login functionality"); }); // User signs up -router.post('/signup', () => { - return "TODO: Implement signup functionality"; +router.post('/signup', (req, res) => { + res.status(200).send("TODO: Implement signup functionality"); }); // User logs out -router.post('/logout', () => { - return "TODO: Implement logout functionality"; +router.post('/logout', (req, res) => { + res.status(200).send("TODO: Implement logout functionality"); }); module.exports = router; \ No newline at end of file From 9ef0423980971070d569f5bd57f2876d17676a74 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Wed, 25 Oct 2023 14:29:14 -0400 Subject: [PATCH 04/41] TCES-12 feat(auth) add PassportJS packages --- server/package-lock.json | 43 +++++++++++++++++++++++++++++++++++++++ server/package.json | 2 ++ server/src/routes/auth.js | 7 +++++++ 3 files changed, 52 insertions(+) diff --git a/server/package-lock.json b/server/package-lock.json index 62de04a9..e55f1a7c 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -13,6 +13,8 @@ "eslint": "^8.52.0", "express": "^4.18.2", "mysql2": "^3.6.2", + "passport": "^0.6.0", + "passport-local": "^1.0.0", "pino": "^8.16.0", "pino-http": "^8.5.0", "prettier": "^3.0.3", @@ -3750,6 +3752,42 @@ "node": ">= 0.8" } }, + "node_modules/passport": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", + "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "dependencies": { + "passport-strategy": "1.x.x", + "pause": "0.0.1", + "utils-merge": "^1.0.1" + }, + "engines": { + "node": ">= 0.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/jaredhanson" + } + }, + "node_modules/passport-local": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-local/-/passport-local-1.0.0.tgz", + "integrity": "sha512-9wCE6qKznvf9mQYYbgJ3sVOHmCWoUNMVFoZzNoznmISbhnNNPhN9xfY3sLmScHMetEJeoY7CXwfhCe7argfQow==", + "dependencies": { + "passport-strategy": "1.x.x" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/passport-strategy": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/passport-strategy/-/passport-strategy-1.0.0.tgz", + "integrity": "sha512-CB97UUvDKJde2V0KDWWB3lyf6PC3FaZP7YxZ2G8OAtn9p4HI9j9JLP9qjOGZFvyl8uwNT8qM+hGnz/n16NI7oA==", + "engines": { + "node": ">= 0.4.0" + } + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3798,6 +3836,11 @@ "node": "*" } }, + "node_modules/pause": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/pause/-/pause-0.0.1.tgz", + "integrity": "sha512-KG8UEiEVkR3wGEb4m5yZkVCzigAD+cVEJck2CzYZO37ZGJfctvVptVO192MwrtPhzONn6go8ylnOdMhKqi4nfg==" + }, "node_modules/pg-connection-string": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", diff --git a/server/package.json b/server/package.json index 3445fab5..08f7d5fa 100644 --- a/server/package.json +++ b/server/package.json @@ -15,6 +15,8 @@ "eslint": "^8.52.0", "express": "^4.18.2", "mysql2": "^3.6.2", + "passport": "^0.6.0", + "passport-local": "^1.0.0", "pino": "^8.16.0", "pino-http": "^8.5.0", "prettier": "^3.0.3", diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index c1d1e6a5..d0dc505f 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -1,6 +1,13 @@ const express = require('express'); const router = express.Router(); +// PassportJS imports for auth +const passport = require('passport'); +const LocalStrategy = require('passport-local'); +// Encryption library +const crypto = require('crypto'); + + // User logs in with password router.post('/login/password', (req, res) => { res.status(200).send("TODO: Implement login functionality"); From 55256fc9cabc88b6d349a8d63995e95444517ae5 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Wed, 25 Oct 2023 14:34:16 -0400 Subject: [PATCH 05/41] TCES-12 config(auth) add LocalStrategy config to auth.js --- server/index.js | 4 +++- server/src/routes/auth.js | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/server/index.js b/server/index.js index aee9fab2..298b2da4 100644 --- a/server/index.js +++ b/server/index.js @@ -30,4 +30,6 @@ app.get("/users", (req, res) => { }); // All endpoints within this API will be found under the /auth subdirectory -app.use('/auth', authRouter); \ No newline at end of file +app.use('/auth', authRouter); + +module.exports = connection; \ No newline at end of file diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index d0dc505f..6effa098 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -1,5 +1,7 @@ const express = require('express'); const router = express.Router(); +// database connection +const connection = require('../../index'); // PassportJS imports for auth const passport = require('passport'); @@ -8,6 +10,23 @@ const LocalStrategy = require('passport-local'); const crypto = require('crypto'); +// Local strategy configuration +passport.use(new LocalStrategy(function verify(username, password, cb) { + connection.get('SELECT * FROM users WHERE username = ?', [ username ], function(err, row) { + if (err) { return cb(err); } + if (!row) { return cb(null, false, { message: 'Incorrect username or password.' }); } + + crypto.pbkdf2(password, row.salt, 310000, 32, 'sha256', function(err, hashedPassword) { + if (err) { return cb(err); } + if (!crypto.timingSafeEqual(row.hashed_password, hashedPassword)) { + return cb(null, false, { message: 'Incorrect username or password.' }); + } + + return cb(null, row); + }); + }); +})); + // User logs in with password router.post('/login/password', (req, res) => { res.status(200).send("TODO: Implement login functionality"); From 843337236ab735c345e6c6b189d0f2357dd0213f Mon Sep 17 00:00:00 2001 From: VangoCode Date: Wed, 25 Oct 2023 14:43:27 -0400 Subject: [PATCH 06/41] TCES-12 feat(auth) add passport middleware and fix SQL bug --- server/src/routes/auth.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 6effa098..3b0439b3 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -12,7 +12,7 @@ const crypto = require('crypto'); // Local strategy configuration passport.use(new LocalStrategy(function verify(username, password, cb) { - connection.get('SELECT * FROM users WHERE username = ?', [ username ], function(err, row) { + connection.get('SELECT * FROM users WHERE email = ?', [ username ], function(err, row) { if (err) { return cb(err); } if (!row) { return cb(null, false, { message: 'Incorrect username or password.' }); } @@ -28,9 +28,13 @@ passport.use(new LocalStrategy(function verify(username, password, cb) { })); // User logs in with password -router.post('/login/password', (req, res) => { - res.status(200).send("TODO: Implement login functionality"); -}); +router.post('/login/password', + // auth middleware + passport.authenticate('local', { + successRedirect: '/', + failureRedirect: '/login' + }) +); // User signs up router.post('/signup', (req, res) => { From aedbbc00c31da4714d89afb1548435b690caf0e5 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Thu, 26 Oct 2023 21:32:53 -0400 Subject: [PATCH 07/41] add constants --- server/src/configs/frontend_config.js | 3 +++ server/src/configs/user_config.js | 3 +++ server/src/routes/auth.js | 5 +++-- 3 files changed, 9 insertions(+), 2 deletions(-) create mode 100644 server/src/configs/frontend_config.js create mode 100644 server/src/configs/user_config.js diff --git a/server/src/configs/frontend_config.js b/server/src/configs/frontend_config.js new file mode 100644 index 00000000..684dcd83 --- /dev/null +++ b/server/src/configs/frontend_config.js @@ -0,0 +1,3 @@ +module.exports = { + frontendUrl: "localhost:8000" +} \ No newline at end of file diff --git a/server/src/configs/user_config.js b/server/src/configs/user_config.js new file mode 100644 index 00000000..d1f695ff --- /dev/null +++ b/server/src/configs/user_config.js @@ -0,0 +1,3 @@ +module.exports = { + userTable: "user-dev", +} \ No newline at end of file diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 3b0439b3..1a096b9b 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -36,8 +36,9 @@ router.post('/login/password', }) ); -// User signs up -router.post('/signup', (req, res) => { +// Admin creates a user +// TODO: add permission handling to ensure the user is signed in as the admin +router.post('/create_user', (req, res, next) => { res.status(200).send("TODO: Implement signup functionality"); }); From 1aceb3609a36485605b80fb745d2214c2442f86a Mon Sep 17 00:00:00 2001 From: VangoCode Date: Thu, 26 Oct 2023 21:35:49 -0400 Subject: [PATCH 08/41] TCES-12 config(user, frontend) update config variables for frontend and auth --- server/src/configs/frontend_config.js | 2 +- server/src/routes/auth.js | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/server/src/configs/frontend_config.js b/server/src/configs/frontend_config.js index 684dcd83..c582a06b 100644 --- a/server/src/configs/frontend_config.js +++ b/server/src/configs/frontend_config.js @@ -1,3 +1,3 @@ module.exports = { - frontendUrl: "localhost:8000" + frontendUrl: "http://localhost:3000" } \ No newline at end of file diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 1a096b9b..5e2e7a51 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -8,6 +8,8 @@ const passport = require('passport'); const LocalStrategy = require('passport-local'); // Encryption library const crypto = require('crypto'); +const { userTable } = require('../configs/user_config'); +const { frontendUrl } = require('../configs/frontend_config'); // Local strategy configuration @@ -31,8 +33,8 @@ passport.use(new LocalStrategy(function verify(username, password, cb) { router.post('/login/password', // auth middleware passport.authenticate('local', { - successRedirect: '/', - failureRedirect: '/login' + successRedirect: `${frontendUrl}/`, + failureRedirect: `${frontendUrl}/login` }) ); From 45d59f5346ef953424e1e68058dfb0098f5f1287 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Thu, 26 Oct 2023 22:14:39 -0400 Subject: [PATCH 09/41] TCES-12 config(index) update express to use json body requests --- server/index.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/index.js b/server/index.js index 298b2da4..c751bfa5 100644 --- a/server/index.js +++ b/server/index.js @@ -6,6 +6,9 @@ const port = 8000; const mysql = require("mysql2"); const connection = mysql.createConnection(process.env.DATABASE_URL); +// So that we can send and receive JSON through express +app.use(express.json()); + // Import router for all authentication API endpoints const authRouter = require('./src/routes/auth'); From f6462310c1c770890ac9ba28f39c3862a20b6c20 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Thu, 26 Oct 2023 23:00:42 -0400 Subject: [PATCH 10/41] TCES-12 feat(create-user) implements create_user endpoint --- server/index.js | 4 +-- server/src/configs/user_config.js | 3 +- server/src/routes/auth.js | 48 +++++++++++++++++++++++++------ 3 files changed, 43 insertions(+), 12 deletions(-) diff --git a/server/index.js b/server/index.js index c751bfa5..f503b626 100644 --- a/server/index.js +++ b/server/index.js @@ -33,6 +33,4 @@ app.get("/users", (req, res) => { }); // All endpoints within this API will be found under the /auth subdirectory -app.use('/auth', authRouter); - -module.exports = connection; \ No newline at end of file +app.use('/auth', authRouter); \ No newline at end of file diff --git a/server/src/configs/user_config.js b/server/src/configs/user_config.js index d1f695ff..c0beec16 100644 --- a/server/src/configs/user_config.js +++ b/server/src/configs/user_config.js @@ -1,3 +1,4 @@ module.exports = { - userTable: "user-dev", + // add backticks because this table name has a dash + userTable: "`users-dev`", } \ No newline at end of file diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 5e2e7a51..1d73b51e 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -1,7 +1,9 @@ const express = require('express'); const router = express.Router(); -// database connection -const connection = require('../../index'); + + +const mysql = require("mysql2"); +const connection = mysql.createConnection(process.env.DATABASE_URL); // PassportJS imports for auth const passport = require('passport'); @@ -31,17 +33,47 @@ passport.use(new LocalStrategy(function verify(username, password, cb) { // User logs in with password router.post('/login/password', - // auth middleware - passport.authenticate('local', { - successRedirect: `${frontendUrl}/`, - failureRedirect: `${frontendUrl}/login` - }) + // auth middleware + passport.authenticate('local', { + successRedirect: `${frontendUrl}/`, + failureRedirect: `${frontendUrl}/login` + }) ); // Admin creates a user // TODO: add permission handling to ensure the user is signed in as the admin +/** + * Expected body parameters: + * @type string {body.first_name} + * @type string {body.last_name} + * @type string {body.email} + * @type string {body.password} + */ router.post('/create_user', (req, res, next) => { - res.status(200).send("TODO: Implement signup functionality"); + // Generate salt value + const salt = crypto.randomBytes(16); + + crypto.pbkdf2(req.body.password, salt, 310000, 32, 'sha256', (err, hashedPassword) => { + if (err) { return next(err); } + + connection.query(`INSERT INTO ${userTable} (first_name, last_name, email, password, salt) VALUES (?, ?, ?, ?, ?)`, [ + req.body.first_name, + req.body.last_name, + req.body.email, + hashedPassword, + salt + ], (err) => { + if (err) { return next(err); } + var user = { + id: this.lastID, + email: req.body.email + }; + req.login(user, (err) => { + if (err) { return next(err); } + res.redirect('/'); + }); + }); + }); }); // User logs out From 426d4bb9387958d09addc195c84a1efa7c0ec1a6 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Thu, 26 Oct 2023 23:25:16 -0400 Subject: [PATCH 11/41] TCES-12 refactor(create_user) fix indentation --- server/src/routes/auth.js | 67 +++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 1d73b51e..0a6b4628 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -16,18 +16,18 @@ const { frontendUrl } = require('../configs/frontend_config'); // Local strategy configuration passport.use(new LocalStrategy(function verify(username, password, cb) { - connection.get('SELECT * FROM users WHERE email = ?', [ username ], function(err, row) { - if (err) { return cb(err); } - if (!row) { return cb(null, false, { message: 'Incorrect username or password.' }); } + connection.get('SELECT * FROM users WHERE email = ?', [ username ], function(err, row) { + if (err) { return cb(err); } + if (!row) { return cb(null, false, { message: 'Incorrect username or password.' }); } - crypto.pbkdf2(password, row.salt, 310000, 32, 'sha256', function(err, hashedPassword) { - if (err) { return cb(err); } - if (!crypto.timingSafeEqual(row.hashed_password, hashedPassword)) { - return cb(null, false, { message: 'Incorrect username or password.' }); - } - - return cb(null, row); - }); + crypto.pbkdf2(password, row.salt, 310000, 32, 'sha256', function(err, hashedPassword) { + if (err) { return cb(err); } + if (!crypto.timingSafeEqual(row.hashed_password, hashedPassword)) { + return cb(null, false, { message: 'Incorrect username or password.' }); + } + + return cb(null, row); + }); }); })); @@ -50,30 +50,35 @@ router.post('/login/password', * @type string {body.password} */ router.post('/create_user', (req, res, next) => { - // Generate salt value - const salt = crypto.randomBytes(16); + try { + // Generate salt value + const salt = crypto.randomBytes(16); - crypto.pbkdf2(req.body.password, salt, 310000, 32, 'sha256', (err, hashedPassword) => { - if (err) { return next(err); } + crypto.pbkdf2(req.body.password, salt, 310000, 32, 'sha256', (err, hashedPassword) => { + if (err) { return next(err); } - connection.query(`INSERT INTO ${userTable} (first_name, last_name, email, password, salt) VALUES (?, ?, ?, ?, ?)`, [ - req.body.first_name, - req.body.last_name, - req.body.email, - hashedPassword, - salt - ], (err) => { - if (err) { return next(err); } - var user = { - id: this.lastID, - email: req.body.email - }; - req.login(user, (err) => { - if (err) { return next(err); } - res.redirect('/'); + connection.query(`INSERT INTO ${userTable} (first_name, last_name, email, password, salt) VALUES (?, ?, ?, ?, ?)`, [ + req.body.first_name, + req.body.last_name, + req.body.email, + hashedPassword, + salt + ], (err) => { + if (err) { return next(err); } + var user = { + id: this.lastID, + email: req.body.email + }; + req.login(user, (err) => { + if (err) { return next(err); } + res.redirect('/'); + }); }); }); - }); + } catch (err) { + console.log(err); + res.status(500).send("error"); + } }); // User logs out From 42b7e72ca5cafea2b0f90eb04b296bcc9e7d9097 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Thu, 26 Oct 2023 23:45:19 -0400 Subject: [PATCH 12/41] TCES-12 feat(login) implements user login --- server/src/routes/auth.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 0a6b4628..9f9d1cb6 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -16,13 +16,16 @@ const { frontendUrl } = require('../configs/frontend_config'); // Local strategy configuration passport.use(new LocalStrategy(function verify(username, password, cb) { - connection.get('SELECT * FROM users WHERE email = ?', [ username ], function(err, row) { + connection.query(`SELECT * FROM ${userTable} WHERE email = ?`, [ username ], function(err, rows, fields) { if (err) { return cb(err); } - if (!row) { return cb(null, false, { message: 'Incorrect username or password.' }); } + if (!rows || rows.length == 0) { return cb(null, false, { message: 'Incorrect username or password.' }); } + + // get first row, here it will only be one row + const row = rows[0]; crypto.pbkdf2(password, row.salt, 310000, 32, 'sha256', function(err, hashedPassword) { if (err) { return cb(err); } - if (!crypto.timingSafeEqual(row.hashed_password, hashedPassword)) { + if (!crypto.timingSafeEqual(row.password, hashedPassword)) { return cb(null, false, { message: 'Incorrect username or password.' }); } @@ -32,11 +35,18 @@ passport.use(new LocalStrategy(function verify(username, password, cb) { })); // User logs in with password +/** + * Note: you MUST use `username` as the JSON body key or else this will not work! + * + * Expected body parameters: + * @type string {body.username} + * @type string {body.password} + */ router.post('/login/password', // auth middleware passport.authenticate('local', { - successRedirect: `${frontendUrl}/`, - failureRedirect: `${frontendUrl}/login` + successRedirect: "/success",//`${frontendUrl}/`, + failureRedirect: "/failure" //`${frontendUrl}/login` }) ); From dd3df2568416d2a5e01266c27f47fe5302321611 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Sat, 28 Oct 2023 18:01:10 -0400 Subject: [PATCH 13/41] TCES-12 feat(session) implements user session --- server/index.js | 14 + server/package-lock.json | 1135 ++++++++++++++++++++++++++++++++++++- server/package.json | 2 + server/src/routes/auth.js | 12 + 4 files changed, 1146 insertions(+), 17 deletions(-) diff --git a/server/index.js b/server/index.js index f503b626..dff1a713 100644 --- a/server/index.js +++ b/server/index.js @@ -6,12 +6,26 @@ const port = 8000; const mysql = require("mysql2"); const connection = mysql.createConnection(process.env.DATABASE_URL); +// Session storage imports +const passport = require('passport'); +var session = require('express-session'); +var SQLiteStore = require('connect-sqlite3')(session); + // So that we can send and receive JSON through express app.use(express.json()); // Import router for all authentication API endpoints const authRouter = require('./src/routes/auth'); +// Set up session for authorization +app.use(session({ + secret: 'blueprint-tces', + resave: false, + saveUninitialized: false, + cookie: { secure: true } +})); +app.use(passport.authenticate('session')); + app.get("/", (req, res) => { res.send("Helloooo World!"); }); diff --git a/server/package-lock.json b/server/package-lock.json index e55f1a7c..052decab 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -9,9 +9,11 @@ "version": "1.0.0", "license": "MIT", "dependencies": { + "connect-sqlite3": "^0.9.13", "dotenv": "^16.3.1", "eslint": "^8.52.0", "express": "^4.18.2", + "express-session": "^1.17.3", "mysql2": "^3.6.2", "passport": "^0.6.0", "passport-local": "^1.0.0", @@ -157,6 +159,12 @@ "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "optional": true + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.13", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.13.tgz", @@ -244,6 +252,25 @@ "dev": true, "license": "MIT" }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -276,6 +303,30 @@ "node": ">= 8" } }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@pkgr/utils": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/@pkgr/utils/-/utils-2.4.2.tgz", @@ -301,6 +352,15 @@ "dev": true, "license": "MIT" }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "optional": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/@types/chai": { "version": "4.3.9", "dev": true, @@ -414,6 +474,11 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "node_modules/abort-controller": { "version": "3.0.0", "license": "MIT", @@ -461,6 +526,63 @@ "node": ">=0.4.0" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", @@ -495,6 +617,36 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -841,6 +993,89 @@ "node": ">=8" } }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/cacache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/cacache/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cacache/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/call-bind": { "version": "1.0.5", "license": "MIT", @@ -918,6 +1153,23 @@ "node": "*" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "optional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -934,6 +1186,14 @@ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/colorette": { "version": "2.0.20", "dev": true, @@ -950,6 +1210,22 @@ "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", "dev": true }, + "node_modules/connect-sqlite3": { + "version": "0.9.13", + "resolved": "https://registry.npmjs.org/connect-sqlite3/-/connect-sqlite3-0.9.13.tgz", + "integrity": "sha512-4Dif7wjNutcAsvvl85nqApIa3gViEnN6lKOcEBEtuL9JB1DIq1bREcq0pQCc1oCpSvDGpjsFs0doftzGFc4cmQ==", + "dependencies": { + "sqlite3": "^5.0.2" + }, + "engines": { + "node": ">=0.4.x" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/content-disposition": { "version": "0.5.4", "license": "MIT", @@ -1104,6 +1380,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "node_modules/denque": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", @@ -1137,6 +1418,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "engines": { + "node": ">=8" + } + }, "node_modules/diff-sequences": { "version": "29.6.3", "dev": true, @@ -1190,6 +1479,27 @@ "node": ">= 0.8" } }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/end-of-stream": { "version": "1.4.4", "dev": true, @@ -1198,6 +1508,21 @@ "once": "^1.4.0" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "optional": true + }, "node_modules/es-abstract": { "version": "1.22.3", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", @@ -2049,6 +2374,32 @@ "node": ">= 0.10.0" } }, + "node_modules/express-session": { + "version": "1.17.3", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.3.tgz", + "integrity": "sha512-4+otWXlShYlG1Ma+2Jnn+xgKUZTMJ5QD3YvfilX3AcocOAbIkVylSWEklzALe/+Pu4qV6TYBj5GwOBFfdKqLBw==", + "dependencies": { + "cookie": "0.4.2", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.1", + "uid-safe": "~2.1.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/express-session/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/fast-copy": { "version": "3.0.1", "dev": true, @@ -2218,6 +2569,17 @@ "node": ">= 0.6" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "license": "ISC" @@ -2268,6 +2630,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/generate-function": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", @@ -2400,6 +2781,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "optional": true + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -2477,6 +2864,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/hasown": { "version": "2.0.0", "license": "MIT", @@ -2509,6 +2901,12 @@ "node": ">= 6" } }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "optional": true + }, "node_modules/http-errors": { "version": "2.0.0", "license": "MIT", @@ -2523,26 +2921,105 @@ "node": ">= 0.8" } }, - "node_modules/human-signals": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", - "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", - "dev": true, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, "engines": { - "node": ">=14.18.0" + "node": ">= 6" } }, - "node_modules/iconv-lite": { - "version": "0.4.24", - "license": "MIT", + "node_modules/http-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "optional": true, "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" + "ms": "2.1.2" }, "engines": { - "node": ">=0.10.0" + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/ieee754": { + "node_modules/http-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { "version": "1.2.1", "funding": [ { @@ -2591,6 +3068,21 @@ "node": ">=0.8.19" } }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "optional": true + }, "node_modules/inflection": { "version": "1.13.4", "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz", @@ -2625,6 +3117,12 @@ "node": ">= 0.4" } }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==", + "optional": true + }, "node_modules/ipaddr.js": { "version": "1.9.1", "license": "MIT", @@ -2766,6 +3264,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-generator-function": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.0.10.tgz", @@ -2811,6 +3317,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "optional": true + }, "node_modules/is-map": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", @@ -3245,6 +3757,67 @@ "node": ">=12" } }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/make-fetch-happen/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "optional": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/media-typer": { "version": "0.3.0", "license": "MIT", @@ -3349,6 +3922,105 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/mlly": { "version": "1.4.2", "dev": true, @@ -3460,6 +4132,171 @@ "node": ">= 0.6" } }, + "node_modules/node-addon-api": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz", + "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==" + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp/node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "optional": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/node-gyp/node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "optional": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-gyp/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "optional": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/node-gyp/node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-gyp/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/npm-run-path": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz", @@ -3487,12 +4324,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "peer": true, "engines": { "node": ">=0.10.0" } @@ -3625,6 +4471,14 @@ "node": ">= 0.8" } }, + "node_modules/on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/once": { "version": "1.4.0", "license": "ISC", @@ -3734,6 +4588,21 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4024,6 +4893,25 @@ "version": "2.2.0", "license": "MIT" }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -4107,6 +4995,14 @@ "version": "4.0.4", "license": "MIT" }, + "node_modules/random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/range-parser": { "version": "1.2.1", "license": "MIT", @@ -4224,6 +5120,15 @@ "node": ">=4" } }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "optional": true, + "engines": { + "node": ">= 4" + } + }, "node_modules/retry-as-promised": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", @@ -4657,6 +5562,11 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "node_modules/set-function-length": { "version": "1.1.1", "license": "MIT", @@ -4727,8 +5637,68 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "optional": true, + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/socks-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "optional": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/socks-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "optional": true }, "node_modules/sonic-boom": { "version": "3.7.0", @@ -4752,6 +5722,28 @@ "node": ">= 10.x" } }, + "node_modules/sqlite3": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.6.tgz", + "integrity": "sha512-olYkWoKFVNSSSQNvxVUfjiVbz3YtBwTJj+mfV5zpHmqW3sELx2Cf4QCdirMelhM5Zh+KDVaKgQHqCxrqiWHybw==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^4.2.0", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, "node_modules/sqlstring": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", @@ -4760,6 +5752,18 @@ "node": ">= 0.6" } }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/stackback": { "version": "0.0.2", "dev": true, @@ -4784,6 +5788,24 @@ "safe-buffer": "~5.2.0" } }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "node_modules/string.prototype.matchall": { "version": "4.0.10", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz", @@ -4944,6 +5966,30 @@ "url": "https://opencollective.com/unts" } }, + "node_modules/tar": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.0.tgz", + "integrity": "sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -5013,6 +6059,11 @@ "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, "node_modules/tsconfig-paths": { "version": "3.14.2", "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", @@ -5143,6 +6194,17 @@ "dev": true, "license": "MIT" }, + "node_modules/uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "dependencies": { + "random-bytes": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -5162,6 +6224,24 @@ "version": "5.25.3", "license": "MIT" }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, "node_modules/unpipe": { "version": "1.0.0", "license": "MIT", @@ -5188,7 +6268,6 @@ }, "node_modules/util-deprecate": { "version": "1.0.2", - "dev": true, "license": "MIT" }, "node_modules/utils-merge": { @@ -5415,6 +6494,20 @@ "dev": true, "license": "MIT" }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -5522,6 +6615,14 @@ "node": ">=8" } }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, "node_modules/wkx": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", diff --git a/server/package.json b/server/package.json index 08f7d5fa..2c2e5c49 100644 --- a/server/package.json +++ b/server/package.json @@ -11,9 +11,11 @@ "author": "Blueprint", "license": "MIT", "dependencies": { + "connect-sqlite3": "^0.9.13", "dotenv": "^16.3.1", "eslint": "^8.52.0", "express": "^4.18.2", + "express-session": "^1.17.3", "mysql2": "^3.6.2", "passport": "^0.6.0", "passport-local": "^1.0.0", diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 9f9d1cb6..755d1c59 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -34,6 +34,18 @@ passport.use(new LocalStrategy(function verify(username, password, cb) { }); })); +// Set up serialization and deserialization for the user's session +passport.serializeUser(function(user, cb) { + process.nextTick(function() { + cb(null, { id: user.id, username: user.username }); + }); +}); +passport.deserializeUser(function(user, cb) { + process.nextTick(function() { + return cb(null, user); + }); +}); + // User logs in with password /** * Note: you MUST use `username` as the JSON body key or else this will not work! From 5b9207b8e3a983cd046d17e711d921ebc0293e05 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Sat, 28 Oct 2023 18:09:38 -0400 Subject: [PATCH 14/41] TCES-12 feat(logout) implements user logout --- server/src/routes/auth.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 755d1c59..93a4e33f 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -105,7 +105,10 @@ router.post('/create_user', (req, res, next) => { // User logs out router.post('/logout', (req, res) => { - res.status(200).send("TODO: Implement logout functionality"); + req.logout((err) => { + if (err) { return next(err); } + res.redirect('/'); + }); }); module.exports = router; \ No newline at end of file From d05e09718a4da811414c8c00cfe24a919e4858a7 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Sun, 29 Oct 2023 16:26:21 -0400 Subject: [PATCH 15/41] TCES-12 refactor(auth) replace cookie authentication with server-side sqlite auth storage --- server/index.js | 2 +- server/src/routes/auth.js | 8 ++++++++ server/var/db/sessions.db | Bin 0 -> 12288 bytes 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 server/var/db/sessions.db diff --git a/server/index.js b/server/index.js index dff1a713..fe6eba8a 100644 --- a/server/index.js +++ b/server/index.js @@ -22,7 +22,7 @@ app.use(session({ secret: 'blueprint-tces', resave: false, saveUninitialized: false, - cookie: { secure: true } + store: new SQLiteStore({ db: 'sessions.db', dir: './var/db' }) })); app.use(passport.authenticate('session')); diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 93a4e33f..de9f2da0 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -111,4 +111,12 @@ router.post('/logout', (req, res) => { }); }); + +router.post('/test', (req, res) => { + if (req.user) { + res.send("User logged in"); + } + res.send("user not logged in"); +}) + module.exports = router; \ No newline at end of file diff --git a/server/var/db/sessions.db b/server/var/db/sessions.db new file mode 100644 index 0000000000000000000000000000000000000000..ec170df95f62c27d71cb3a998a9857e59af3dd86 GIT binary patch literal 12288 zcmeI$Jx;?g6bEoSsH@@7YN#<+r_DoF7XqSSO6{UCk)(f}~0SG_<0uX=z1Rwwb2tWV=5cnqoO}emFDA191 zZ+xMIQZfuwmW^7|v0Dyn+0|o*WxH%cNspa1>kYek#g3e-A``<%#=MR;9iDQtFvcCN;Yx83+hK00Izz00bZa0SG_<0uX=z z1b!#*ylTuh7N6Tu<*_~(Ifv19^`O2x7*uvD?n&5kVsTmC(@#Nl__DtJc1_0oHVp5i z;MSOjvFysg^&9Tc?j}1y-}j6ByZ=|&vZr-)8u%k_>9{Y7JaTo9TfD?4X{}Tg#yUN$ zuSA??>2a$(nM{_G@1o{ANd^J}5P$##AOHafKmY;|fB*y_0D-?Ju%2tsS^pc1FD?3b A&Hw-a literal 0 HcmV?d00001 From 4aa4a9f57dd8e6b0f7cec8cc7b03dc833856e32f Mon Sep 17 00:00:00 2001 From: VangoCode Date: Mon, 30 Oct 2023 18:30:30 -0400 Subject: [PATCH 16/41] TCES-12 feat(auth) add admin feature --- server/src/routes/auth.js | 7 +++++-- server/var/db/sessions.db | Bin 12288 -> 12288 bytes 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index de9f2da0..180b4d0c 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -37,7 +37,7 @@ passport.use(new LocalStrategy(function verify(username, password, cb) { // Set up serialization and deserialization for the user's session passport.serializeUser(function(user, cb) { process.nextTick(function() { - cb(null, { id: user.id, username: user.username }); + cb(null, { id: user.id, username: user.username, is_admin: user.is_admin }); }); }); passport.deserializeUser(function(user, cb) { @@ -114,7 +114,10 @@ router.post('/logout', (req, res) => { router.post('/test', (req, res) => { if (req.user) { - res.send("User logged in"); + if (req.user.is_admin) { + res.send("User is logged in as admin"); + } + res.send("User logged in, but not an admin"); } res.send("user not logged in"); }) diff --git a/server/var/db/sessions.db b/server/var/db/sessions.db index ec170df95f62c27d71cb3a998a9857e59af3dd86..6c0d851942aa41677ae7b837337b484fc464ad4f 100644 GIT binary patch delta 216 zcmZojXh@hK%_uQZ#+gxKW5P0imR1J-*3E(f7X0-Gec7Azy^MX`3{pxgaxKH+BYewC z98Eo(lX8sGjY5qoEP_+~oGNzIZc#2^s8&kO&(F?eU|{I-Wp8wZYO7>q1@ctmOLfcB z{S1vF0-Xz@s{9=dOHBgPGgBg>{7g&TJ(A5phHTrq0A@(4l2x@*{^TX{cHFgGKoc4H Y?=bM+*(|7Vihp7Nhl(<@FDD@r0i-HJxc~qF delta 166 zcmZojXh@hK&B#1a#+i|MW5P0imUIUG^v!|_vHbdtVoa>Q?2YjS#^s)6m9Fju22O6C zre$TuCdP?=`5~@FsiB6JB~^J&6+2W6PA5#>EbpVCqg0SsTwIV}RH9^6tyEf^S_Gmq lQYinz{7#J8B`EN7u-v-)nntx&do2m-4FC!rfm;imXGWY-h From 52bfcfa914c8957a5d9030aa62879bd11b1cd086 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Mon, 30 Oct 2023 18:32:40 -0400 Subject: [PATCH 17/41] TCES-12 feat(auth) add admin control for creating a user --- server/src/routes/auth.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 180b4d0c..35870fcb 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -72,6 +72,10 @@ router.post('/login/password', * @type string {body.password} */ router.post('/create_user', (req, res, next) => { + if (!req.user) { res.statusCode(403).send("You are not logged in"); } + if (!req.user.is_admin) { res.statusCode(403).send("Only an admin can create users"); } + + // If you reac here, the user is an admin try { // Generate salt value const salt = crypto.randomBytes(16); From e3f56623820ae3ac6b9afebae75b4f6486202f9e Mon Sep 17 00:00:00 2001 From: VangoCode Date: Mon, 30 Oct 2023 18:47:24 -0400 Subject: [PATCH 18/41] TCES-12 fix(auth) fix error status response --- server/src/routes/auth.js | 4 ++-- server/var/db/sessions.db | Bin 12288 -> 12288 bytes 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 35870fcb..11054519 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -72,8 +72,8 @@ router.post('/login/password', * @type string {body.password} */ router.post('/create_user', (req, res, next) => { - if (!req.user) { res.statusCode(403).send("You are not logged in"); } - if (!req.user.is_admin) { res.statusCode(403).send("Only an admin can create users"); } + if (!req.user) { res.status(403).send("You are not logged in"); } + if (!req.user.is_admin) { res.status(403).send("Only an admin can create users"); } // If you reac here, the user is an admin try { diff --git a/server/var/db/sessions.db b/server/var/db/sessions.db index 6c0d851942aa41677ae7b837337b484fc464ad4f..ebab7510051367fb1236cc10cd01e1fdba2272dd 100644 GIT binary patch delta 95 zcmZojXh@hK%_u!l#+gxiV}g#nx}UqdL6)(fdyuDRp^sB|RZ)^}k#A+OQ;}1sWl?FA Vu2aR1x>b)AHgA^K6;L3g7y!@@ANBwM delta 95 zcmZojXh@hK%_uQZ#+gxKV}g#ndVHyFdAgsWQAD6~K~$B$qhYB@V0vasM3kRtsk=wA VnN!7%+HG4GY~C!dE1*C~F#z7XAMXGF From 0d920ace99ba943315ed6a9e6468abd6402ac22c Mon Sep 17 00:00:00 2001 From: VangoCode Date: Mon, 30 Oct 2023 18:52:13 -0400 Subject: [PATCH 19/41] TCES-12 refactor(auth) rewrite functions to use arrow functions --- server/src/routes/auth.js | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 11054519..50241a4a 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -15,15 +15,15 @@ const { frontendUrl } = require('../configs/frontend_config'); // Local strategy configuration -passport.use(new LocalStrategy(function verify(username, password, cb) { - connection.query(`SELECT * FROM ${userTable} WHERE email = ?`, [ username ], function(err, rows, fields) { +passport.use(new LocalStrategy((username, password, cb) => { + connection.query(`SELECT * FROM ${userTable} WHERE email = ?`, [ username ], (err, rows, fields) => { if (err) { return cb(err); } if (!rows || rows.length == 0) { return cb(null, false, { message: 'Incorrect username or password.' }); } // get first row, here it will only be one row const row = rows[0]; - crypto.pbkdf2(password, row.salt, 310000, 32, 'sha256', function(err, hashedPassword) { + crypto.pbkdf2(password, row.salt, 310000, 32, 'sha256', (err, hashedPassword) => { if (err) { return cb(err); } if (!crypto.timingSafeEqual(row.password, hashedPassword)) { return cb(null, false, { message: 'Incorrect username or password.' }); @@ -35,13 +35,13 @@ passport.use(new LocalStrategy(function verify(username, password, cb) { })); // Set up serialization and deserialization for the user's session -passport.serializeUser(function(user, cb) { - process.nextTick(function() { +passport.serializeUser((user, cb) => { + process.nextTick(() => { cb(null, { id: user.id, username: user.username, is_admin: user.is_admin }); }); }); -passport.deserializeUser(function(user, cb) { - process.nextTick(function() { +passport.deserializeUser((user, cb) => { + process.nextTick(() => { return cb(null, user); }); }); @@ -75,7 +75,7 @@ router.post('/create_user', (req, res, next) => { if (!req.user) { res.status(403).send("You are not logged in"); } if (!req.user.is_admin) { res.status(403).send("Only an admin can create users"); } - // If you reac here, the user is an admin + // If you reach here, the user is an admin try { // Generate salt value const salt = crypto.randomBytes(16); From edc09e98ca0c56e0198f43a640bca83feba32e0d Mon Sep 17 00:00:00 2001 From: VangoCode Date: Mon, 30 Oct 2023 19:10:58 -0400 Subject: [PATCH 20/41] TCES-12 refactor(auth) restructure config file for passport --- server/index.js | 3 +++ server/src/configs/passport.js | 41 +++++++++++++++++++++++++++++++++ server/src/routes/auth.js | 36 ++--------------------------- server/var/db/sessions.db | Bin 12288 -> 12288 bytes 4 files changed, 46 insertions(+), 34 deletions(-) create mode 100644 server/src/configs/passport.js diff --git a/server/index.js b/server/index.js index fe6eba8a..64fbecd9 100644 --- a/server/index.js +++ b/server/index.js @@ -11,6 +11,9 @@ const passport = require('passport'); var session = require('express-session'); var SQLiteStore = require('connect-sqlite3')(session); +// Import passport configuration +require("./src/configs/passport"); + // So that we can send and receive JSON through express app.use(express.json()); diff --git a/server/src/configs/passport.js b/server/src/configs/passport.js new file mode 100644 index 00000000..aa7f589a --- /dev/null +++ b/server/src/configs/passport.js @@ -0,0 +1,41 @@ +const passport = require('passport'); +const LocalStrategy = require('passport-local'); + +const mysql = require("mysql2"); +const connection = mysql.createConnection(process.env.DATABASE_URL); + +const { userTable } = require('./user_config'); +const crypto = require('crypto'); + + +// Local strategy configuration +passport.use(new LocalStrategy((username, password, cb) => { + connection.query(`SELECT * FROM ${userTable} WHERE email = ?`, [ username ], (err, rows, fields) => { + if (err) { return cb(err); } + if (!rows || rows.length == 0) { return cb(null, false, { message: 'Incorrect username or password.' }); } + + // get first row, here it will only be one row + const row = rows[0]; + + crypto.pbkdf2(password, row.salt, 310000, 32, 'sha256', (err, hashedPassword) => { + if (err) { return cb(err); } + if (!crypto.timingSafeEqual(row.password, hashedPassword)) { + return cb(null, false, { message: 'Incorrect username or password.' }); + } + + return cb(null, row); + }); + }); +})); + +// Set up serialization and deserialization for the user's session +passport.serializeUser((user, cb) => { + process.nextTick(() => { + cb(null, { id: user.id, username: user.email, is_admin: user.is_admin }); + }); +}); +passport.deserializeUser((user, cb) => { + process.nextTick(() => { + return cb(null, user); + }); +}); \ No newline at end of file diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 50241a4a..749d9b52 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -14,38 +14,6 @@ const { userTable } = require('../configs/user_config'); const { frontendUrl } = require('../configs/frontend_config'); -// Local strategy configuration -passport.use(new LocalStrategy((username, password, cb) => { - connection.query(`SELECT * FROM ${userTable} WHERE email = ?`, [ username ], (err, rows, fields) => { - if (err) { return cb(err); } - if (!rows || rows.length == 0) { return cb(null, false, { message: 'Incorrect username or password.' }); } - - // get first row, here it will only be one row - const row = rows[0]; - - crypto.pbkdf2(password, row.salt, 310000, 32, 'sha256', (err, hashedPassword) => { - if (err) { return cb(err); } - if (!crypto.timingSafeEqual(row.password, hashedPassword)) { - return cb(null, false, { message: 'Incorrect username or password.' }); - } - - return cb(null, row); - }); - }); -})); - -// Set up serialization and deserialization for the user's session -passport.serializeUser((user, cb) => { - process.nextTick(() => { - cb(null, { id: user.id, username: user.username, is_admin: user.is_admin }); - }); -}); -passport.deserializeUser((user, cb) => { - process.nextTick(() => { - return cb(null, user); - }); -}); - // User logs in with password /** * Note: you MUST use `username` as the JSON body key or else this will not work! @@ -119,9 +87,9 @@ router.post('/logout', (req, res) => { router.post('/test', (req, res) => { if (req.user) { if (req.user.is_admin) { - res.send("User is logged in as admin"); + res.send(`User ${req.user.username} is logged in as admin`); } - res.send("User logged in, but not an admin"); + res.send(`User ${req.user} logged in, but not an admin`); } res.send("user not logged in"); }) diff --git a/server/var/db/sessions.db b/server/var/db/sessions.db index ebab7510051367fb1236cc10cd01e1fdba2272dd..36de677cc46374befa5b0211fcf2f35d150f538c 100644 GIT binary patch delta 253 zcmZojXh@hK&8R+6#+gxlW5P0i7D)zv$<2ZS{QUZjDNL-s>`m1Vq zQ2|~#9>Ko3hGt&H7GXI~AwJ1Y6+0T(cm*bJmiMXGQ7T9*E-uI~Dp9hkRw^w{EdtS* zDN0s`I$&;IVs5IEl~PfDURh#MaYkZUadxGlLwasvW{zHRey);^Qf6^{VoGji9!O(J zWdTUFQ)yZn&?FtDl*E!mC97z|*jgaqVqjokq1@ct=+}#bb zjQ!k$JUt72oWiS$l6;GND~p|qoI)*&N~3gvhSaTktN=44RmrMaDSvX9yd8Hf7tlmT Y{yPl(cYuyM#Xm8CLq(a{my?i*0E=crf&c&j From 3dc12015a03d5f20ad4a87d1d3f99631b87fcc57 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Mon, 30 Oct 2023 19:13:20 -0400 Subject: [PATCH 21/41] TCES-12 fix(auth) remove automatic logging in when user created --- server/src/routes/auth.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 749d9b52..f2cd3eea 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -7,7 +7,6 @@ const connection = mysql.createConnection(process.env.DATABASE_URL); // PassportJS imports for auth const passport = require('passport'); -const LocalStrategy = require('passport-local'); // Encryption library const crypto = require('crypto'); const { userTable } = require('../configs/user_config'); @@ -59,14 +58,7 @@ router.post('/create_user', (req, res, next) => { salt ], (err) => { if (err) { return next(err); } - var user = { - id: this.lastID, - email: req.body.email - }; - req.login(user, (err) => { - if (err) { return next(err); } - res.redirect('/'); - }); + res.status(200).send("User created successfully"); }); }); } catch (err) { From c7f201ed8f5aa7aa18cf94dbf8cf7d6e5e7827fa Mon Sep 17 00:00:00 2001 From: VangoCode Date: Thu, 2 Nov 2023 21:11:03 -0400 Subject: [PATCH 22/41] TCES-12 refactor(auth) remove callback function for hashing --- server/src/routes/auth.js | 42 ++++++++++++++++++++++++++------------ server/var/db/sessions.db | Bin 12288 -> 12288 bytes 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index f2cd3eea..b3bc4038 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -4,6 +4,22 @@ const router = express.Router(); const mysql = require("mysql2"); const connection = mysql.createConnection(process.env.DATABASE_URL); +const Sequelize = require("sequelize"); +const sequelize = new Sequelize( + 'blueprint-tces', + 'username', + 'password', + { + host: 'aws.connect.psdb.cloud', + dialect: 'mysql', + dialectOptions: { + ssl: { + rejectUnauthorized: true + }, + } + } +); + // PassportJS imports for auth const passport = require('passport'); @@ -47,20 +63,20 @@ router.post('/create_user', (req, res, next) => { // Generate salt value const salt = crypto.randomBytes(16); - crypto.pbkdf2(req.body.password, salt, 310000, 32, 'sha256', (err, hashedPassword) => { - if (err) { return next(err); } - - connection.query(`INSERT INTO ${userTable} (first_name, last_name, email, password, salt) VALUES (?, ?, ?, ?, ?)`, [ - req.body.first_name, - req.body.last_name, - req.body.email, - hashedPassword, - salt - ], (err) => { - if (err) { return next(err); } - res.status(200).send("User created successfully"); - }); + // synchronous hashing function + const hashedPassword = crypto.pbkdf2(req.body.password, salt, 310000, 32, 'sha256'); + + connection.query(`INSERT INTO ${userTable} (first_name, last_name, email, password, salt) VALUES (?, ?, ?, ?, ?)`, [ + req.body.first_name, + req.body.last_name, + req.body.email, + hashedPassword, + salt + ], (err) => { + if (err) { return next(err); } + res.status(200).send("User created successfully"); }); + } catch (err) { console.log(err); res.status(500).send("error"); diff --git a/server/var/db/sessions.db b/server/var/db/sessions.db index 36de677cc46374befa5b0211fcf2f35d150f538c..4055c5bcbbe128f31c5006a99869719a50d0faa6 100644 GIT binary patch delta 96 zcmZojXh@hK&8Rg|#+gxTW5Pi>_0$qqLt{s$M6ZCr;8ahKaz{TigG%2_V<)fRtWa}v WAE%0)wa)GbHhaiV7f>Xmm^&Cf6!@Qu-oOlz{!1Aa7uN;qH-&{j8uVRa^9H$VU WWT%Q94Q#vun?2;G3n&s&%me_`Vjffg From cfac6d55de06cdb10049d33a2992f1740ccd58d5 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Thu, 2 Nov 2023 21:11:57 -0400 Subject: [PATCH 23/41] TCES-12 hotfix(auth) fix hashing function --- server/src/routes/auth.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index b3bc4038..0eb1cc41 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -64,7 +64,7 @@ router.post('/create_user', (req, res, next) => { const salt = crypto.randomBytes(16); // synchronous hashing function - const hashedPassword = crypto.pbkdf2(req.body.password, salt, 310000, 32, 'sha256'); + const hashedPassword = crypto.pbkdf2Sync(req.body.password, salt, 310000, 32, 'sha256'); connection.query(`INSERT INTO ${userTable} (first_name, last_name, email, password, salt) VALUES (?, ?, ?, ?, ?)`, [ req.body.first_name, From 76b028e45482a9d83ba8a53ce904abd63e315ab4 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Thu, 2 Nov 2023 21:47:42 -0400 Subject: [PATCH 24/41] TCES-12 refactor(auth) implement sequelize model for auth --- server/src/models/user.model.js | 57 +++++++++++++++++++++++++++++++++ server/src/routes/auth.js | 55 +++++++++++++++---------------- 2 files changed, 85 insertions(+), 27 deletions(-) create mode 100644 server/src/models/user.model.js diff --git a/server/src/models/user.model.js b/server/src/models/user.model.js new file mode 100644 index 00000000..1b7174b6 --- /dev/null +++ b/server/src/models/user.model.js @@ -0,0 +1,57 @@ +const { Sequelize, DataTypes } = require("sequelize"); +const sequelize = new Sequelize( + 'blueprint-tces', + '8p17fcl2jfs56m6568qv', + 'pscale_pw_I0KA2cGUmh9IeR95xDnRy9YAjZlkLQGzJVn1JXbJWve', + { + host: 'aws.connect.psdb.cloud', + dialect: 'mysql', + dialectOptions: { + ssl: { + rejectUnauthorized: true + }, + }, + define: { + defaultScope: { + attributes: { exclude: ['createdAt', 'updatedAt'] } + }, + timestamps: false + } + }, +); + + +const User = sequelize.define("users-dev", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true + }, + first_name: { + type: DataTypes.STRING, + allowNull: false + }, + last_name: { + type: DataTypes.STRING, + allowNull: false + }, + email: { + type: DataTypes.STRING, + allowNull: false + }, + password: { + type: DataTypes.BLOB('tiny'), + allowNull: false + }, + salt: { + type: DataTypes.BLOB('tiny'), + allowNull: false + }, + isAdmin: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: 0 + } +}); + +module.exports = User; \ No newline at end of file diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 0eb1cc41..7cad8038 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -4,21 +4,23 @@ const router = express.Router(); const mysql = require("mysql2"); const connection = mysql.createConnection(process.env.DATABASE_URL); -const Sequelize = require("sequelize"); -const sequelize = new Sequelize( - 'blueprint-tces', - 'username', - 'password', - { - host: 'aws.connect.psdb.cloud', - dialect: 'mysql', - dialectOptions: { - ssl: { - rejectUnauthorized: true - }, - } - } -); +// const Sequelize = require("sequelize"); +// const sequelize = new Sequelize( +// 'blueprint-tces', +// 'username', +// 'password', +// { +// host: 'aws.connect.psdb.cloud', +// dialect: 'mysql', +// dialectOptions: { +// ssl: { +// rejectUnauthorized: true +// }, +// } +// } +// ); + +const User = require('../models/user.model') // PassportJS imports for auth @@ -54,7 +56,7 @@ router.post('/login/password', * @type string {body.email} * @type string {body.password} */ -router.post('/create_user', (req, res, next) => { +router.post('/create_user', async (req, res, next) => { if (!req.user) { res.status(403).send("You are not logged in"); } if (!req.user.is_admin) { res.status(403).send("Only an admin can create users"); } @@ -66,20 +68,19 @@ router.post('/create_user', (req, res, next) => { // synchronous hashing function const hashedPassword = crypto.pbkdf2Sync(req.body.password, salt, 310000, 32, 'sha256'); - connection.query(`INSERT INTO ${userTable} (first_name, last_name, email, password, salt) VALUES (?, ?, ?, ?, ?)`, [ - req.body.first_name, - req.body.last_name, - req.body.email, - hashedPassword, - salt - ], (err) => { - if (err) { return next(err); } - res.status(200).send("User created successfully"); - }); + User.create({ + first_name: req.body.first_name, + last_name: req.body.last_name, + email: req.body.email, + password: hashedPassword, + salt: salt + }).then(() => {}); + + res.status(200).send("User created successfully"); } catch (err) { console.log(err); - res.status(500).send("error"); + res.status(500).send(err); } }); From 6b35c4d30c6e60cb8793819951c045d4d0bde6a0 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Thu, 2 Nov 2023 22:05:55 -0400 Subject: [PATCH 25/41] TCES-12 refactor(auth) implement sequelize for user --- server/.env.example | 6 +++++- server/src/configs/frontend_config.js | 3 --- server/src/configs/passport.js | 6 +++--- server/src/configs/user_config.js | 4 ---- server/src/models/user.model.js | 17 ++++++++++------- server/src/routes/auth.js | 6 ++---- 6 files changed, 20 insertions(+), 22 deletions(-) delete mode 100644 server/src/configs/frontend_config.js delete mode 100644 server/src/configs/user_config.js diff --git a/server/.env.example b/server/.env.example index b7dd6bd1..f30c0d99 100644 --- a/server/.env.example +++ b/server/.env.example @@ -1,3 +1,7 @@ # This will connect to the main branch of the db in the final changes # Rename this to .env and copy a dev branch url to here from PlanetScale -DATABASE_URL='' +DATABASE_NAME='blueprint-tces' +DATABASE_USERNAME='8p17fcl2jfs56m6568qv' +DATABASE_PASSOWRD='pscale_pw_I0KA2cGUmh9IeR95xDnRy9YAjZlkLQGzJVn1JXbJWve' +FRONTNED_URL='http://localhost:3000' +USERS_TABLE="users-dev" \ No newline at end of file diff --git a/server/src/configs/frontend_config.js b/server/src/configs/frontend_config.js deleted file mode 100644 index c582a06b..00000000 --- a/server/src/configs/frontend_config.js +++ /dev/null @@ -1,3 +0,0 @@ -module.exports = { - frontendUrl: "http://localhost:3000" -} \ No newline at end of file diff --git a/server/src/configs/passport.js b/server/src/configs/passport.js index aa7f589a..97ab1558 100644 --- a/server/src/configs/passport.js +++ b/server/src/configs/passport.js @@ -1,16 +1,16 @@ +require('dotenv').config(); + const passport = require('passport'); const LocalStrategy = require('passport-local'); const mysql = require("mysql2"); const connection = mysql.createConnection(process.env.DATABASE_URL); -const { userTable } = require('./user_config'); const crypto = require('crypto'); - // Local strategy configuration passport.use(new LocalStrategy((username, password, cb) => { - connection.query(`SELECT * FROM ${userTable} WHERE email = ?`, [ username ], (err, rows, fields) => { + connection.query(`SELECT * FROM ${process.env.USERS_TABLE} WHERE email = ?`, [ username ], (err, rows, fields) => { if (err) { return cb(err); } if (!rows || rows.length == 0) { return cb(null, false, { message: 'Incorrect username or password.' }); } diff --git a/server/src/configs/user_config.js b/server/src/configs/user_config.js deleted file mode 100644 index c0beec16..00000000 --- a/server/src/configs/user_config.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - // add backticks because this table name has a dash - userTable: "`users-dev`", -} \ No newline at end of file diff --git a/server/src/models/user.model.js b/server/src/models/user.model.js index 1b7174b6..b4bfb282 100644 --- a/server/src/models/user.model.js +++ b/server/src/models/user.model.js @@ -1,10 +1,12 @@ +require("dotenv").config(); + const { Sequelize, DataTypes } = require("sequelize"); const sequelize = new Sequelize( - 'blueprint-tces', - '8p17fcl2jfs56m6568qv', - 'pscale_pw_I0KA2cGUmh9IeR95xDnRy9YAjZlkLQGzJVn1JXbJWve', + process.env.DATABASE_NAME, + process.env.DATABASE_USERNAME, + process.env.DATABASE_PASSWORD, { - host: 'aws.connect.psdb.cloud', + host: process.env.DATABASE_HOST, dialect: 'mysql', dialectOptions: { ssl: { @@ -15,13 +17,14 @@ const sequelize = new Sequelize( defaultScope: { attributes: { exclude: ['createdAt', 'updatedAt'] } }, - timestamps: false + timestamps: false, + freezeTableName: true } }, ); -const User = sequelize.define("users-dev", { +const User = sequelize.define(process.env.USERS_TABLE, { id: { type: DataTypes.INTEGER, autoIncrement: true, @@ -47,7 +50,7 @@ const User = sequelize.define("users-dev", { type: DataTypes.BLOB('tiny'), allowNull: false }, - isAdmin: { + is_admin: { type: DataTypes.BOOLEAN, allowNull: false, defaultValue: 0 diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 7cad8038..fe595666 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -27,8 +27,6 @@ const User = require('../models/user.model') const passport = require('passport'); // Encryption library const crypto = require('crypto'); -const { userTable } = require('../configs/user_config'); -const { frontendUrl } = require('../configs/frontend_config'); // User logs in with password @@ -68,13 +66,13 @@ router.post('/create_user', async (req, res, next) => { // synchronous hashing function const hashedPassword = crypto.pbkdf2Sync(req.body.password, salt, 310000, 32, 'sha256'); - User.create({ + await User.create({ first_name: req.body.first_name, last_name: req.body.last_name, email: req.body.email, password: hashedPassword, salt: salt - }).then(() => {}); + }); res.status(200).send("User created successfully"); From 3f310212c76293bc01561b66fb0764628e57976d Mon Sep 17 00:00:00 2001 From: VangoCode Date: Thu, 2 Nov 2023 22:13:48 -0400 Subject: [PATCH 26/41] TCES-12 refactor(auth) implement sequelize in separate file --- server/.env.example | 9 +++++---- server/src/configs/sequelize.js | 28 ++++++++++++++++++++++++++++ server/src/models/user.model.js | 25 ++----------------------- 3 files changed, 35 insertions(+), 27 deletions(-) create mode 100644 server/src/configs/sequelize.js diff --git a/server/.env.example b/server/.env.example index f30c0d99..94778dd7 100644 --- a/server/.env.example +++ b/server/.env.example @@ -1,7 +1,8 @@ # This will connect to the main branch of the db in the final changes # Rename this to .env and copy a dev branch url to here from PlanetScale DATABASE_NAME='blueprint-tces' -DATABASE_USERNAME='8p17fcl2jfs56m6568qv' -DATABASE_PASSOWRD='pscale_pw_I0KA2cGUmh9IeR95xDnRy9YAjZlkLQGzJVn1JXbJWve' -FRONTNED_URL='http://localhost:3000' -USERS_TABLE="users-dev" \ No newline at end of file +DATABASE_USERNAME='sl1r933z216gebrobmoy' +DATABASE_PASSWORD='pscale_pw_9QtSX4DdwRvnD5T0CsVZjABnMu862B4FJLCEaBd3BX8' +DATABASE_HOST='aws.connect.psdb.cloud' +FRONTEND_URL='http://localhost:3000' +USERS_TABLE='users-dev' \ No newline at end of file diff --git a/server/src/configs/sequelize.js b/server/src/configs/sequelize.js new file mode 100644 index 00000000..d1635f1f --- /dev/null +++ b/server/src/configs/sequelize.js @@ -0,0 +1,28 @@ +require('dotenv').config(); +const { Sequelize } = require('sequelize'); + +const sequelize = new Sequelize( + process.env.DATABASE_NAME, + process.env.DATABASE_USERNAME, + process.env.DATABASE_PASSWORD, + { + host: process.env.DATABASE_HOST, + dialect: 'mysql', + dialectOptions: { + ssl: { + rejectUnauthorized: true + }, + }, + define: { + defaultScope: { + attributes: { exclude: ['createdAt', 'updatedAt'] } + }, + timestamps: false, + freezeTableName: true + } + }, +); + +module.exports = { + sequelize: sequelize +} \ No newline at end of file diff --git a/server/src/models/user.model.js b/server/src/models/user.model.js index b4bfb282..202effd7 100644 --- a/server/src/models/user.model.js +++ b/server/src/models/user.model.js @@ -1,27 +1,6 @@ require("dotenv").config(); - -const { Sequelize, DataTypes } = require("sequelize"); -const sequelize = new Sequelize( - process.env.DATABASE_NAME, - process.env.DATABASE_USERNAME, - process.env.DATABASE_PASSWORD, - { - host: process.env.DATABASE_HOST, - dialect: 'mysql', - dialectOptions: { - ssl: { - rejectUnauthorized: true - }, - }, - define: { - defaultScope: { - attributes: { exclude: ['createdAt', 'updatedAt'] } - }, - timestamps: false, - freezeTableName: true - } - }, -); +const { DataTypes } = require("sequelize"); +const { sequelize } = require('../configs/sequelize'); const User = sequelize.define(process.env.USERS_TABLE, { From 88fbc71181ee5a04c1e77ff907676603860c8b13 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Thu, 2 Nov 2023 22:22:25 -0400 Subject: [PATCH 27/41] TCES-12 refactor(auth) refactor localstrategy imports --- server/src/configs/passport.js | 27 ++++++++++++--------------- server/src/routes/auth.js | 21 +-------------------- server/var/db/sessions.db | Bin 12288 -> 12288 bytes 3 files changed, 13 insertions(+), 35 deletions(-) diff --git a/server/src/configs/passport.js b/server/src/configs/passport.js index 97ab1558..b3c8eb13 100644 --- a/server/src/configs/passport.js +++ b/server/src/configs/passport.js @@ -5,27 +5,24 @@ const LocalStrategy = require('passport-local'); const mysql = require("mysql2"); const connection = mysql.createConnection(process.env.DATABASE_URL); +const User = require('../models/user.model') const crypto = require('crypto'); // Local strategy configuration -passport.use(new LocalStrategy((username, password, cb) => { - connection.query(`SELECT * FROM ${process.env.USERS_TABLE} WHERE email = ?`, [ username ], (err, rows, fields) => { - if (err) { return cb(err); } - if (!rows || rows.length == 0) { return cb(null, false, { message: 'Incorrect username or password.' }); } +passport.use(new LocalStrategy(async (username, password, cb) => { + const user = await User.findOne({ where: { email: username } }); + if (user === null) { + return cb(null, false, { message: 'Incorrect username or password.' }); + } + + const hashedPassword = crypto.pbkdf2Sync(password, user.salt, 310000, 32, 'sha256'); - // get first row, here it will only be one row - const row = rows[0]; + if (!crypto.timingSafeEqual(user.password, hashedPassword)) { + return cb(null, false, { message: 'Incorrect username or password.' }); + } - crypto.pbkdf2(password, row.salt, 310000, 32, 'sha256', (err, hashedPassword) => { - if (err) { return cb(err); } - if (!crypto.timingSafeEqual(row.password, hashedPassword)) { - return cb(null, false, { message: 'Incorrect username or password.' }); - } - - return cb(null, row); - }); - }); + return cb(null, user); })); // Set up serialization and deserialization for the user's session diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index fe595666..bc258d75 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -1,26 +1,7 @@ const express = require('express'); const router = express.Router(); - -const mysql = require("mysql2"); -const connection = mysql.createConnection(process.env.DATABASE_URL); -// const Sequelize = require("sequelize"); -// const sequelize = new Sequelize( -// 'blueprint-tces', -// 'username', -// 'password', -// { -// host: 'aws.connect.psdb.cloud', -// dialect: 'mysql', -// dialectOptions: { -// ssl: { -// rejectUnauthorized: true -// }, -// } -// } -// ); - -const User = require('../models/user.model') +const User = require('../models/user.model'); // PassportJS imports for auth diff --git a/server/var/db/sessions.db b/server/var/db/sessions.db index 4055c5bcbbe128f31c5006a99869719a50d0faa6..052d6e6314319522927e0fc28d1a90baee1b0b09 100644 GIT binary patch delta 144 zcmZojXh@hK&1f)D#+lJzW5P0i7DEPp!_9&ULi{ezec79;Q%hV8jUAm5y#fM*Q$0P( z8-18qf#Tlr;ZBu~E&;9;7KWbYZuzG1na-v`Sw*Q~mBxXA#lcxl6+4^siv=co$j@Xc RDJo6f{8#=Fzak-BOaP>6E?WQq delta 147 zcmZojXh@hK&8Rg|#+gxTW5P0i7D)zv$<2Za{QUZjDNL-s>`m3FC9a0Xj!ubQ0fE7( zo*w0ner5)hzL~~OUcp(R=H@<56+3I4-49Goke?}2tyEH3kg8;* Date: Thu, 2 Nov 2023 22:56:44 -0400 Subject: [PATCH 28/41] TCES-12 fix(auth) implements user login feature --- server/src/routes/auth.js | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index bc258d75..a616d033 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -21,8 +21,8 @@ const crypto = require('crypto'); router.post('/login/password', // auth middleware passport.authenticate('local', { - successRedirect: "/success",//`${frontendUrl}/`, - failureRedirect: "/failure" //`${frontendUrl}/login` + successRedirect: `${process.env.FRONTEND_URL}/`, + failureRedirect: `${process.env.FRONTEND_URL}/login` }) ); @@ -36,8 +36,8 @@ router.post('/login/password', * @type string {body.password} */ router.post('/create_user', async (req, res, next) => { - if (!req.user) { res.status(403).send("You are not logged in"); } - if (!req.user.is_admin) { res.status(403).send("Only an admin can create users"); } + if (!req.user) { res.status(403).send("You are not logged in"); return; } + if (!req.user.is_admin) { res.status(403).send("Only an admin can create users"); return; } // If you reach here, the user is an admin try { @@ -58,8 +58,11 @@ router.post('/create_user', async (req, res, next) => { res.status(200).send("User created successfully"); } catch (err) { - console.log(err); - res.status(500).send(err); + if (err.name == "SequelizeUniqueConstraintError") { + res.status(403).send("A user with this email already exists in the database"); + return; + } + res.status(500).send("Unexpected server error"); } }); @@ -71,15 +74,18 @@ router.post('/logout', (req, res) => { }); }); - +// This endpoint is to verify the users login status router.post('/test', (req, res) => { if (req.user) { if (req.user.is_admin) { res.send(`User ${req.user.username} is logged in as admin`); + return; } res.send(`User ${req.user} logged in, but not an admin`); + return; } res.send("user not logged in"); -}) + return; +}); module.exports = router; \ No newline at end of file From 79432b20ccbbab95e1ebb24bdf00fb0cc64dca98 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Sat, 4 Nov 2023 15:10:48 -0400 Subject: [PATCH 29/41] TCES-12 refactor(auth) update .env.example to remove credentials --- server/.env.example | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/.env.example b/server/.env.example index 94778dd7..b15dcdf6 100644 --- a/server/.env.example +++ b/server/.env.example @@ -1,8 +1,8 @@ # This will connect to the main branch of the db in the final changes # Rename this to .env and copy a dev branch url to here from PlanetScale DATABASE_NAME='blueprint-tces' -DATABASE_USERNAME='sl1r933z216gebrobmoy' -DATABASE_PASSWORD='pscale_pw_9QtSX4DdwRvnD5T0CsVZjABnMu862B4FJLCEaBd3BX8' +DATABASE_USERNAME='' +DATABASE_PASSWORD='' DATABASE_HOST='aws.connect.psdb.cloud' FRONTEND_URL='http://localhost:3000' USERS_TABLE='users-dev' \ No newline at end of file From fd9ac2c49e580e5ac93c59f152b33f08c8c699cf Mon Sep 17 00:00:00 2001 From: VangoCode Date: Sat, 4 Nov 2023 15:20:42 -0400 Subject: [PATCH 30/41] TCES-12 refactor(auth) update .env.example, index, and update routing --- server/.env.example | 3 ++- server/index.js | 4 ++-- server/src/routes/auth.js | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/server/.env.example b/server/.env.example index b15dcdf6..13fb636b 100644 --- a/server/.env.example +++ b/server/.env.example @@ -5,4 +5,5 @@ DATABASE_USERNAME='' DATABASE_PASSWORD='' DATABASE_HOST='aws.connect.psdb.cloud' FRONTEND_URL='http://localhost:3000' -USERS_TABLE='users-dev' \ No newline at end of file +USERS_TABLE='users-dev' +SESSION_SECRET= \ No newline at end of file diff --git a/server/index.js b/server/index.js index 64fbecd9..b8523ba9 100644 --- a/server/index.js +++ b/server/index.js @@ -22,7 +22,7 @@ const authRouter = require('./src/routes/auth'); // Set up session for authorization app.use(session({ - secret: 'blueprint-tces', + secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false, store: new SQLiteStore({ db: 'sessions.db', dir: './var/db' }) @@ -50,4 +50,4 @@ app.get("/users", (req, res) => { }); // All endpoints within this API will be found under the /auth subdirectory -app.use('/auth', authRouter); \ No newline at end of file +app.use('/', authRouter); \ No newline at end of file diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index a616d033..33799940 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -18,7 +18,7 @@ const crypto = require('crypto'); * @type string {body.username} * @type string {body.password} */ -router.post('/login/password', +router.post('/login', // auth middleware passport.authenticate('local', { successRedirect: `${process.env.FRONTEND_URL}/`, From d2888fc29a68e67c4b413fcc248d9f2f70f4f13c Mon Sep 17 00:00:00 2001 From: VangoCode Date: Sat, 4 Nov 2023 15:26:36 -0400 Subject: [PATCH 31/41] TCES-12 fix(auth) update model to match sql --- server/src/models/user.model.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/server/src/models/user.model.js b/server/src/models/user.model.js index 202effd7..a428a423 100644 --- a/server/src/models/user.model.js +++ b/server/src/models/user.model.js @@ -19,7 +19,8 @@ const User = sequelize.define(process.env.USERS_TABLE, { }, email: { type: DataTypes.STRING, - allowNull: false + allowNull: false, + unique: true }, password: { type: DataTypes.BLOB('tiny'), From 7714eeb80a0dbc183ecbf721b44b7e5d0bb17402 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Sat, 4 Nov 2023 15:44:58 -0400 Subject: [PATCH 32/41] TCES-12 refactor(auth) refactor all routes to use controller --- server/src/configs/sequelize.js | 6 +++ server/src/controllers/authController.js | 61 +++++++++++++++++++++++ server/src/routes/auth.js | 58 +++------------------ server/var/db/sessions.db | Bin 12288 -> 12288 bytes 4 files changed, 75 insertions(+), 50 deletions(-) create mode 100644 server/src/controllers/authController.js diff --git a/server/src/configs/sequelize.js b/server/src/configs/sequelize.js index d1635f1f..99c0f2fa 100644 --- a/server/src/configs/sequelize.js +++ b/server/src/configs/sequelize.js @@ -23,6 +23,12 @@ const sequelize = new Sequelize( }, ); +try { + sequelize.authenticate().then(() => { console.log('Connection has been established successfully.'); }); +} catch (error) { + console.error('Unable to connect to the database:', error); +} + module.exports = { sequelize: sequelize } \ No newline at end of file diff --git a/server/src/controllers/authController.js b/server/src/controllers/authController.js new file mode 100644 index 00000000..8f2681a5 --- /dev/null +++ b/server/src/controllers/authController.js @@ -0,0 +1,61 @@ +const User = require('../models/user.model'); +const crypto = require('crypto'); + +const createUserRequestHandler = async (req, res, next) => { + if (!req.user) { res.status(403).send("You are not logged in"); return; } + if (!req.user.is_admin) { res.status(403).send("Only an admin can create users"); return; } + + // If you reach here, the user is an admin + try { + // Generate salt value + const salt = crypto.randomBytes(16); + + // synchronous hashing function + const hashedPassword = crypto.pbkdf2Sync(req.body.password, salt, 310000, 32, 'sha256'); + + await User.create({ + first_name: req.body.first_name, + last_name: req.body.last_name, + email: req.body.email, + password: hashedPassword, + salt: salt + }); + + res.status(200).send("User created successfully"); + + } catch (err) { + if (err.name == "SequelizeUniqueConstraintError") { + res.status(403).send("A user with this email already exists in the database"); + return; + } + console.log(err); + res.status(500).send("Unexpected server error"); + } +} + +const logoutRequestHandler = (req, res, next) => { + req.logout((err) => { + if (err) { return next(err); } + res.redirect('/'); + }); +} + +const isLoggedInRequestHandler = (req, res) => { + if (req.user) { + if (req.user.is_admin) { + res.send(`User ${req.user.username} is logged in as admin`); + return; + } + res.send(`User ${req.user} logged in, but not an admin`); + return; + } + res.send("user not logged in"); + return; +} + + +module.exports = { + createUserRequestHandler, + logoutRequestHandler, + isLoggedInRequestHandler +} \ No newline at end of file diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 33799940..a4af5c88 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -1,13 +1,16 @@ const express = require('express'); const router = express.Router(); -const User = require('../models/user.model'); - // PassportJS imports for auth const passport = require('passport'); // Encryption library const crypto = require('crypto'); +const { + createUserRequestHandler, + logoutRequestHandler, + isLoggedInRequestHandler +} = require('../controllers/authController'); // User logs in with password @@ -35,57 +38,12 @@ router.post('/login', * @type string {body.email} * @type string {body.password} */ -router.post('/create_user', async (req, res, next) => { - if (!req.user) { res.status(403).send("You are not logged in"); return; } - if (!req.user.is_admin) { res.status(403).send("Only an admin can create users"); return; } - - // If you reach here, the user is an admin - try { - // Generate salt value - const salt = crypto.randomBytes(16); - - // synchronous hashing function - const hashedPassword = crypto.pbkdf2Sync(req.body.password, salt, 310000, 32, 'sha256'); - - await User.create({ - first_name: req.body.first_name, - last_name: req.body.last_name, - email: req.body.email, - password: hashedPassword, - salt: salt - }); - - res.status(200).send("User created successfully"); - - } catch (err) { - if (err.name == "SequelizeUniqueConstraintError") { - res.status(403).send("A user with this email already exists in the database"); - return; - } - res.status(500).send("Unexpected server error"); - } -}); +router.post('/create_user', createUserRequestHandler); // User logs out -router.post('/logout', (req, res) => { - req.logout((err) => { - if (err) { return next(err); } - res.redirect('/'); - }); -}); +router.post('/logout', logoutRequestHandler); // This endpoint is to verify the users login status -router.post('/test', (req, res) => { - if (req.user) { - if (req.user.is_admin) { - res.send(`User ${req.user.username} is logged in as admin`); - return; - } - res.send(`User ${req.user} logged in, but not an admin`); - return; - } - res.send("user not logged in"); - return; -}); +router.post('/is_logged_in', isLoggedInRequestHandler); module.exports = router; \ No newline at end of file diff --git a/server/var/db/sessions.db b/server/var/db/sessions.db index 052d6e6314319522927e0fc28d1a90baee1b0b09..46e56a62631a1dce46c40a631d7ebc82d39d2a8d 100644 GIT binary patch delta 96 zcmZojXh@hK&1gJP#+lK0W5P{2^+2<9XEUeb%DfySCo`AGL`y@X>@+uvfbvMk_;Qy( WQ>Thu{I5bkY)+7`7f>Xmmg1r!M>W&!~IejjoG From 00e162eb5bd01c1db620def1083bdaa0fe05660e Mon Sep 17 00:00:00 2001 From: VangoCode Date: Sat, 4 Nov 2023 15:50:04 -0400 Subject: [PATCH 33/41] TCES-12 refactor(auth) refactor all controllers to be separate files --- .../{authController.js => auth/createUser.js} | 29 ++----------------- server/src/controllers/auth/isLoggedIn.js | 15 ++++++++++ server/src/controllers/auth/logout.js | 8 +++++ server/src/routes/auth.js | 9 +++--- 4 files changed, 29 insertions(+), 32 deletions(-) rename server/src/controllers/{authController.js => auth/createUser.js} (61%) create mode 100644 server/src/controllers/auth/isLoggedIn.js create mode 100644 server/src/controllers/auth/logout.js diff --git a/server/src/controllers/authController.js b/server/src/controllers/auth/createUser.js similarity index 61% rename from server/src/controllers/authController.js rename to server/src/controllers/auth/createUser.js index 8f2681a5..2c619f20 100644 --- a/server/src/controllers/authController.js +++ b/server/src/controllers/auth/createUser.js @@ -1,4 +1,4 @@ -const User = require('../models/user.model'); +const User = require('../../models/user.model'); const crypto = require('crypto'); const createUserRequestHandler = async (req, res, next) => { @@ -33,29 +33,4 @@ const createUserRequestHandler = async (req, res, next) => { } } -const logoutRequestHandler = (req, res, next) => { - req.logout((err) => { - if (err) { return next(err); } - res.redirect('/'); - }); -} - -const isLoggedInRequestHandler = (req, res) => { - if (req.user) { - if (req.user.is_admin) { - res.send(`User ${req.user.username} is logged in as admin`); - return; - } - res.send(`User ${req.user} logged in, but not an admin`); - return; - } - res.send("user not logged in"); - return; -} - - -module.exports = { - createUserRequestHandler, - logoutRequestHandler, - isLoggedInRequestHandler -} \ No newline at end of file +module.exports = createUserRequestHandler; \ No newline at end of file diff --git a/server/src/controllers/auth/isLoggedIn.js b/server/src/controllers/auth/isLoggedIn.js new file mode 100644 index 00000000..16102ed0 --- /dev/null +++ b/server/src/controllers/auth/isLoggedIn.js @@ -0,0 +1,15 @@ +const isLoggedInRequestHandler = (req, res) => { + if (req.user) { + if (req.user.is_admin) { + res.send(`User ${req.user.username} is logged in as admin`); + return; + } + res.send(`User ${req.user} logged in, but not an admin`); + return; + } + res.send("user not logged in"); + return; +} + + +module.exports = isLoggedInRequestHandler; \ No newline at end of file diff --git a/server/src/controllers/auth/logout.js b/server/src/controllers/auth/logout.js new file mode 100644 index 00000000..90b1a074 --- /dev/null +++ b/server/src/controllers/auth/logout.js @@ -0,0 +1,8 @@ +const logoutRequestHandler = (req, res, next) => { + req.logout((err) => { + if (err) { return next(err); } + res.redirect('/'); + }); +} + +module.exports = logoutRequestHandler; \ No newline at end of file diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index a4af5c88..2be577ee 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -6,11 +6,10 @@ const router = express.Router(); const passport = require('passport'); // Encryption library const crypto = require('crypto'); -const { - createUserRequestHandler, - logoutRequestHandler, - isLoggedInRequestHandler -} = require('../controllers/authController'); + +const createUserRequestHandler = require('../controllers/auth/createUser'); +const logoutRequestHandler = require('../controllers/auth/logout'); +const isLoggedInRequestHandler = require('../controllers/auth/isLoggedIn'); // User logs in with password From 1fec3a2fb77d25728fbfa7b7a6b545d9ce6bbdc8 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Sat, 4 Nov 2023 17:07:20 -0400 Subject: [PATCH 34/41] TCES-12 refactor(auth) refactor after formatter and linter --- server/index.js | 26 ++++--- server/package-lock.json | 52 +++---------- server/package.json | 3 +- server/src/configs/passport.js | 82 +++++++++++--------- server/src/configs/sequelize.js | 64 ++++++++------- server/src/controllers/auth/createUser.js | 85 +++++++++++--------- server/src/controllers/auth/isLoggedIn.js | 29 ++++--- server/src/controllers/auth/logout.js | 18 +++-- server/src/models/user.model.js | 79 ++++++++++--------- server/src/routes/auth.js | 94 +++++++++++------------ 10 files changed, 259 insertions(+), 273 deletions(-) diff --git a/server/index.js b/server/index.js index b8523ba9..a3bac672 100644 --- a/server/index.js +++ b/server/index.js @@ -7,9 +7,9 @@ const mysql = require("mysql2"); const connection = mysql.createConnection(process.env.DATABASE_URL); // Session storage imports -const passport = require('passport'); -var session = require('express-session'); -var SQLiteStore = require('connect-sqlite3')(session); +const passport = require("passport"); +var session = require("express-session"); +var SQLiteStore = require("connect-sqlite3")(session); // Import passport configuration require("./src/configs/passport"); @@ -18,16 +18,18 @@ require("./src/configs/passport"); app.use(express.json()); // Import router for all authentication API endpoints -const authRouter = require('./src/routes/auth'); +const authRouter = require("./src/routes/auth"); // Set up session for authorization -app.use(session({ - secret: process.env.SESSION_SECRET, - resave: false, - saveUninitialized: false, - store: new SQLiteStore({ db: 'sessions.db', dir: './var/db' }) -})); -app.use(passport.authenticate('session')); +app.use( + session({ + secret: process.env.SESSION_SECRET, + resave: false, + saveUninitialized: false, + store: new SQLiteStore({ db: "sessions.db", dir: "./var/db" }), + }), +); +app.use(passport.authenticate("session")); app.get("/", (req, res) => { res.send("Helloooo World!"); @@ -50,4 +52,4 @@ app.get("/users", (req, res) => { }); // All endpoints within this API will be found under the /auth subdirectory -app.use('/', authRouter); \ No newline at end of file +app.use("/", authRouter); diff --git a/server/package-lock.json b/server/package-lock.json index 0271a0cf..4bca1b01 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -10,6 +10,7 @@ "license": "MIT", "dependencies": { "connect-sqlite3": "^0.9.13", + "crypto": "^1.0.1", "dotenv": "^16.3.1", "eslint": "^8.52.0", "express": "^4.18.2", @@ -629,7 +630,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, "engines": { "node": ">=8" } @@ -877,7 +877,6 @@ }, "node_modules/balanced-match": { "version": "1.0.2", - "dev": true, "license": "MIT" }, "node_modules/base64-js": { @@ -1219,14 +1218,6 @@ "color-support": "bin.js" } }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "bin": { - "color-support": "bin.js" - } - }, "node_modules/colorette": { "version": "2.0.20", "dev": true, @@ -1235,8 +1226,7 @@ "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, "node_modules/confusing-browser-globals": { "version": "1.0.11", @@ -1302,6 +1292,12 @@ "node": ">= 8" } }, + "node_modules/crypto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", + "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==", + "deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in." + }, "node_modules/damerau-levenshtein": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/damerau-levenshtein/-/damerau-levenshtein-1.0.8.tgz", @@ -2611,7 +2607,6 @@ }, "node_modules/fs.realpath": { "version": "1.0.0", - "dev": true, "license": "ISC" }, "node_modules/fsevents": { @@ -3099,7 +3094,7 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, + "devOptional": true, "engines": { "node": ">=0.8.19" } @@ -3129,7 +3124,6 @@ }, "node_modules/inflight": { "version": "1.0.6", - "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", @@ -3582,7 +3576,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "devOptional": true }, "node_modules/iterator.prototype": { "version": "1.1.2", @@ -4374,7 +4368,6 @@ "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -4513,7 +4506,6 @@ }, "node_modules/once": { "version": "1.4.0", - "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -4640,21 +4632,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-map": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", - "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "optional": true, - "dependencies": { - "aggregate-error": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -4723,7 +4700,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, "engines": { "node": ">=0.10.0" } @@ -5203,7 +5179,6 @@ "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, "dependencies": { "glob": "^7.1.3" }, @@ -5218,7 +5193,6 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -5228,7 +5202,6 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -5248,7 +5221,6 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -5938,7 +5910,6 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -6578,7 +6549,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, + "devOptional": true, "dependencies": { "isexe": "^2.0.0" }, @@ -6698,7 +6669,6 @@ }, "node_modules/wrappy": { "version": "1.0.2", - "dev": true, "license": "ISC" }, "node_modules/yallist": { diff --git a/server/package.json b/server/package.json index fb46e4d7..5c8f3c65 100644 --- a/server/package.json +++ b/server/package.json @@ -12,6 +12,7 @@ "license": "MIT", "dependencies": { "connect-sqlite3": "^0.9.13", + "crypto": "^1.0.1", "dotenv": "^16.3.1", "eslint": "^8.52.0", "express": "^4.18.2", @@ -33,8 +34,8 @@ "eslint-plugin-prettier": "^5.0.1", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", - "prettier": "3.0.3", "pino-pretty": "^10.2.3", + "prettier": "3.0.3", "vitest": "^0.34.6" } } diff --git a/server/src/configs/passport.js b/server/src/configs/passport.js index b3c8eb13..9007dd6e 100644 --- a/server/src/configs/passport.js +++ b/server/src/configs/passport.js @@ -1,38 +1,44 @@ -require('dotenv').config(); - -const passport = require('passport'); -const LocalStrategy = require('passport-local'); - -const mysql = require("mysql2"); -const connection = mysql.createConnection(process.env.DATABASE_URL); -const User = require('../models/user.model') - -const crypto = require('crypto'); - -// Local strategy configuration -passport.use(new LocalStrategy(async (username, password, cb) => { - const user = await User.findOne({ where: { email: username } }); - if (user === null) { - return cb(null, false, { message: 'Incorrect username or password.' }); - } - - const hashedPassword = crypto.pbkdf2Sync(password, user.salt, 310000, 32, 'sha256'); - - if (!crypto.timingSafeEqual(user.password, hashedPassword)) { - return cb(null, false, { message: 'Incorrect username or password.' }); - } - - return cb(null, user); -})); - -// Set up serialization and deserialization for the user's session -passport.serializeUser((user, cb) => { - process.nextTick(() => { - cb(null, { id: user.id, username: user.email, is_admin: user.is_admin }); - }); -}); -passport.deserializeUser((user, cb) => { - process.nextTick(() => { - return cb(null, user); - }); -}); \ No newline at end of file +require("dotenv").config(); + +const passport = require("passport"); +const LocalStrategy = require("passport-local"); + +const crypto = require("crypto"); + +const User = require("../models/user.model"); + +// Local strategy configuration +passport.use( + new LocalStrategy(async (username, password, cb) => { + const user = await User.findOne({ where: { email: username } }); + if (user === null) { + return cb(null, false, { message: "Incorrect username or password." }); + } + + const hashedPassword = crypto.pbkdf2Sync( + password, + user.salt, + 310000, + 32, + "sha256", + ); + + if (!crypto.timingSafeEqual(user.password, hashedPassword)) { + return cb(null, false, { message: "Incorrect username or password." }); + } + + return cb(null, user); + }), +); + +// Set up serialization and deserialization for the user's session +passport.serializeUser((user, cb) => { + process.nextTick(() => { + cb(null, { id: user.id, username: user.email, is_admin: user.is_admin }); + }); +}); +passport.deserializeUser((user, cb) => { + process.nextTick(() => { + return cb(null, user); + }); +}); diff --git a/server/src/configs/sequelize.js b/server/src/configs/sequelize.js index 99c0f2fa..7158595b 100644 --- a/server/src/configs/sequelize.js +++ b/server/src/configs/sequelize.js @@ -1,34 +1,30 @@ -require('dotenv').config(); -const { Sequelize } = require('sequelize'); - -const sequelize = new Sequelize( - process.env.DATABASE_NAME, - process.env.DATABASE_USERNAME, - process.env.DATABASE_PASSWORD, - { - host: process.env.DATABASE_HOST, - dialect: 'mysql', - dialectOptions: { - ssl: { - rejectUnauthorized: true - }, - }, - define: { - defaultScope: { - attributes: { exclude: ['createdAt', 'updatedAt'] } - }, - timestamps: false, - freezeTableName: true - } - }, -); - -try { - sequelize.authenticate().then(() => { console.log('Connection has been established successfully.'); }); -} catch (error) { - console.error('Unable to connect to the database:', error); -} - -module.exports = { - sequelize: sequelize -} \ No newline at end of file +require("dotenv").config(); +const { Sequelize } = require("sequelize"); + +const sequelize = new Sequelize( + process.env.DATABASE_NAME, + process.env.DATABASE_USERNAME, + process.env.DATABASE_PASSWORD, + { + host: process.env.DATABASE_HOST, + dialect: "mysql", + dialectOptions: { + ssl: { + rejectUnauthorized: true, + }, + }, + define: { + defaultScope: { + attributes: { exclude: ["createdAt", "updatedAt"] }, + }, + timestamps: false, + freezeTableName: true, + }, + }, +); + +sequelize.authenticate(); + +module.exports = { + sequelize, +}; diff --git a/server/src/controllers/auth/createUser.js b/server/src/controllers/auth/createUser.js index 2c619f20..5ea1015b 100644 --- a/server/src/controllers/auth/createUser.js +++ b/server/src/controllers/auth/createUser.js @@ -1,36 +1,49 @@ -const User = require('../../models/user.model'); -const crypto = require('crypto'); - -const createUserRequestHandler = async (req, res, next) => { - if (!req.user) { res.status(403).send("You are not logged in"); return; } - if (!req.user.is_admin) { res.status(403).send("Only an admin can create users"); return; } - - // If you reach here, the user is an admin - try { - // Generate salt value - const salt = crypto.randomBytes(16); - - // synchronous hashing function - const hashedPassword = crypto.pbkdf2Sync(req.body.password, salt, 310000, 32, 'sha256'); - - await User.create({ - first_name: req.body.first_name, - last_name: req.body.last_name, - email: req.body.email, - password: hashedPassword, - salt: salt - }); - - res.status(200).send("User created successfully"); - - } catch (err) { - if (err.name == "SequelizeUniqueConstraintError") { - res.status(403).send("A user with this email already exists in the database"); - return; - } - console.log(err); - res.status(500).send("Unexpected server error"); - } -} - -module.exports = createUserRequestHandler; \ No newline at end of file +const User = require("../../models/user.model"); +const crypto = require("crypto"); + +const createUserRequestHandler = async (req, res, next) => { + if (!req.user) { + res.status(403).send("You are not logged in"); + return; + } + if (!req.user.is_admin) { + res.status(403).send("Only an admin can create users"); + return; + } + + // If you reach here, the user is an admin + try { + // Generate salt value + const salt = crypto.randomBytes(16); + + // synchronous hashing function + const hashedPassword = crypto.pbkdf2Sync( + req.body.password, + salt, + 310000, + 32, + "sha256", + ); + + await User.create({ + first_name: req.body.first_name, + last_name: req.body.last_name, + email: req.body.email, + password: hashedPassword, + salt: salt, + }); + + res.status(200).send("User created successfully"); + } catch (err) { + if (err.name == "SequelizeUniqueConstraintError") { + res + .status(403) + .send("A user with this email already exists in the database"); + return; + } + console.log(err); + res.status(500).send("Unexpected server error"); + } +}; + +module.exports = createUserRequestHandler; diff --git a/server/src/controllers/auth/isLoggedIn.js b/server/src/controllers/auth/isLoggedIn.js index 16102ed0..6a620be9 100644 --- a/server/src/controllers/auth/isLoggedIn.js +++ b/server/src/controllers/auth/isLoggedIn.js @@ -1,15 +1,14 @@ -const isLoggedInRequestHandler = (req, res) => { - if (req.user) { - if (req.user.is_admin) { - res.send(`User ${req.user.username} is logged in as admin`); - return; - } - res.send(`User ${req.user} logged in, but not an admin`); - return; - } - res.send("user not logged in"); - return; -} - - -module.exports = isLoggedInRequestHandler; \ No newline at end of file +const isLoggedInRequestHandler = (req, res) => { + if (req.user) { + if (req.user.is_admin) { + res.send(`User ${req.user.username} is logged in as admin`); + return; + } + res.send(`User ${req.user} logged in, but not an admin`); + return; + } + res.send("user not logged in"); + return; +}; + +module.exports = isLoggedInRequestHandler; diff --git a/server/src/controllers/auth/logout.js b/server/src/controllers/auth/logout.js index 90b1a074..4b824627 100644 --- a/server/src/controllers/auth/logout.js +++ b/server/src/controllers/auth/logout.js @@ -1,8 +1,10 @@ -const logoutRequestHandler = (req, res, next) => { - req.logout((err) => { - if (err) { return next(err); } - res.redirect('/'); - }); -} - -module.exports = logoutRequestHandler; \ No newline at end of file +const logoutRequestHandler = (req, res, next) => { + req.logout((err) => { + if (err) { + return next(err); + } + res.redirect("/"); + }); +}; + +module.exports = logoutRequestHandler; diff --git a/server/src/models/user.model.js b/server/src/models/user.model.js index a428a423..80cdfc85 100644 --- a/server/src/models/user.model.js +++ b/server/src/models/user.model.js @@ -1,40 +1,39 @@ -require("dotenv").config(); -const { DataTypes } = require("sequelize"); -const { sequelize } = require('../configs/sequelize'); - - -const User = sequelize.define(process.env.USERS_TABLE, { - id: { - type: DataTypes.INTEGER, - autoIncrement: true, - primaryKey: true - }, - first_name: { - type: DataTypes.STRING, - allowNull: false - }, - last_name: { - type: DataTypes.STRING, - allowNull: false - }, - email: { - type: DataTypes.STRING, - allowNull: false, - unique: true - }, - password: { - type: DataTypes.BLOB('tiny'), - allowNull: false - }, - salt: { - type: DataTypes.BLOB('tiny'), - allowNull: false - }, - is_admin: { - type: DataTypes.BOOLEAN, - allowNull: false, - defaultValue: 0 - } -}); - -module.exports = User; \ No newline at end of file +require("dotenv").config(); +const { DataTypes } = require("sequelize"); +const { sequelize } = require("../configs/sequelize"); + +const User = sequelize.define(process.env.USERS_TABLE, { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + }, + first_name: { + type: DataTypes.STRING, + allowNull: false, + }, + last_name: { + type: DataTypes.STRING, + allowNull: false, + }, + email: { + type: DataTypes.STRING, + allowNull: false, + unique: true, + }, + password: { + type: DataTypes.BLOB("tiny"), + allowNull: false, + }, + salt: { + type: DataTypes.BLOB("tiny"), + allowNull: false, + }, + is_admin: { + type: DataTypes.BOOLEAN, + allowNull: false, + defaultValue: 0, + }, +}); + +module.exports = User; diff --git a/server/src/routes/auth.js b/server/src/routes/auth.js index 2be577ee..03d8c85f 100644 --- a/server/src/routes/auth.js +++ b/server/src/routes/auth.js @@ -1,48 +1,46 @@ -const express = require('express'); -const router = express.Router(); - - -// PassportJS imports for auth -const passport = require('passport'); -// Encryption library -const crypto = require('crypto'); - -const createUserRequestHandler = require('../controllers/auth/createUser'); -const logoutRequestHandler = require('../controllers/auth/logout'); -const isLoggedInRequestHandler = require('../controllers/auth/isLoggedIn'); - - -// User logs in with password -/** - * Note: you MUST use `username` as the JSON body key or else this will not work! - * - * Expected body parameters: - * @type string {body.username} - * @type string {body.password} - */ -router.post('/login', - // auth middleware - passport.authenticate('local', { - successRedirect: `${process.env.FRONTEND_URL}/`, - failureRedirect: `${process.env.FRONTEND_URL}/login` - }) -); - -// Admin creates a user -// TODO: add permission handling to ensure the user is signed in as the admin -/** - * Expected body parameters: - * @type string {body.first_name} - * @type string {body.last_name} - * @type string {body.email} - * @type string {body.password} - */ -router.post('/create_user', createUserRequestHandler); - -// User logs out -router.post('/logout', logoutRequestHandler); - -// This endpoint is to verify the users login status -router.post('/is_logged_in', isLoggedInRequestHandler); - -module.exports = router; \ No newline at end of file +const express = require("express"); + +const router = express.Router(); + +// PassportJS imports for auth +const passport = require("passport"); + +const createUserRequestHandler = require("../controllers/auth/createUser"); +const logoutRequestHandler = require("../controllers/auth/logout"); +const isLoggedInRequestHandler = require("../controllers/auth/isLoggedIn"); + +// User logs in with password +/** + * Note: you MUST use `username` as the JSON body key or else this will not work! + * + * Expected body parameters: + * @type string {body.username} + * @type string {body.password} + */ +router.post( + "/login", + // auth middleware + passport.authenticate("local", { + successRedirect: `${process.env.FRONTEND_URL}/`, + failureRedirect: `${process.env.FRONTEND_URL}/login`, + }), +); + +// Admin creates a user +// TODO: add permission handling to ensure the user is signed in as the admin +/** + * Expected body parameters: + * @type string {body.first_name} + * @type string {body.last_name} + * @type string {body.email} + * @type string {body.password} + */ +router.post("/create_user", createUserRequestHandler); + +// User logs out +router.post("/logout", logoutRequestHandler); + +// This endpoint is to verify the users login status +router.post("/is_logged_in", isLoggedInRequestHandler); + +module.exports = router; From d6d2d94ea626bd955e7f8457fd3e71334eb9968b Mon Sep 17 00:00:00 2001 From: VangoCode Date: Sun, 5 Nov 2023 12:20:47 -0500 Subject: [PATCH 35/41] TCES-12 test(auth) add test cases for createUser --- .../test/controllers/auth/createUser.test.js | 28 ++++++++++++++++++ server/var/db/sessions.db | Bin 12288 -> 12288 bytes 2 files changed, 28 insertions(+) create mode 100644 server/test/controllers/auth/createUser.test.js diff --git a/server/test/controllers/auth/createUser.test.js b/server/test/controllers/auth/createUser.test.js new file mode 100644 index 00000000..a95db9ca --- /dev/null +++ b/server/test/controllers/auth/createUser.test.js @@ -0,0 +1,28 @@ +import { expect, vi, describe, it } from "vitest"; +import createUserRequestHandler from "../../../src/controllers/auth/createUser"; + +describe('createUser test suite', () => { + it('should respond with a 403 if you are not logged in', async () => { + const mockReq = { }; + const mockRes = { + status: (code) => { mockRes.statusCode = code; return { send: (message) => { return ; } } }, + statusCode: 0 + }; + const mockNext = vi.fn(); + + await createUserRequestHandler(mockReq, mockRes, mockNext); + expect(mockRes.statusCode).toBe(403); + }); + + it('should respond with a 403 if you are not an admin', async () => { + const mockReq = { user: { is_admin: false } }; + const mockRes = { + status: (code) => { mockRes.statusCode = code; return { send: (message) => { return ; } } }, + statusCode: 0 + }; + const mockNext = vi.fn(); + + await createUserRequestHandler(mockReq, mockRes, mockNext); + expect(mockRes.statusCode).toBe(403); + }); +}); \ No newline at end of file diff --git a/server/var/db/sessions.db b/server/var/db/sessions.db index 46e56a62631a1dce46c40a631d7ebc82d39d2a8d..6f668b91f6d74976cc0aebfddacff50841c7bc93 100644 GIT binary patch delta 171 zcmZojXh@hK&1gAM#+lJ_W5P0imR1J-*3E(nLj03u Date: Sun, 5 Nov 2023 12:25:21 -0500 Subject: [PATCH 36/41] TCES-12 refactor(auth_test) refactor test cases for auth to match formatter and linter --- .../test/controllers/auth/createUser.test.js | 70 +++++++++++-------- 1 file changed, 42 insertions(+), 28 deletions(-) diff --git a/server/test/controllers/auth/createUser.test.js b/server/test/controllers/auth/createUser.test.js index a95db9ca..13387566 100644 --- a/server/test/controllers/auth/createUser.test.js +++ b/server/test/controllers/auth/createUser.test.js @@ -1,28 +1,42 @@ -import { expect, vi, describe, it } from "vitest"; -import createUserRequestHandler from "../../../src/controllers/auth/createUser"; - -describe('createUser test suite', () => { - it('should respond with a 403 if you are not logged in', async () => { - const mockReq = { }; - const mockRes = { - status: (code) => { mockRes.statusCode = code; return { send: (message) => { return ; } } }, - statusCode: 0 - }; - const mockNext = vi.fn(); - - await createUserRequestHandler(mockReq, mockRes, mockNext); - expect(mockRes.statusCode).toBe(403); - }); - - it('should respond with a 403 if you are not an admin', async () => { - const mockReq = { user: { is_admin: false } }; - const mockRes = { - status: (code) => { mockRes.statusCode = code; return { send: (message) => { return ; } } }, - statusCode: 0 - }; - const mockNext = vi.fn(); - - await createUserRequestHandler(mockReq, mockRes, mockNext); - expect(mockRes.statusCode).toBe(403); - }); -}); \ No newline at end of file +import { expect, vi, describe, it } from "vitest"; +import createUserRequestHandler from "../../../src/controllers/auth/createUser"; + +describe("createUser test suite", () => { + it("should respond with a 403 if you are not logged in", async () => { + const mockReq = {}; + const mockRes = { + status: (code) => { + mockRes.statusCode = code; + return { + send: (message) => { + return; + }, + }; + }, + statusCode: 0, + }; + const mockNext = vi.fn(); + + await createUserRequestHandler(mockReq, mockRes, mockNext); + expect(mockRes.statusCode).toBe(403); + }); + + it("should respond with a 403 if you are not an admin", async () => { + const mockReq = { user: { is_admin: false } }; + const mockRes = { + status: (code) => { + mockRes.statusCode = code; + return { + send: (message) => { + return; + }, + }; + }, + statusCode: 0, + }; + const mockNext = vi.fn(); + + await createUserRequestHandler(mockReq, mockRes, mockNext); + expect(mockRes.statusCode).toBe(403); + }); +}); From 1dfa3937b72286be84cdebd8498c25979875e560 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Sun, 5 Nov 2023 12:45:54 -0500 Subject: [PATCH 37/41] TCES-12 hotfix(auth_test) fix sequelize connection failure to pass tests --- server/src/configs/sequelize.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/src/configs/sequelize.js b/server/src/configs/sequelize.js index 7158595b..d990ec16 100644 --- a/server/src/configs/sequelize.js +++ b/server/src/configs/sequelize.js @@ -23,7 +23,11 @@ const sequelize = new Sequelize( }, ); -sequelize.authenticate(); +try { + sequelize.authenticate(); +} catch { + console.log("Sequelize could not connect"); +} module.exports = { sequelize, From dc9e79db96df7192a5878d5a42cb83d3f1e510e9 Mon Sep 17 00:00:00 2001 From: VangoCode Date: Sun, 5 Nov 2023 15:38:26 -0500 Subject: [PATCH 38/41] TCES-12 hotfix(auth_test) fix sequelize connection failure to pass tests --- server/src/configs/sequelize.js | 46 ++++++++++++++++---------------- server/var/db/sessions.db | Bin 12288 -> 12288 bytes 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/server/src/configs/sequelize.js b/server/src/configs/sequelize.js index d990ec16..996b6029 100644 --- a/server/src/configs/sequelize.js +++ b/server/src/configs/sequelize.js @@ -1,34 +1,34 @@ require("dotenv").config(); const { Sequelize } = require("sequelize"); -const sequelize = new Sequelize( - process.env.DATABASE_NAME, - process.env.DATABASE_USERNAME, - process.env.DATABASE_PASSWORD, - { - host: process.env.DATABASE_HOST, - dialect: "mysql", - dialectOptions: { - ssl: { - rejectUnauthorized: true, +try { + const sequelize = new Sequelize( + process.env.DATABASE_NAME, + process.env.DATABASE_USERNAME, + process.env.DATABASE_PASSWORD, + { + host: process.env.DATABASE_HOST, + dialect: "mysql", + dialectOptions: { + ssl: { + rejectUnauthorized: true, + }, }, - }, - define: { - defaultScope: { - attributes: { exclude: ["createdAt", "updatedAt"] }, + define: { + defaultScope: { + attributes: { exclude: ["createdAt", "updatedAt"] }, + }, + timestamps: false, + freezeTableName: true, }, - timestamps: false, - freezeTableName: true, }, - }, -); + ); -try { sequelize.authenticate(); + + module.exports = { + sequelize, + }; } catch { console.log("Sequelize could not connect"); } - -module.exports = { - sequelize, -}; diff --git a/server/var/db/sessions.db b/server/var/db/sessions.db index 6f668b91f6d74976cc0aebfddacff50841c7bc93..8568c6193fde4976568b0948fcc908857c7931fa 100644 GIT binary patch delta 228 zcmZojXh@hK&1gSS#+lK6W5P0i7DEPp!_9&ULj03uwssYM__ZZNqYbQ delta 206 zcmZojXh@hK&1gAM#+lJ_W5P0imR1J-*3E(nLj03u@ury9Am#RqWz_75ZUvg1ne5P*0aHd!r*v4P`0oIn Ra*BUq0Edb)vo9whGXT+ZJ=XvL From c349499ec8966443bc05b5dda1a617005a0d79da Mon Sep 17 00:00:00 2001 From: VangoCode Date: Sun, 5 Nov 2023 15:44:32 -0500 Subject: [PATCH 39/41] TCES-12 hotfix(auth_test) fix sequelize connection failure to pass tests --- server/src/configs/sequelize.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/server/src/configs/sequelize.js b/server/src/configs/sequelize.js index 996b6029..b80f04c5 100644 --- a/server/src/configs/sequelize.js +++ b/server/src/configs/sequelize.js @@ -24,11 +24,13 @@ try { }, ); - sequelize.authenticate(); + sequelize.authenticate().catch(() => { + console.error("Error connecting to database"); + }); module.exports = { sequelize, }; } catch { - console.log("Sequelize could not connect"); + console.error("Sequelize could not connect"); } From 8d8862134037fdcbfc1198466cbfeb445745a6ec Mon Sep 17 00:00:00 2001 From: Jordan Janakievski Date: Sun, 5 Nov 2023 16:27:09 -0500 Subject: [PATCH 40/41] Create a .env when running the server tests --- ...Checks.yml => automatedPrClientChecks.yml} | 0 ...PrLint.yml => automatedPrServerChecks.yml} | 3 ++ server/src/configs/sequelize.js | 53 +++++++++---------- 3 files changed, 28 insertions(+), 28 deletions(-) rename .github/workflows/{automatedPrChecks.yml => automatedPrClientChecks.yml} (100%) rename .github/workflows/{automatedPrLint.yml => automatedPrServerChecks.yml} (81%) diff --git a/.github/workflows/automatedPrChecks.yml b/.github/workflows/automatedPrClientChecks.yml similarity index 100% rename from .github/workflows/automatedPrChecks.yml rename to .github/workflows/automatedPrClientChecks.yml diff --git a/.github/workflows/automatedPrLint.yml b/.github/workflows/automatedPrServerChecks.yml similarity index 81% rename from .github/workflows/automatedPrLint.yml rename to .github/workflows/automatedPrServerChecks.yml index b5733aff..53dc70d8 100644 --- a/.github/workflows/automatedPrLint.yml +++ b/.github/workflows/automatedPrServerChecks.yml @@ -11,6 +11,9 @@ jobs: steps: - name: Checkout code uses: actions/checkout@v2 + env: + DATABASE_USERNAME: ${{ secrets.DATABASE_USERNAME }} + DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }} - name: Set up Node.js uses: actions/setup-node@v2 diff --git a/server/src/configs/sequelize.js b/server/src/configs/sequelize.js index b80f04c5..f92628f6 100644 --- a/server/src/configs/sequelize.js +++ b/server/src/configs/sequelize.js @@ -1,36 +1,33 @@ require("dotenv").config(); const { Sequelize } = require("sequelize"); -try { - const sequelize = new Sequelize( - process.env.DATABASE_NAME, - process.env.DATABASE_USERNAME, - process.env.DATABASE_PASSWORD, - { - host: process.env.DATABASE_HOST, - dialect: "mysql", - dialectOptions: { - ssl: { - rejectUnauthorized: true, - }, + +const sequelize = new Sequelize( + process.env.DATABASE_NAME, + process.env.DATABASE_USERNAME, + process.env.DATABASE_PASSWORD, + { + host: process.env.DATABASE_HOST, + dialect: "mysql", + dialectOptions: { + ssl: { + rejectUnauthorized: true, }, - define: { - defaultScope: { - attributes: { exclude: ["createdAt", "updatedAt"] }, - }, - timestamps: false, - freezeTableName: true, + }, + define: { + defaultScope: { + attributes: { exclude: ["createdAt", "updatedAt"] }, }, + timestamps: false, + freezeTableName: true, }, - ); + }, +); - sequelize.authenticate().catch(() => { - console.error("Error connecting to database"); - }); +sequelize.authenticate().catch(() => { + console.error("Error connecting to database"); +}); - module.exports = { - sequelize, - }; -} catch { - console.error("Sequelize could not connect"); -} +module.exports = { + sequelize, +}; \ No newline at end of file From 013b59e2419f0a966e3a75d2e587c3bcf25eb54d Mon Sep 17 00:00:00 2001 From: Jordan Janakievski Date: Sun, 5 Nov 2023 16:50:42 -0500 Subject: [PATCH 41/41] Linter error changes --- server/src/configs/sequelize.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/configs/sequelize.js b/server/src/configs/sequelize.js index f92628f6..94e50a3b 100644 --- a/server/src/configs/sequelize.js +++ b/server/src/configs/sequelize.js @@ -1,6 +1,6 @@ require("dotenv").config(); const { Sequelize } = require("sequelize"); - +const logger = require("../middlewares/logger/pino"); const sequelize = new Sequelize( process.env.DATABASE_NAME, @@ -25,9 +25,9 @@ const sequelize = new Sequelize( ); sequelize.authenticate().catch(() => { - console.error("Error connecting to database"); + logger.error("Unable to connect to the database"); }); module.exports = { sequelize, -}; \ No newline at end of file +};