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 };