From 58a99a61e65ff1f554d50d49e1d40be77750b4cf Mon Sep 17 00:00:00 2001 From: Lirong Cui Date: Sat, 26 Mar 2022 17:44:52 -0700 Subject: [PATCH 1/3] wip --- api/auth/auth-router.js | 47 +++++++- api/middleware/restricted.js | 18 ++- api/middleware/uniqueUsername.js | 15 +++ api/server.js | 6 + api/server.test.js | 52 +++++++- config/secrets.js | 3 + package-lock.json | 199 +++++++++++++++++++++++++++++++ package.json | 2 + user/user-model.js | 15 +++ 9 files changed, 351 insertions(+), 6 deletions(-) create mode 100644 api/middleware/uniqueUsername.js create mode 100644 config/secrets.js create mode 100644 user/user-model.js diff --git a/api/auth/auth-router.js b/api/auth/auth-router.js index 47d8e51ae..03696d241 100644 --- a/api/auth/auth-router.js +++ b/api/auth/auth-router.js @@ -1,7 +1,33 @@ +const bcrypt = require('bcryptjs'); +const jwt = require('jsonwebtoken'); const router = require('express').Router(); +const User = require('../../user/user-model'); +const { TOKEN_SECRET } = require('../../config/secrets'); +const uniqueUsername = require('../middleware/uniqueUsername'); + +function buildToken(userObj) { + const payload = { + subject: userObj.id, + username: userObj.username, + } + const options = { + expriresIn: '1d', + } + return jwt.sign(playload, TOKEN_SECRET, options ) +} +router.post('/register', uniqueUsername, async (req, res) => { + try { + const { username, password } = req.body; + const hash = bcrypt.hashSync(password, 8); + const newUser = await User.add({ + username, + password: hash, + }); + res.status(201).json(newUser); + } catch(err) { + res.status(500).json({ message: err.message}) + } -router.post('/register', (req, res) => { - res.end('implement register, please!'); /* IMPLEMENT You are welcome to build additional middlewares to help with the endpoint's functionality. @@ -29,8 +55,21 @@ router.post('/register', (req, res) => { */ }); -router.post('/login', (req, res) => { - res.end('implement login, please!'); +router.post('/login', (req, res, next) => { + let { username, password } = req.body; + User.findByUsername({username}) + .then(([user]) => { + if (user && bcrypt.compareSync(password, user.password)) { + const token = buildToken(user) + res.status(200).json({ + message: `welcome ${user.username}`, + token: token, + }) + } else { + next({ status: 401, message: 'invalid credentials' }) + } + }) + .catch(next) /* IMPLEMENT You are welcome to build additional middlewares to help with the endpoint's functionality. diff --git a/api/middleware/restricted.js b/api/middleware/restricted.js index a690e961e..c8d5e89bc 100644 --- a/api/middleware/restricted.js +++ b/api/middleware/restricted.js @@ -1,5 +1,21 @@ +const jwt = require('jsonwebtoken'); +const { TOKEN_SECRET } = require('../../config/secrets'); + module.exports = (req, res, next) => { - next(); + const token = req.headers.authorization + + if (token) { + jwt.verify(token, TOKEN_SECRET, (err, decoded) => { + if (err) { + next({ status: 401, message: 'token invalid'}) + } else { + req.decodedJwt = decoded + next() + } + }) + } else { + next({ status: 401, message: 'token required'}) + } /* IMPLEMENT diff --git a/api/middleware/uniqueUsername.js b/api/middleware/uniqueUsername.js new file mode 100644 index 000000000..4394f847e --- /dev/null +++ b/api/middleware/uniqueUsername.js @@ -0,0 +1,15 @@ +const User = require('../../user/user-model'); + +async function uniqueUsername(req, res, next) { + const { username } = req.body; + const user = await User.findByUsername(username); + if (user) { + res.status(400).json({ message: 'username taken'}) + } else { + next() + } +} + +module.exports = { + uniqueUsername +} \ No newline at end of file diff --git a/api/server.js b/api/server.js index 33320b871..3bf047f72 100644 --- a/api/server.js +++ b/api/server.js @@ -16,4 +16,10 @@ server.use(express.json()); server.use('/api/auth', authRouter); server.use('/api/jokes', restrict, jokesRouter); // only logged-in users should have access! +server.use((err, req, res, next) => { + res.staus(err.status || 500).json({ + message: err.message, + stack: err.stack, + }); +}); module.exports = server; diff --git a/api/server.test.js b/api/server.test.js index 96965c559..2d3ee7a1b 100644 --- a/api/server.test.js +++ b/api/server.test.js @@ -1,4 +1,54 @@ // Write your tests here +const request = require('supertest') +const server = require('./server') +const db = require('../data/dbConfig') + +const userA = { username: 'foo', password: 'bar' } + +beforeAll(async () => { + await db.migrate.rollback() + await db.migrate.latest() +}) + afterAll(async () => { + await db.destroy() + }) + test('sanity', () => { - expect(true).toBe(false) + expect(true).not.toBe(false) }) + +describe ('server.js', () => { + describe('auth endpoints', ()=> { + beforeEach(async () => { + await db('users').truncate() + }) + it('adds a new user with a bcrypted password to the users table on success', async () => { + await requrest(server).post('/api/auth/register').send(userA) + const user = await db('users').first() + expect(user).toHaveProperty('id') + expect(user).toHaveProperty('username') + expect(user).toHaveProperty('password') + expect(user.password).toMatch(/^\$2[ayb]\$.{56}$/) + expect(user.username).toBe(userA.username) + }) + it ('responds with the new user with a bcryped password on success', async () => { + const { body } = await (await request(server).post('/api/auth/register')).setEncoding(userA) + expect(body).toHaveProperty('id') + expect(body).toHaveProperty('username') + expect(body).toHaveProperty('password') + expect(body.password).toMatch(/^\$2[ayb]\$.{56}$/) + expect(body.username).toBe(userA.username) + }) + }) + describe('[POST] /api/auth/login', () => { + beforeEach(async () => { + await db('users').truncate() + await request(server).post('/api/auth/register').send(userA) + }) + it ('responds with a welcome message and a token on success', async ()=> { + const res = await request(server).post('/api/auth/login').send(userA) + expect(res.body).toHaveProperty('message') + expect(res.body).toHaveProperty('token') + }) + }) +}) \ No newline at end of file diff --git a/config/secrets.js b/config/secrets.js new file mode 100644 index 000000000..e3e42a520 --- /dev/null +++ b/config/secrets.js @@ -0,0 +1,3 @@ +module.exports = { + TOKEN_SECRET: process.env.TOKEN_SECRET || 'shh' +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 141703ec1..9ffffb5d9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +10,11 @@ "license": "ISC", "dependencies": { "@vscode/sqlite3": "5.0.7", + "bcryptjs": "^2.4.3", "cors": "2.8.5", "express": "4.17.3", "helmet": "5.0.2", + "jsonwebtoken": "^8.5.1", "knex": "1.0.3" }, "devDependencies": { @@ -1438,6 +1440,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -1574,6 +1581,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", @@ -2182,6 +2194,14 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "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", @@ -4235,6 +4255,54 @@ "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/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/keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -4367,12 +4435,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", @@ -7410,6 +7513,11 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha1-mrVie5PmBiH/fNrF2pczAn3x0Ms=" + }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -7519,6 +7627,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", @@ -7990,6 +8103,14 @@ "integrity": "sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI=", "dev": true }, + "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", @@ -9561,6 +9682,49 @@ "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==" + } + } + }, + "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" + } + }, "keyv": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/keyv/-/keyv-3.1.0.tgz", @@ -9648,12 +9812,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 8b03c4fa2..b77e6d7e9 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,11 @@ "license": "ISC", "dependencies": { "@vscode/sqlite3": "5.0.7", + "bcryptjs": "^2.4.3", "cors": "2.8.5", "express": "4.17.3", "helmet": "5.0.2", + "jsonwebtoken": "^8.5.1", "knex": "1.0.3" }, "devDependencies": { diff --git a/user/user-model.js b/user/user-model.js new file mode 100644 index 000000000..5f0334d67 --- /dev/null +++ b/user/user-model.js @@ -0,0 +1,15 @@ +const db = require('../data/dbConfig') + +function findByUsername(username) { + return db('users').where('username', username).first() +} + +async function add(user) { + const [id] = await db('users').insert(user) + return findByUsername(username) +} + +module.exports = { + findByUsername, + add +} \ No newline at end of file From 36f8d73d68c3571f186ed3fc74abe9fb5c6d09bc Mon Sep 17 00:00:00 2001 From: Lirong Cui Date: Sun, 27 Mar 2022 01:04:34 -0700 Subject: [PATCH 2/3] wip --- api/auth/auth-router.js | 6 +++--- api/middleware/uniqueUsername.js | 8 ++------ {user => api/user}/user-model.js | 6 +++--- 3 files changed, 8 insertions(+), 12 deletions(-) rename {user => api/user}/user-model.js (55%) diff --git a/api/auth/auth-router.js b/api/auth/auth-router.js index 03696d241..eb8f96a8d 100644 --- a/api/auth/auth-router.js +++ b/api/auth/auth-router.js @@ -1,7 +1,7 @@ const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const router = require('express').Router(); -const User = require('../../user/user-model'); +const User = require('../user/user-model'); const { TOKEN_SECRET } = require('../../config/secrets'); const uniqueUsername = require('../middleware/uniqueUsername'); @@ -13,9 +13,9 @@ function buildToken(userObj) { const options = { expriresIn: '1d', } - return jwt.sign(playload, TOKEN_SECRET, options ) + return jwt.sign(payload, TOKEN_SECRET, options ) } -router.post('/register', uniqueUsername, async (req, res) => { +router.post('/register',uniqueUsername, async (req, res) => { try { const { username, password } = req.body; const hash = bcrypt.hashSync(password, 8); diff --git a/api/middleware/uniqueUsername.js b/api/middleware/uniqueUsername.js index 4394f847e..4080fe609 100644 --- a/api/middleware/uniqueUsername.js +++ b/api/middleware/uniqueUsername.js @@ -1,6 +1,6 @@ -const User = require('../../user/user-model'); +const User = require('../user/user-model'); -async function uniqueUsername(req, res, next) { +module.exports = async function uniqueUsername(req, res, next) { const { username } = req.body; const user = await User.findByUsername(username); if (user) { @@ -8,8 +8,4 @@ async function uniqueUsername(req, res, next) { } else { next() } -} - -module.exports = { - uniqueUsername } \ No newline at end of file diff --git a/user/user-model.js b/api/user/user-model.js similarity index 55% rename from user/user-model.js rename to api/user/user-model.js index 5f0334d67..ee3df1fdf 100644 --- a/user/user-model.js +++ b/api/user/user-model.js @@ -1,12 +1,12 @@ -const db = require('../data/dbConfig') +const db = require('../../data/dbConfig') function findByUsername(username) { - return db('users').where('username', username).first() +return db('users').where({username}).first() } async function add(user) { const [id] = await db('users').insert(user) - return findByUsername(username) + return db('users').where({id}).first() } module.exports = { From 13173e4c1d0e9bdffbded025e2f585433f5045fe Mon Sep 17 00:00:00 2001 From: Lirong Cui Date: Sun, 27 Mar 2022 01:22:49 -0700 Subject: [PATCH 3/3] wip --- api/auth/auth-router.js | 21 +++++++++++---------- api/middleware/usernameExists.js | 12 ++++++++++++ 2 files changed, 23 insertions(+), 10 deletions(-) create mode 100644 api/middleware/usernameExists.js diff --git a/api/auth/auth-router.js b/api/auth/auth-router.js index eb8f96a8d..06555e567 100644 --- a/api/auth/auth-router.js +++ b/api/auth/auth-router.js @@ -4,6 +4,7 @@ const router = require('express').Router(); const User = require('../user/user-model'); const { TOKEN_SECRET } = require('../../config/secrets'); const uniqueUsername = require('../middleware/uniqueUsername'); +const usernameExists = require('../middleware/usernameExists'); function buildToken(userObj) { const payload = { @@ -11,7 +12,7 @@ function buildToken(userObj) { username: userObj.username, } const options = { - expriresIn: '1d', + expiresIn: '1d', } return jwt.sign(payload, TOKEN_SECRET, options ) } @@ -55,21 +56,21 @@ router.post('/register',uniqueUsername, async (req, res) => { */ }); -router.post('/login', (req, res, next) => { - let { username, password } = req.body; - User.findByUsername({username}) - .then(([user]) => { - if (user && bcrypt.compareSync(password, user.password)) { +router.post('/login', usernameExists, async(req, res, next) => { + try{ + const { body: { password }, user } = req; + if (bcrypt.compareSync(password, user.password)) { const token = buildToken(user) - res.status(200).json({ + res.json({ message: `welcome ${user.username}`, token: token, }) } else { - next({ status: 401, message: 'invalid credentials' }) + res.status(401).json({message: 'invalid credentials' }) } - }) - .catch(next) + } catch (err) { + res.status(500).json({ message: err.message}) + } /* IMPLEMENT You are welcome to build additional middlewares to help with the endpoint's functionality. diff --git a/api/middleware/usernameExists.js b/api/middleware/usernameExists.js new file mode 100644 index 000000000..96bfd9436 --- /dev/null +++ b/api/middleware/usernameExists.js @@ -0,0 +1,12 @@ +const User = require('../user/user-model'); + +module.exports = async function(req, res, next) { + const { username } = req.body; + const user = await User.findByUsername(username); + if (!user) { + res.status(400).json({ message: 'invalid credentials' }) + } else { + req.user = user + next() + } +} \ No newline at end of file