summaryrefslogtreecommitdiffstats
path: root/backend/src
diff options
context:
space:
mode:
authorJan Tuomi <jan.tuomi@eficode.com>2020-02-01 16:33:56 +0200
committerJan Tuomi <jan.tuomi@eficode.com>2020-02-01 16:33:56 +0200
commita5ae2653d8ccdaf00270c0c8c8a30b88d7955114 (patch)
treebd265901dbda512fb1f6d717beb545234468d7ec /backend/src
parentfbf108595a00a7c9db5984158e4b02cc345b68d1 (diff)
Do stuff
Diffstat (limited to 'backend/src')
-rw-r--r--backend/src/db.js4
-rw-r--r--backend/src/index.js22
-rw-r--r--backend/src/routes.js133
3 files changed, 159 insertions, 0 deletions
diff --git a/backend/src/db.js b/backend/src/db.js
new file mode 100644
index 0000000..2573239
--- /dev/null
+++ b/backend/src/db.js
@@ -0,0 +1,4 @@
+const config = require('../knexfile')[process.env.NODE_ENV || 'development'];
+const knex = require('knex')(config);
+
+module.exports = knex;
diff --git a/backend/src/index.js b/backend/src/index.js
new file mode 100644
index 0000000..128ed60
--- /dev/null
+++ b/backend/src/index.js
@@ -0,0 +1,22 @@
+const express = require('express');
+const bodyParser = require('body-parser');
+const cookieParser = require('cookie-parser');
+const morgan = require('morgan');
+const routes = require('./routes');
+
+const app = express();
+
+app.use(morgan('dev'));
+app.use(bodyParser.json());
+app.use(cookieParser());
+app.use((req, res, next) => {
+ res.set('Access-Control-Allow-Origin', 'http://localhost:3000');
+ res.set('Access-Control-Allow-Headers', 'Content-Type');
+ res.set('Access-Control-Allow-Credentials', true);
+ next();
+});
+app.use(routes.normalRouter);
+app.use(routes.authedRouter);
+
+const port = 4000;
+app.listen(port, () => console.log(`App listening on http://localhost:${port}!`));
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 };