diff --git a/login.html b/login.html new file mode 100644 index 0000000..b0d6d13 --- /dev/null +++ b/login.html @@ -0,0 +1,68 @@ + + + + + + + Login - Timetable V2 + + + +
+

Timetable V2

+
+ + +
+
+ + diff --git a/server/api/auth.js b/server/api/auth.js new file mode 100644 index 0000000..962606e --- /dev/null +++ b/server/api/auth.js @@ -0,0 +1,32 @@ +export class Auth { + activeSessions = []; + constructor() {} + login = (req, res) => { + if (!req.body.password) { + res.status(401).sendFile("login.html", { root: "../" }); + return; + } else { + if (req.body.password == process.env.AUTH_PASSWORD) { + const sessionId = Math.random().toString(36).slice(-8); + this.activeSessions.push(sessionId); + res.cookie("session", sessionId, { httpOnly: true }); + res.redirect("/"); + } else { + res.status(401).sendFile("login.html", { root: "../" }); + return; + } + } + }; + checkLogin = (req, res, next) => { + if (!req.cookies.session) { + res.status(401).sendFile("login.html", { root: "../" }); + return; + } else { + if (!this.activeSessions.includes(req.cookies.session)) { + res.status(401).sendFile("login.html", { root: "../" }); + return; + } + } + next(); + }; +} diff --git a/server/index.js b/server/index.js index 0035ac7..ce65066 100644 --- a/server/index.js +++ b/server/index.js @@ -5,12 +5,18 @@ import { getHistory, getClasses, } from "./api/index.js"; +import { Auth } from "./api/auth.js"; import { Parser } from "./parser/index.js"; import cors from "cors"; +import cookieParser from "cookie-parser"; const app = express(); const port = process.env.PORT || 3000; app.use(cors()); +app.use(cookieParser()); +app.use(express.urlencoded({ extended: true })); + +const auth = new Auth(); if (!process.env.DSB_USER || !process.env.DSB_PASSWORD) { console.error("Error: DSB Auth environment variables missing!"); @@ -22,6 +28,9 @@ const parser = new Parser( process.env.UPDATE_INTERVAL || 1 * 60 * 1000 ); +app.post("/login", auth.login); +app.use(auth.checkLogin); + app.get("/api/timetable", getTimetable); app.get("/api/substitutions", getSubstitutions); app.get("/api/history", getHistory); diff --git a/server/package-lock.json b/server/package-lock.json index 3db61f9..2b065a9 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -12,6 +12,7 @@ "@prisma/client": "^3.13.0", "axios": "^0.27.2", "cheerio": "^1.0.0-rc.10", + "cookie-parser": "^1.4.6", "cors": "^2.8.5", "express": "^4.18.1" } @@ -193,6 +194,26 @@ "node": ">= 0.6" } }, + "node_modules/cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "dependencies": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/cookie-parser/node_modules/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==", + "engines": { + "node": ">= 0.6" + } + }, "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", @@ -1007,6 +1028,22 @@ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==" }, + "cookie-parser": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.6.tgz", + "integrity": "sha512-z3IzaNjdwUC2olLIB5/ITd0/setiaFMLYiZJle7xg5Fe9KWAceil7xszYfHHBtDFYLSgJduS2Ty0P1uJdPDJeA==", + "requires": { + "cookie": "0.4.1", + "cookie-signature": "1.0.6" + }, + "dependencies": { + "cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-ZwrFkGJxUR3EIoXtO+yVE69Eb7KlixbaeAWfBQB9vVsNn/o+Yw69gBWSSDK825hQNdN+wF8zELf3dFNl/kxkUA==" + } + } + }, "cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", diff --git a/server/package.json b/server/package.json index 52669f3..9b7cf80 100644 --- a/server/package.json +++ b/server/package.json @@ -13,6 +13,7 @@ "@prisma/client": "^3.13.0", "axios": "^0.27.2", "cheerio": "^1.0.0-rc.10", + "cookie-parser": "^1.4.6", "cors": "^2.8.5", "express": "^4.18.1" }