import { NextFunction, Request, Response } from "express"; import LoginToken, { CheckToken } from "../../models/login_token"; import Logging from "@hibas123/nodelogging"; import RequestError, { HttpStatusCode } from "../../helper/request_error"; import User from "../../models/user"; import promiseMiddleware from "../../helper/promiseMiddleware"; class Invalid extends Error {} /** * Returns customized Middleware function, that could also be called directly * by code and will return true or false depending on the token. In the false * case it will also send error and redirect if json is not set * @param json Default false. Checks if requests wants an json or html for returning errors * @param special_required Default false. If true, a special token is required * @param redirect_uri Default current uri. Sets the uri to redirect, if json is not set and user not logged in * @param validated Default true. If false, the token must not be validated */ export function GetUserMiddleware( json = false, special_required: boolean = false, redirect_uri?: string, validated = true ) { return promiseMiddleware(async function ( req: Request, res: Response, next?: NextFunction ) { const invalid = (message: string) => { throw new Invalid(req.__(message)); }; try { let { login, special } = req.query; if (!login) { login = req.cookies.login; special = req.cookies.special; } if (!login) invalid("No login token"); if (!special && special_required) invalid("No special token"); let token = await LoginToken.findOne({ token: login, valid: true }); if (!(await CheckToken(token, validated))) invalid("Login token invalid"); let user = await User.findById(token.user); if (!user) { token.valid = false; await LoginToken.save(token); invalid("Login token invalid"); } let special_token; if (special) { Logging.debug("Special found"); special_token = await LoginToken.findOne({ token: special, special: true, valid: true, user: token.user, }); if (!(await CheckToken(special_token, validated))) invalid("Special token invalid"); req.special = true; } req.user = user; req.isAdmin = user.admin; req.token = { login: token, special: special_token, }; if (next) next(); return true; } catch (e) { if (e instanceof Invalid) { if (req.method === "GET" && !json) { res.status(HttpStatusCode.UNAUTHORIZED); res.redirect( "/login?base64=true&state=" + Buffer.from( redirect_uri ? redirect_uri : req.originalUrl ).toString("base64") ); } else { throw new RequestError( req.__( "You are not logged in or your login is expired" + ` (${e.message})` ), HttpStatusCode.UNAUTHORIZED, undefined, { auth: true } ); } } else { if (next) next(e); else throw e; } return false; } }); } export const UserMiddleware = GetUserMiddleware();