summaryrefslogtreecommitdiffstats
path: root/backend/src/routes.js
diff options
context:
space:
mode:
Diffstat (limited to 'backend/src/routes.js')
-rw-r--r--backend/src/routes.js133
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 };