/* ---------------------------------------------------------------------------- Question Server GitLab: This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ------------------------------------------------------------------------- */ import type { Response, NextFunction, RequestHandler } from 'express' import type { Request, User } from '../types/basicTypes' import type { Database } from 'better-sqlite3' import logger from '../utils/logger' import dbtools from '../utils/dbtools' import { paths } from '../utils/files' import utils from '../utils/utils' const domain = utils.ReadFile(paths.domainFile).trim() interface Options { userDB: Database exceptions: Array } export const testUser: User = { id: 1, avaiblePWRequests: 645, pwRequestCount: 19, created: new Date().getTime(), lastLogin: new Date().getTime(), lastAccess: new Date().getTime(), pw: '5d146f72-e1b8-4440-a6e3-f22f31810316', loginCount: 3, createdBy: 1, } function renderLogin(req: Request, res: Response) { res.status(401) // Unauthorized if (req.is('application/json')) { res.json({ result: 'nouser', msg: 'You are not logged in', }) } else { res.render('login', { useHttp: process.env.NS_NO_HTTPS_FORCE, domain: domain, }) } } export default function (options: Options): RequestHandler { const { userDB, exceptions, }: { userDB: Database exceptions: string[] } = options return function (req: Request, res: Response, next: NextFunction) { const sessionID = req.cookies.sessionID const isException = exceptions.some((exc) => { return req.originalUrl.split('?')[0] === exc }) if (process.env.NS_NOUSER) { req.session = { user: testUser, sessionID: sessionID || 11111111111, isException: false, } next() return } // FIXME Allowing all urls with _next in it, but not in params if ( req.url.split('?')[0].includes('_next') || req.url.split('?')[0].includes('well-known/acme-challenge') ) { req.session = { isException: true } next() return } if (!sessionID) { if (isException) { logger.DebugLog(`EXCEPTION: ${req.url}`, 'auth', 1) req.session = { isException: true } next() return } logger.DebugLog(`No session ID: ${req.url}`, 'auth', 1) renderLogin(req, res) return } const user = GetUserBySessionID(userDB, sessionID) if (!user) { if (isException) { logger.DebugLog(`EXCEPTION: ${req.url}`, 'auth', 1) req.session = { isException: true } next() return } logger.DebugLog(`No user:${req.url}`, 'auth', 1) renderLogin(req, res) return } req.session = { user: user, sessionID: sessionID, isException: isException, } logger.DebugLog(`ID #${user.id}: ${req.url}`, 'auth', 1) dbtools.Update( userDB, 'sessions', { lastAccess: new Date().getTime(), }, { id: sessionID, } ) dbtools.Update( userDB, 'users', { lastAccess: new Date().getTime(), }, { id: user.id, } ) next() } } function GetUserBySessionID(db: Database, sessionID: string) { logger.DebugLog(`Getting user from db`, 'auth', 2) const session = dbtools.Select(db, 'sessions', { id: sessionID, })[0] if (!session) { return } const user = dbtools.Select(db, 'users', { id: session.userID, })[0] if (user) { return user } }