diff options
| author | Jan Tuomi <jan.tuomi@eficode.com> | 2020-02-01 16:33:56 +0200 |
|---|---|---|
| committer | Jan Tuomi <jan.tuomi@eficode.com> | 2020-02-01 16:33:56 +0200 |
| commit | a5ae2653d8ccdaf00270c0c8c8a30b88d7955114 (patch) | |
| tree | bd265901dbda512fb1f6d717beb545234468d7ec /backend/src/routes.js | |
| parent | fbf108595a00a7c9db5984158e4b02cc345b68d1 (diff) | |
Do stuff
Diffstat (limited to 'backend/src/routes.js')
| -rw-r--r-- | backend/src/routes.js | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/backend/src/routes.js b/backend/src/routes.js new file mode 100644 index 0000000..a762d3a --- /dev/null +++ b/backend/src/routes.js @@ -0,0 +1,133 @@ +const express = require('express'); +const sha512 = require('js-sha512'); +const shortid = require('shortid'); + +const salt = 'suola'; + +const db = require('./db'); + +const buildSessionCookie = ({ sessionId, isLogout, remember }) => { + if (!isLogout) { + if (remember) { + return `sessionId=${sessionId}; Domain=localhost; HttpOnly; SameSite=strict;`; + } else { + return `sessionId=${sessionId}; Domain=localhost; HttpOnly; SameSite=strict; Max-Age=86400;`; + } + } else { + return `sessionId=deleted; Domain=localhost; Expires=Thu, 01 Jan 1970 00:00:00 GMT; HttpOnly; SameSite=strict;`; + } +}; + +const normalRouter = express.Router(); +const authedRouter = express.Router(); + +authedRouter.use(async (req, res, next) => { + const cookies = req.cookies; + const { sessionId } = cookies; + + if (!sessionId) { + res.status(403); + return res.json({ + message: 'Log in first!', + }); + } + + const token = await db('tokens').where('value', sessionId).first(); + + if (!token) { + res.status(400); + res.set('Set-Cookie', buildSessionCookie({ isLogout: true })); + return res.json({ + message: 'Invalid session token.', + sessionId, + }); + } + + const user = await db('users').where({ id: token.user_id }).first(); + + req.sessionId = sessionId; + req.user = user; + + next(); +}); + +normalRouter.get('/', (req, res) => { + res.json({ + message: 'Backend API', + }); +}); + +normalRouter.post('/register', async (req, res) => { + const { username, password } = req.body; + if (!username || !password) { + res.status(400); + return res.json({ + error: 'Username or password missing.', + }); + } + + const existingUuser = await db('users').where({ username }).first(); + if (existingUuser) { + res.status(400); + return res.json({ + error: 'Username already taken.', + }); + } + + const pwHash = sha512(salt + password); + const sessionId = shortid.generate(); + const user = (await db('users').insert({ username, password: pwHash }).returning('*'))[0]; + await db('tokens').insert({ user_id: user.id, type: 'session', value: sessionId }); + + res.set('Set-Cookie', buildSessionCookie({ sessionId, remember: false, isLogout: false })); + return res.json({ + username, + }); +}); + +normalRouter.post('/login', async (req, res) => { + const { username, password, remember } = req.body; + if (!username || !password) { + res.status(400); + return res.json({ + error: 'Username or password missing.', + }); + } + + const user = await db('users').where({ username }).first(); + + if (user) { + const sessionId = shortid.generate(); + await db('tokens').insert({ user_id: user.id, type: 'session', value: sessionId }); + + res.set('Set-Cookie', buildSessionCookie({ sessionId, remember, isLogout: false })); + + return res.json({ + username, + }); + } + + res.status(403); + res.json({ + error: 'Wrong username or password', + }); +}); + +authedRouter.post('/logout', async (req, res) => { + if (req.user && req.sessionId) { + await db('tokens').where({ value: req.sessionId }).delete(); + } + res.status(204); + res.set('Set-Cookie', buildSessionCookie({ isLogout: true })); + res.send(); +}); + +authedRouter.get('/user', (req, res) => { + const user = req.user; + return res.json({ + message: `Hello user ${user.username}!`, + username: user.username, + }); +}); + +module.exports = { authedRouter, normalRouter }; |
