From 82c6b81d31bef11b2bec675ef15d3f5db1d8e582 Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Tue, 9 Nov 2021 14:06:47 -0800 Subject: [PATCH 01/18] added config folder/file for environment vars --- config/index.js | 3 +++ index.js | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 config/index.js diff --git a/config/index.js b/config/index.js new file mode 100644 index 000000000..576df0efe --- /dev/null +++ b/config/index.js @@ -0,0 +1,3 @@ +module.exports = { + PORT: process.env.PORT || 9000 +} diff --git a/index.js b/index.js index 71f14885b..2cfe428e2 100644 --- a/index.js +++ b/index.js @@ -1,6 +1,6 @@ -const server = require('./api/server.js'); +const { PORT } = require("./config"); -const PORT = process.env.PORT || 9000; +const server = require('./api/server.js'); server.listen(PORT, () => { console.log(`Listening on port ${PORT}...`); From 31cf6870dca977a748cf35d0176fb1ad14eae623 Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Tue, 9 Nov 2021 14:45:48 -0800 Subject: [PATCH 02/18] filled out users-model.js --- api/users/users-model.js | 45 +++++++++++++++++++++++++++++++--------- 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/api/users/users-model.js b/api/users/users-model.js index 7a2064834..95b9a9bce 100644 --- a/api/users/users-model.js +++ b/api/users/users-model.js @@ -18,6 +18,13 @@ function find() { } ] */ + const users = db("users as u") + .leftJoin("roles as r", + "u.role_id", "r.role_id") + .select("u.user_id", + "u.username", + "r.role_name"); + return users; } function findBy(filter) { @@ -34,6 +41,15 @@ function findBy(filter) { } ] */ + const filteredUsers = db("user as u") + .leftJoin("roles as r", + "u.role_id", "r.role_id") + .select("u.user_id", + "u.username", + "u.password", + "r.role_name") + .where(filter); + return filteredUsers; } function findById(user_id) { @@ -47,6 +63,15 @@ function findById(user_id) { "role_name": "instructor" } */ + const user = db("user as u") + .leftJoin("roles as r", + "u.role_id", "r.role_id") + .select("u.user_id", + "u.username", + "r.role_name") + .where({ user_id }) + .first(); + return user; } /** @@ -68,20 +93,20 @@ function findById(user_id) { } */ async function add({ username, password, role_name }) { // done for you - let created_user_id + let created_user_id; await db.transaction(async trx => { - let role_id_to_use - const [role] = await trx('roles').where('role_name', role_name) + let role_id_to_use; + const [role] = await trx('roles').where('role_name', role_name); if (role) { - role_id_to_use = role.role_id + role_id_to_use = role.role_id; } else { - const [role_id] = await trx('roles').insert({ role_name: role_name }) - role_id_to_use = role_id + const [role_id] = await trx('roles').insert({ role_name: role_name }); + role_id_to_use = role_id; } - const [user_id] = await trx('users').insert({ username, password, role_id: role_id_to_use }) - created_user_id = user_id - }) - return findById(created_user_id) + const [user_id] = await trx('users').insert({ username, password, role_id: role_id_to_use }); + created_user_id = user_id; + }); + return findById(created_user_id); } module.exports = { From b56111cdc5b45870fc1bf34fe7711be649db80b4 Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Tue, 9 Nov 2021 15:57:58 -0800 Subject: [PATCH 03/18] added JWT, filled auth-mdlwr, started /register --- api/auth/auth-middleware.js | 74 ++++++++++++-- api/auth/auth-router.js | 42 +++++--- api/secrets/index.js | 4 +- package-lock.json | 188 ++++++++++++++++++++++++++++++++++++ package.json | 1 + 5 files changed, 286 insertions(+), 23 deletions(-) diff --git a/api/auth/auth-middleware.js b/api/auth/auth-middleware.js index c603d37c7..8ed400f5f 100644 --- a/api/auth/auth-middleware.js +++ b/api/auth/auth-middleware.js @@ -1,4 +1,6 @@ -const { JWT_SECRET } = require("../secrets"); // use this secret! +const jwt = require("jsonwebtoken"); +const { JWT_SECRET } = require("./../secrets"); // use this secret! +const User = require("./../users/users-model"); const restricted = (req, res, next) => { /* @@ -16,7 +18,26 @@ const restricted = (req, res, next) => { Put the decoded token in the req object, to make life easier for middlewares downstream! */ -} + const token = req.headers.authorization; + if (!token) { + next({ + status: 401, + message: "Token required" + }); + } else { + jwt.verify(token, JWT_SECRET, (err, decoded) => { + if (err) { + next({ + status: 401, + message: "Token invalid" + }); + } else { + req.decodedJwt = decoded; + next(); + } + }); + } +}; const only = role_name => (req, res, next) => { /* @@ -29,10 +50,18 @@ const only = role_name => (req, res, next) => { Pull the decoded token from the req object, to avoid verifying it again! */ -} + if (req.decodedJwt.role_name !== role_name) { + next({ + status: 403, + message: "This is not for you" + }); + } else { + next(); + } +}; -const checkUsernameExists = (req, res, next) => { +const checkUsernameExists = async (req, res, next) => { /* If the username in req.body does NOT exist in the database status 401 @@ -40,7 +69,17 @@ const checkUsernameExists = (req, res, next) => { "message": "Invalid credentials" } */ -} + const { username } = req.body; + const user = await User.getBy({ username }); + if (!user) { + next({ + status: 401, + message: "Invalid credentials" + }); + } else { + next(); + } +}; const validateRoleName = (req, res, next) => { @@ -62,11 +101,32 @@ const validateRoleName = (req, res, next) => { "message": "Role name can not be longer than 32 chars" } */ -} + const { role_name } = req.body; + const role = role_name.trim(); + if ( + !role || + role.length === 0 + ) { + req.role_name = "student"; + return next(); + } + if (role === "admin") { + return next({ + status: 422, + message: "Role name can not be admin" + }); + } + if (role.length > 32) { + return next({ + status: 422, + message: "Role name can not be longer than 32 chars" + }); + } +}; module.exports = { restricted, checkUsernameExists, validateRoleName, only, -} +}; diff --git a/api/auth/auth-router.js b/api/auth/auth-router.js index c723c2da8..7f0a280ef 100644 --- a/api/auth/auth-router.js +++ b/api/auth/auth-router.js @@ -1,20 +1,34 @@ const router = require("express").Router(); -const { checkUsernameExists, validateRoleName } = require('./auth-middleware'); +const { + checkUsernameExists, + validateRoleName +} = require('./auth-middleware'); const { JWT_SECRET } = require("../secrets"); // use this secret! - -router.post("/register", validateRoleName, (req, res, next) => { - /** - [POST] /api/auth/register { "username": "anna", "password": "1234", "role_name": "angel" } - - response: - status 201 - { - "user"_id: 3, - "username": "anna", - "role_name": "angel" +const User = require("./../users/users-model"); + +router.post("/register", + validateRoleName, + async (req, res, next) => { + /** + [POST] /api/auth/register { "username": "anna", "password": "1234", "role_name": "angel" } + + response: + status 201 + { + "user"_id: 3, + "username": "anna", + "role_name": "angel" + } + */ + try { + const { username, password, role_name } = req.body; + const newUser = await User.add({ username, password, role_name }); + return newUser; + } catch (err) { + next(err); } - */ -}); + } +); router.post("/login", checkUsernameExists, (req, res, next) => { diff --git a/api/secrets/index.js b/api/secrets/index.js index 1a125b81e..e6f0c6736 100644 --- a/api/secrets/index.js +++ b/api/secrets/index.js @@ -7,5 +7,5 @@ developers cloning this repo won't be able to run the project as is. */ module.exports = { - -} + JWT_SECRET: process.env.JWT_SECRET || "shh" +}; diff --git a/package-lock.json b/package-lock.json index 4c7839920..cc7c65ff3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,6 +12,7 @@ "cors": "^2.8.5", "express": "^4.17.1", "helmet": "^4.6.0", + "jsonwebtoken": "^8.5.1", "knex": "^0.95.11", "sqlite3": "^5.0.2" }, @@ -1739,6 +1740,11 @@ "node-int64": "^0.4.0" } }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -2396,6 +2402,14 @@ "safer-buffer": "^2.1.0" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -4623,6 +4637,35 @@ "node": ">=6" } }, + "node_modules/jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=4", + "npm": ">=1.4.28" + } + }, + "node_modules/jsonwebtoken/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "bin": { + "semver": "bin/semver" + } + }, "node_modules/jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -4638,6 +4681,25 @@ "verror": "1.10.0" } }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/jwt-decode": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", @@ -4769,12 +4831,47 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, "node_modules/lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", @@ -8613,6 +8710,11 @@ "node-int64": "^0.4.0" } }, + "buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", @@ -9122,6 +9224,14 @@ "safer-buffer": "^2.1.0" } }, + "ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "requires": { + "safe-buffer": "^5.0.1" + } + }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -10849,6 +10959,30 @@ "minimist": "^1.2.5" } }, + "jsonwebtoken": { + "version": "8.5.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz", + "integrity": "sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==", + "requires": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^5.6.0" + }, + "dependencies": { + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + } + } + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -10861,6 +10995,25 @@ "verror": "1.10.0" } }, + "jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "requires": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "requires": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "jwt-decode": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz", @@ -10953,12 +11106,47 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha1-YLuYqHy5I8aMoeUTJUgzFISfVT8=" + }, + "lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha1-bC4XHbKiV82WgC/UOwGyDV9YcPY=" + }, + "lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha1-YZwK89A/iwTDH1iChAt3sRzWg0M=" + }, + "lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha1-POdoEMWSjQM1IwGsKHMX8RwLH/w=" + }, + "lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha1-fFJqUtibRcRcxpC4gWO+BJf1UMs=" + }, + "lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha1-1SfftUVuynzJu5XV2ur4i6VKVFE=" + }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, + "lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + }, "lowercase-keys": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", diff --git a/package.json b/package.json index 2252417b8..527c1ff6b 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "cors": "^2.8.5", "express": "^4.17.1", "helmet": "^4.6.0", + "jsonwebtoken": "^8.5.1", "knex": "^0.95.11", "sqlite3": "^5.0.2" }, From 3111341b24fea6280debc22f5de8782a8f7c773f Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Tue, 9 Nov 2021 16:21:37 -0800 Subject: [PATCH 04/18] added /login endpoint, edited /register w/ hash --- api/auth/auth-middleware.js | 2 +- api/auth/auth-router.js | 73 ++++++++++++++++++++++++++---------- api/users/users-model.js | 4 +- config/index.js | 5 ++- data/auth.db3 | Bin 32768 -> 32768 bytes 5 files changed, 59 insertions(+), 25 deletions(-) diff --git a/api/auth/auth-middleware.js b/api/auth/auth-middleware.js index 8ed400f5f..dc8caca5c 100644 --- a/api/auth/auth-middleware.js +++ b/api/auth/auth-middleware.js @@ -108,7 +108,6 @@ const validateRoleName = (req, res, next) => { role.length === 0 ) { req.role_name = "student"; - return next(); } if (role === "admin") { return next({ @@ -122,6 +121,7 @@ const validateRoleName = (req, res, next) => { message: "Role name can not be longer than 32 chars" }); } + next(); }; module.exports = { diff --git a/api/auth/auth-router.js b/api/auth/auth-router.js index 7f0a280ef..5a5855742 100644 --- a/api/auth/auth-router.js +++ b/api/auth/auth-router.js @@ -1,10 +1,13 @@ const router = require("express").Router(); +const bcrypt = require("bcryptjs"); +const jwt = require("jsonwebtoken"); const { checkUsernameExists, validateRoleName } = require('./auth-middleware'); -const { JWT_SECRET } = require("../secrets"); // use this secret! const User = require("./../users/users-model"); +const { JWT_SECRET } = require("../secrets"); // use this secret! +const { BCRYPT_ROUNDS } = require("./../../config"); router.post("/register", validateRoleName, @@ -21,8 +24,11 @@ router.post("/register", } */ try { - const { username, password, role_name } = req.body; - const newUser = await User.add({ username, password, role_name }); + let user = req.body; + const hash = bcrypt.hashSync(user.password, BCRYPT_ROUNDS); + user.password = hash; + + const newUser = await User.add(user); return newUser; } catch (err) { next(err); @@ -31,26 +37,53 @@ router.post("/register", ); -router.post("/login", checkUsernameExists, (req, res, next) => { - /** - [POST] /api/auth/login { "username": "sue", "password": "1234" } +router.post("/login", + checkUsernameExists, + async (req, res, next) => { + /** + [POST] /api/auth/login { "username": "sue", "password": "1234" } - response: - status 200 - { - "message": "sue is back!", - "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ETC.ETC" - } + response: + status 200 + { + "message": "sue is back!", + "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ETC.ETC" + } - The token must expire in one day, and must provide the following information - in its payload: + The token must expire in one day, and must provide the following information + in its payload: - { - "subject" : 1 // the user_id of the authenticated user - "username" : "bob" // the username of the authenticated user - "role_name": "admin" // the role of the authenticated user + { + "subject" : 1 // the user_id of the authenticated user + "username" : "bob" // the username of the authenticated user + "role_name": "admin" // the role of the authenticated user + } + */ + try { + const { username, password } = req.body; + const user = await User.findBy({ username }); + if (user && bcrypt.compareSync(password, user.password)) { + const token = jwt.sign({ + subject: user.user_id, + username: user.username, + role: user.role_name + }, + JWT_SECRET, + { expiresIn: "1d" }); + res.status(200).json({ + message: `${username} is back!`, + token: token + }); + } else { + next({ + status: 401, + message: "Invalid credentials" + }); + } + } catch (err) { + next(err); } - */ -}); + } +); module.exports = router; diff --git a/api/users/users-model.js b/api/users/users-model.js index 95b9a9bce..a5d5815a2 100644 --- a/api/users/users-model.js +++ b/api/users/users-model.js @@ -41,7 +41,7 @@ function findBy(filter) { } ] */ - const filteredUsers = db("user as u") + const filteredUsers = db("users as u") .leftJoin("roles as r", "u.role_id", "r.role_id") .select("u.user_id", @@ -63,7 +63,7 @@ function findById(user_id) { "role_name": "instructor" } */ - const user = db("user as u") + const user = db("users as u") .leftJoin("roles as r", "u.role_id", "r.role_id") .select("u.user_id", diff --git a/config/index.js b/config/index.js index 576df0efe..2670fb07a 100644 --- a/config/index.js +++ b/config/index.js @@ -1,3 +1,4 @@ module.exports = { - PORT: process.env.PORT || 9000 -} + PORT: process.env.PORT || 9000, + BCRYPT_ROUNDS: process.env.BCRYPT_ROUNDS || 8 +}; diff --git a/data/auth.db3 b/data/auth.db3 index 568bc34c7877fd4d47b42a561434f8885c50ca00..066d45e536c1a658cb18119a15c8ba145503164b 100644 GIT binary patch delta 196 zcmZo@U}|V!njp=XIZ?)$F>_-=gFX*4Clj+cV^MxiYB9^^H~JC+JS_Z|8Th~PKj**A ze|fW@z+rw4HWp?E;gtOJ$+!JAfznqP_`maC;eWw@2Pl1npM#xQm=P$;GWkxt1{X7b z7z6)K{zCq+&3p+S{L+%ltPHBsjOB@y<%vZp1^M~O86~O3C7F3Z^@aJ9f$ASH@c-oh g$p2t7U%@4Q1p#JN6vfOS(~C<}nb??xIg|2}0Ai{-U;qFB delta 184 zcmZo@U}|V!njp=XF;T{uF=JywgFX)vClj+cV^MxiYBBTXH~JC+Jk0#J8Th~PKj**A ze{Hj%!AX85E$PX({WXCScNqA;^S|J~!+#wpaf+Wwvv~5IcnvNl{z3-+o&1IT>YMoz zJou%Jy#33 Date: Tue, 9 Nov 2021 19:55:33 -0800 Subject: [PATCH 05/18] installed yup --- package-lock.json | 113 +++++++++++++++++++++++++++++++++++++++++++++- package.json | 3 +- 2 files changed, 114 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index cc7c65ff3..aa2c9e609 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,7 +14,8 @@ "helmet": "^4.6.0", "jsonwebtoken": "^8.5.1", "knex": "^0.95.11", - "sqlite3": "^5.0.2" + "sqlite3": "^5.0.2", + "yup": "^0.32.11" }, "devDependencies": { "@types/jest": "^27.0.2", @@ -577,6 +578,17 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/runtime": { + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz", + "integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==", + "dependencies": { + "regenerator-runtime": "^0.13.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/template": { "version": "7.15.4", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", @@ -1129,6 +1141,11 @@ "pretty-format": "^27.0.0" } }, + "node_modules/@types/lodash": { + "version": "4.14.176", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.176.tgz", + "integrity": "sha512-xZmuPTa3rlZoIbtDUyJKZQimJV3bxCmzMIO2c9Pz9afyDro6kr7R79GwcB6mRhuoPmV2p1Vb66WOJH7F886WKQ==" + }, "node_modules/@types/node": { "version": "16.6.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.6.1.tgz", @@ -4831,6 +4848,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -5068,6 +5090,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/nanoclone": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", + "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -5800,6 +5827,11 @@ "node": ">= 6" } }, + "node_modules/property-expr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz", + "integrity": "sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg==" + }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -5950,6 +5982,11 @@ "node": ">= 0.10" } }, + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, "node_modules/regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -6747,6 +6784,11 @@ "node": ">=0.6" } }, + "node_modules/toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=" + }, "node_modules/touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -7336,6 +7378,23 @@ "engines": { "node": ">=8" } + }, + "node_modules/yup": { + "version": "0.32.11", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", + "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", + "dependencies": { + "@babel/runtime": "^7.15.4", + "@types/lodash": "^4.14.175", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + }, + "engines": { + "node": ">=10" + } } }, "dependencies": { @@ -7753,6 +7812,14 @@ "@babel/helper-plugin-utils": "^7.14.5" } }, + "@babel/runtime": { + "version": "7.16.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.16.3.tgz", + "integrity": "sha512-WBwekcqacdY2e9AF/Q7WLFUWmdJGJTkbjqTjoMDgXkVZ3ZRUvOPsLb5KdwISoQVsbP+DQzVZW4Zhci0DvpbNTQ==", + "requires": { + "regenerator-runtime": "^0.13.4" + } + }, "@babel/template": { "version": "7.15.4", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.15.4.tgz", @@ -8220,6 +8287,11 @@ "pretty-format": "^27.0.0" } }, + "@types/lodash": { + "version": "4.14.176", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.176.tgz", + "integrity": "sha512-xZmuPTa3rlZoIbtDUyJKZQimJV3bxCmzMIO2c9Pz9afyDro6kr7R79GwcB6mRhuoPmV2p1Vb66WOJH7F886WKQ==" + }, "@types/node": { "version": "16.6.1", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.6.1.tgz", @@ -11106,6 +11178,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "lodash.includes": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", @@ -11299,6 +11376,11 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "nanoclone": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz", + "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==" + }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -11855,6 +11937,11 @@ "sisteransi": "^1.0.5" } }, + "property-expr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz", + "integrity": "sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg==" + }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -11977,6 +12064,11 @@ "resolve": "^1.9.0" } }, + "regenerator-runtime": { + "version": "0.13.9", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", + "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==" + }, "regexpp": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz", @@ -12591,6 +12683,11 @@ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" }, + "toposort": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz", + "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA=" + }, "touch": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", @@ -13055,6 +13152,20 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", "dev": true + }, + "yup": { + "version": "0.32.11", + "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz", + "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==", + "requires": { + "@babel/runtime": "^7.15.4", + "@types/lodash": "^4.14.175", + "lodash": "^4.17.21", + "lodash-es": "^4.17.21", + "nanoclone": "^0.2.1", + "property-expr": "^2.0.4", + "toposort": "^2.0.2" + } } } } diff --git a/package.json b/package.json index 527c1ff6b..22a52b8cc 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,8 @@ "helmet": "^4.6.0", "jsonwebtoken": "^8.5.1", "knex": "^0.95.11", - "sqlite3": "^5.0.2" + "sqlite3": "^5.0.2", + "yup": "^0.32.11" }, "repository": { "type": "git", From 308f578d89c39a3ed304c1989394de2ed472445f Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Tue, 9 Nov 2021 19:56:00 -0800 Subject: [PATCH 06/18] used yup to validate role name --- api/auth/auth-middleware.js | 39 ++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/api/auth/auth-middleware.js b/api/auth/auth-middleware.js index dc8caca5c..83e132e6b 100644 --- a/api/auth/auth-middleware.js +++ b/api/auth/auth-middleware.js @@ -1,6 +1,7 @@ const jwt = require("jsonwebtoken"); const { JWT_SECRET } = require("./../secrets"); // use this secret! const User = require("./../users/users-model"); +const yup = require("yup"); const restricted = (req, res, next) => { /* @@ -70,7 +71,7 @@ const checkUsernameExists = async (req, res, next) => { } */ const { username } = req.body; - const user = await User.getBy({ username }); + const user = await User.findBy({ username }); if (!user) { next({ status: 401, @@ -82,7 +83,7 @@ const checkUsernameExists = async (req, res, next) => { }; -const validateRoleName = (req, res, next) => { +const validateRoleName = async (req, res, next) => { /* If the role_name in the body is valid, set req.role_name to be the trimmed string and proceed. @@ -102,26 +103,24 @@ const validateRoleName = (req, res, next) => { } */ const { role_name } = req.body; - const role = role_name.trim(); - if ( - !role || - role.length === 0 - ) { - req.role_name = "student"; - } - if (role === "admin") { - return next({ - status: 422, - message: "Role name can not be admin" - }); - } - if (role.length > 32) { - return next({ + const roleSchema = yup.object().shape({ + role_name: yup + .string() + .trim() + .notOneOf(["admin"], "Role name can not be admin") + .max(32, "Role name can not be longer than 32 chars") + .default(() => { "student" }) + }) + try { + const validatedRole = await roleSchema.validate({ role_name }) + req.role_name = validatedRole; + next() + } catch (err) { + next({ status: 422, - message: "Role name can not be longer than 32 chars" - }); + message: err.errors[0] + }) } - next(); }; module.exports = { From 26e5f90f327d174242a44f17827d3789a619e5f4 Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Tue, 9 Nov 2021 20:23:28 -0800 Subject: [PATCH 07/18] fixed "undefined" bug in validation of role name --- api/auth/auth-middleware.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/api/auth/auth-middleware.js b/api/auth/auth-middleware.js index 83e132e6b..a7e68770b 100644 --- a/api/auth/auth-middleware.js +++ b/api/auth/auth-middleware.js @@ -109,13 +109,14 @@ const validateRoleName = async (req, res, next) => { .trim() .notOneOf(["admin"], "Role name can not be admin") .max(32, "Role name can not be longer than 32 chars") - .default(() => { "student" }) + .default(() => { return "student" }) }) try { const validatedRole = await roleSchema.validate({ role_name }) req.role_name = validatedRole; next() } catch (err) { + console.log(err.errors[0]) next({ status: 422, message: err.errors[0] From 97d1ae51859a67429ca35fc97050ceb33d3e1677 Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Tue, 9 Nov 2021 20:42:19 -0800 Subject: [PATCH 08/18] fixed role_name appending incorrectly to request --- api/auth/auth-middleware.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/auth/auth-middleware.js b/api/auth/auth-middleware.js index a7e68770b..616a2872e 100644 --- a/api/auth/auth-middleware.js +++ b/api/auth/auth-middleware.js @@ -113,7 +113,7 @@ const validateRoleName = async (req, res, next) => { }) try { const validatedRole = await roleSchema.validate({ role_name }) - req.role_name = validatedRole; + req.role_name = validatedRole.role_name; next() } catch (err) { console.log(err.errors[0]) From 61d10fb5a8202d125477f1c97c9efc25a5f9798b Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Tue, 9 Nov 2021 20:50:36 -0800 Subject: [PATCH 09/18] refactored restricted middleware --- api/auth/auth-middleware.js | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/api/auth/auth-middleware.js b/api/auth/auth-middleware.js index 616a2872e..953d40506 100644 --- a/api/auth/auth-middleware.js +++ b/api/auth/auth-middleware.js @@ -21,25 +21,24 @@ const restricted = (req, res, next) => { */ const token = req.headers.authorization; if (!token) { - next({ + return next({ status: 401, message: "Token required" }); - } else { - jwt.verify(token, JWT_SECRET, (err, decoded) => { - if (err) { - next({ - status: 401, - message: "Token invalid" - }); - } else { - req.decodedJwt = decoded; - next(); - } - }); } + jwt.verify(token, JWT_SECRET, (err, decoded) => { + if (err) { + return next({ + status: 401, + message: "Token invalid" + }); + } + req.decodedJwt = decoded; + next(); + }) }; + const only = role_name => (req, res, next) => { /* If the user does not provide a token in the Authorization header with a role_name @@ -116,7 +115,6 @@ const validateRoleName = async (req, res, next) => { req.role_name = validatedRole.role_name; next() } catch (err) { - console.log(err.errors[0]) next({ status: 422, message: err.errors[0] From 6cbda0d3e588a757dc47a47d454b8ffed11dafa5 Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Tue, 9 Nov 2021 20:51:21 -0800 Subject: [PATCH 10/18] converted users-model functions to be arrow-async --- api/users/users-model.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/api/users/users-model.js b/api/users/users-model.js index a5d5815a2..ed14c72eb 100644 --- a/api/users/users-model.js +++ b/api/users/users-model.js @@ -1,6 +1,6 @@ const db = require('../../data/db-config.js'); -function find() { +const find = async () => { /** You will need to join two tables. Resolves to an ARRAY with all users. @@ -18,7 +18,7 @@ function find() { } ] */ - const users = db("users as u") + const users = await db("users as u") .leftJoin("roles as r", "u.role_id", "r.role_id") .select("u.user_id", @@ -27,7 +27,7 @@ function find() { return users; } -function findBy(filter) { +const findBy = async (filter) => { /** You will need to join two tables. Resolves to an ARRAY with all users that match the filter condition. @@ -41,7 +41,7 @@ function findBy(filter) { } ] */ - const filteredUsers = db("users as u") + const filteredUsers = await db("users as u") .leftJoin("roles as r", "u.role_id", "r.role_id") .select("u.user_id", @@ -52,7 +52,7 @@ function findBy(filter) { return filteredUsers; } -function findById(user_id) { +const findById = async (user_id) => { /** You will need to join two tables. Resolves to the user with the given user_id. @@ -63,7 +63,7 @@ function findById(user_id) { "role_name": "instructor" } */ - const user = db("users as u") + const user = await db("users as u") .leftJoin("roles as r", "u.role_id", "r.role_id") .select("u.user_id", @@ -92,7 +92,7 @@ function findById(user_id) { "role_name": "team lead" } */ -async function add({ username, password, role_name }) { // done for you +const add = async ({ username, password, role_name }) => { // done for you let created_user_id; await db.transaction(async trx => { let role_id_to_use; From c705c509422ac9505a93c07fa50ede4afda9247b Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Tue, 9 Nov 2021 20:51:46 -0800 Subject: [PATCH 11/18] added role_name to /register --- api/auth/auth-router.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api/auth/auth-router.js b/api/auth/auth-router.js index 5a5855742..46677bc28 100644 --- a/api/auth/auth-router.js +++ b/api/auth/auth-router.js @@ -6,7 +6,7 @@ const { validateRoleName } = require('./auth-middleware'); const User = require("./../users/users-model"); -const { JWT_SECRET } = require("../secrets"); // use this secret! +const { JWT_SECRET } = require("./../secrets"); // use this secret! const { BCRYPT_ROUNDS } = require("./../../config"); router.post("/register", @@ -26,9 +26,11 @@ router.post("/register", try { let user = req.body; const hash = bcrypt.hashSync(user.password, BCRYPT_ROUNDS); + user.role_name = req.role_name; user.password = hash; const newUser = await User.add(user); + return newUser; } catch (err) { next(err); From 6567fdda1d2270c7a0309db1d349c0a4330a2405 Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Wed, 10 Nov 2021 05:28:26 -0800 Subject: [PATCH 12/18] moved token generation to separate file --- api/auth/token-builder.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 api/auth/token-builder.js diff --git a/api/auth/token-builder.js b/api/auth/token-builder.js new file mode 100644 index 000000000..a8073f9d2 --- /dev/null +++ b/api/auth/token-builder.js @@ -0,0 +1,16 @@ +const jwt = require("jsonwebtoken") +const { JWT_SECRET } = require("./../secrets") + +const buildToken = (user) => { + const payload = { + subject: user.id, + username: user.username, + role_id: user.role, + } + const options = { + expiresIn: "1d", + } + return jwt.sign(payload, JWT_SECRET, options) +} + +module.exports = buildToken; \ No newline at end of file From cb696f56ababc16c39493515caaf408b98779d09 Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Wed, 10 Nov 2021 05:56:54 -0800 Subject: [PATCH 13/18] fixed /register not sending a response --- api/auth/auth-middleware.js | 2 +- api/auth/auth-router.js | 20 +++++++------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/api/auth/auth-middleware.js b/api/auth/auth-middleware.js index 953d40506..1b8b5e022 100644 --- a/api/auth/auth-middleware.js +++ b/api/auth/auth-middleware.js @@ -101,7 +101,6 @@ const validateRoleName = async (req, res, next) => { "message": "Role name can not be longer than 32 chars" } */ - const { role_name } = req.body; const roleSchema = yup.object().shape({ role_name: yup .string() @@ -111,6 +110,7 @@ const validateRoleName = async (req, res, next) => { .default(() => { return "student" }) }) try { + const { role_name } = req.body; const validatedRole = await roleSchema.validate({ role_name }) req.role_name = validatedRole.role_name; next() diff --git a/api/auth/auth-router.js b/api/auth/auth-router.js index 46677bc28..ff33e59a4 100644 --- a/api/auth/auth-router.js +++ b/api/auth/auth-router.js @@ -6,8 +6,8 @@ const { validateRoleName } = require('./auth-middleware'); const User = require("./../users/users-model"); -const { JWT_SECRET } = require("./../secrets"); // use this secret! const { BCRYPT_ROUNDS } = require("./../../config"); +const buildToken = require("./token-builder"); router.post("/register", validateRoleName, @@ -31,7 +31,7 @@ router.post("/register", const newUser = await User.add(user); - return newUser; + res.status(201).json(newUser); } catch (err) { next(err); } @@ -62,18 +62,12 @@ router.post("/login", } */ try { - const { username, password } = req.body; - const user = await User.findBy({ username }); - if (user && bcrypt.compareSync(password, user.password)) { - const token = jwt.sign({ - subject: user.user_id, - username: user.username, - role: user.role_name - }, - JWT_SECRET, - { expiresIn: "1d" }); + const credentials = req.body; + const user = await User.findBy({ username: credentials.username }); + if (user && bcrypt.compareSync(credentials.password, user.password)) { + const token = buildToken(user) res.status(200).json({ - message: `${username} is back!`, + message: `${user.username} is back!`, token: token }); } else { From 1b443363d5a338bde70328e098a7df602a4a681b Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Wed, 10 Nov 2021 06:01:37 -0800 Subject: [PATCH 14/18] fixed /login failing to grab user via findBy() --- api/auth/auth-router.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/auth/auth-router.js b/api/auth/auth-router.js index ff33e59a4..78bf238a1 100644 --- a/api/auth/auth-router.js +++ b/api/auth/auth-router.js @@ -64,10 +64,10 @@ router.post("/login", try { const credentials = req.body; const user = await User.findBy({ username: credentials.username }); - if (user && bcrypt.compareSync(credentials.password, user.password)) { + if (user && bcrypt.compareSync(credentials.password, user[0].password)) { const token = buildToken(user) res.status(200).json({ - message: `${user.username} is back!`, + message: `${credentials.username} is back!`, token: token }); } else { From 268c98ababea7ed82dfcfef5c627aa93f5bbdf58 Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Wed, 10 Nov 2021 06:18:58 -0800 Subject: [PATCH 15/18] adjusted token-builder --- api/auth/token-builder.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/api/auth/token-builder.js b/api/auth/token-builder.js index a8073f9d2..5ac35e6a8 100644 --- a/api/auth/token-builder.js +++ b/api/auth/token-builder.js @@ -3,14 +3,15 @@ const { JWT_SECRET } = require("./../secrets") const buildToken = (user) => { const payload = { - subject: user.id, + subject: user.user_id, username: user.username, - role_id: user.role, + role_id: user.role_name, } const options = { expiresIn: "1d", } - return jwt.sign(payload, JWT_SECRET, options) + const signedToken = jwt.sign(payload, JWT_SECRET, options) + return signedToken; } module.exports = buildToken; \ No newline at end of file From ef153460a9db63b7bfd6919dd0763344188a4cb5 Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Wed, 10 Nov 2021 06:19:25 -0800 Subject: [PATCH 16/18] fixed /login looking at wrong user --- api/auth/auth-router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/auth/auth-router.js b/api/auth/auth-router.js index 78bf238a1..1b95317ed 100644 --- a/api/auth/auth-router.js +++ b/api/auth/auth-router.js @@ -64,7 +64,7 @@ router.post("/login", try { const credentials = req.body; const user = await User.findBy({ username: credentials.username }); - if (user && bcrypt.compareSync(credentials.password, user[0].password)) { + if (user[0] && bcrypt.compareSync(credentials.password, user[0].password)) { const token = buildToken(user) res.status(200).json({ message: `${credentials.username} is back!`, From d2e03eeb21d11689a4db4eb33290c648353930f5 Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Wed, 10 Nov 2021 06:24:40 -0800 Subject: [PATCH 17/18] fixed role_name typo in token builder --- api/auth/token-builder.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/auth/token-builder.js b/api/auth/token-builder.js index 5ac35e6a8..9fa7c4002 100644 --- a/api/auth/token-builder.js +++ b/api/auth/token-builder.js @@ -5,7 +5,7 @@ const buildToken = (user) => { const payload = { subject: user.user_id, username: user.username, - role_id: user.role_name, + role_name: user.role_name, } const options = { expiresIn: "1d", From 239e77b3670834d7978ac17a2e4ea46bc9979548 Mon Sep 17 00:00:00 2001 From: Lance Turbes Jr Date: Wed, 10 Nov 2021 06:25:23 -0800 Subject: [PATCH 18/18] fixed invalid argument passed into buildToken --- api/auth/auth-router.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/auth/auth-router.js b/api/auth/auth-router.js index 1b95317ed..c5823f33f 100644 --- a/api/auth/auth-router.js +++ b/api/auth/auth-router.js @@ -65,7 +65,7 @@ router.post("/login", const credentials = req.body; const user = await User.findBy({ username: credentials.username }); if (user[0] && bcrypt.compareSync(credentials.password, user[0].password)) { - const token = buildToken(user) + const token = buildToken(user[0]) res.status(200).json({ message: `${credentials.username} is back!`, token: token