2020-09-25 22:03:22 +02:00
|
|
|
import {NextFunction, Request, Response} from "express";
|
2021-05-03 19:29:22 +02:00
|
|
|
|
|
|
|
import Application from "../Application.js";
|
|
|
|
import ApplicationComponent from "../ApplicationComponent.js";
|
2021-06-01 14:34:04 +02:00
|
|
|
import {route} from "../common/Routing.js";
|
2021-05-03 19:29:22 +02:00
|
|
|
import {ForbiddenHttpError} from "../HttpError.js";
|
|
|
|
import Middleware from "../Middleware.js";
|
|
|
|
import AuthGuard from "./AuthGuard.js";
|
|
|
|
import AuthMethod from "./AuthMethod.js";
|
|
|
|
import AuthProof from "./AuthProof.js";
|
|
|
|
import User from "./models/User.js";
|
2020-04-24 12:12:27 +02:00
|
|
|
|
2020-09-25 22:03:22 +02:00
|
|
|
export default class AuthComponent extends ApplicationComponent {
|
2020-11-11 19:08:33 +01:00
|
|
|
private readonly authGuard: AuthGuard;
|
2020-04-24 12:12:27 +02:00
|
|
|
|
2020-11-11 19:08:33 +01:00
|
|
|
public constructor(app: Application, ...authMethods: AuthMethod<AuthProof<User>>[]) {
|
2020-04-24 12:12:27 +02:00
|
|
|
super();
|
2020-11-11 19:08:33 +01:00
|
|
|
this.authGuard = new AuthGuard(app, ...authMethods);
|
2020-04-24 12:12:27 +02:00
|
|
|
}
|
|
|
|
|
2021-05-13 16:03:59 +02:00
|
|
|
public async initRoutes(): Promise<void> {
|
2020-09-25 22:03:22 +02:00
|
|
|
this.use(AuthMiddleware);
|
2020-04-24 12:12:27 +02:00
|
|
|
}
|
2020-09-23 08:46:37 +02:00
|
|
|
|
2020-11-11 19:08:33 +01:00
|
|
|
public getAuthGuard(): AuthGuard {
|
2020-09-23 08:46:37 +02:00
|
|
|
return this.authGuard;
|
|
|
|
}
|
2020-04-24 12:12:27 +02:00
|
|
|
}
|
|
|
|
|
2020-09-25 22:03:22 +02:00
|
|
|
export class AuthMiddleware extends Middleware {
|
2020-11-11 19:08:33 +01:00
|
|
|
private authGuard?: AuthGuard;
|
2020-09-25 22:03:22 +02:00
|
|
|
private user: User | null = null;
|
2020-06-16 11:12:58 +02:00
|
|
|
|
2020-09-25 22:03:22 +02:00
|
|
|
protected async handle(req: Request, res: Response, next: NextFunction): Promise<void> {
|
|
|
|
this.authGuard = this.app.as(AuthComponent).getAuthGuard();
|
|
|
|
|
2020-11-11 19:08:33 +01:00
|
|
|
const proofs = await this.authGuard.getProofsForSession(req.getSession());
|
|
|
|
if (proofs.length > 0) {
|
|
|
|
this.user = await proofs[0].getResource();
|
2020-09-25 22:03:22 +02:00
|
|
|
res.locals.user = this.user;
|
|
|
|
}
|
2020-04-24 12:12:27 +02:00
|
|
|
|
2020-06-14 11:59:02 +02:00
|
|
|
next();
|
2020-07-28 11:47:20 +02:00
|
|
|
}
|
2020-06-14 11:59:02 +02:00
|
|
|
|
2020-09-25 22:03:22 +02:00
|
|
|
public getUser(): User | null {
|
|
|
|
return this.user;
|
2020-04-24 12:12:27 +02:00
|
|
|
}
|
2020-07-28 11:47:20 +02:00
|
|
|
|
2020-11-11 19:08:33 +01:00
|
|
|
public getAuthGuard(): AuthGuard {
|
2020-09-25 22:03:22 +02:00
|
|
|
if (!this.authGuard) throw new Error('AuthGuard was not initialized.');
|
|
|
|
return this.authGuard;
|
2020-04-24 12:12:27 +02:00
|
|
|
}
|
2020-09-25 22:03:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export class RequireRequestAuthMiddleware extends Middleware {
|
2020-10-01 13:59:19 +02:00
|
|
|
private user?: User;
|
|
|
|
|
2020-09-25 22:03:22 +02:00
|
|
|
protected async handle(req: Request, res: Response, next: NextFunction): Promise<void> {
|
2020-11-11 19:08:33 +01:00
|
|
|
const proofs = await req.as(AuthMiddleware).getAuthGuard().getProofsForRequest(req);
|
|
|
|
const user = await proofs[0]?.getResource();
|
2020-10-01 13:59:19 +02:00
|
|
|
if (user) {
|
|
|
|
this.user = user;
|
|
|
|
next();
|
2020-09-25 22:03:22 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-04-24 12:12:27 +02:00
|
|
|
|
2020-10-01 13:59:19 +02:00
|
|
|
req.flash('error', `You must be logged in to access ${req.url}.`);
|
2021-06-01 14:34:04 +02:00
|
|
|
res.redirect(route('auth', undefined, {
|
2020-10-01 13:59:19 +02:00
|
|
|
redirect_uri: req.url,
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
public getUser(): User {
|
|
|
|
if (!this.user) throw new Error('user not initialized.');
|
|
|
|
return this.user;
|
2020-04-24 12:12:27 +02:00
|
|
|
}
|
2020-09-25 22:03:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
export class RequireAuthMiddleware extends Middleware {
|
2020-10-01 13:59:19 +02:00
|
|
|
private user?: User;
|
|
|
|
|
2020-09-25 22:03:22 +02:00
|
|
|
protected async handle(req: Request, res: Response, next: NextFunction): Promise<void> {
|
|
|
|
const authGuard = req.as(AuthMiddleware).getAuthGuard();
|
|
|
|
// Via request
|
|
|
|
|
2020-11-11 19:08:33 +01:00
|
|
|
let proofs = await authGuard.getProofsForRequest(req);
|
|
|
|
let user = await proofs[0]?.getResource();
|
2020-10-01 13:59:19 +02:00
|
|
|
if (user) {
|
|
|
|
this.user = user;
|
2020-09-25 22:03:22 +02:00
|
|
|
next();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Via session
|
2020-11-11 19:08:33 +01:00
|
|
|
proofs = await authGuard.getProofsForSession(req.getSession());
|
|
|
|
user = await proofs[0]?.getResource();
|
2020-10-01 13:59:19 +02:00
|
|
|
if (user) {
|
|
|
|
this.user = user;
|
|
|
|
next();
|
2020-09-25 22:03:22 +02:00
|
|
|
return;
|
|
|
|
}
|
2020-04-24 12:12:27 +02:00
|
|
|
|
2020-10-01 13:59:19 +02:00
|
|
|
req.flash('error', `You must be logged in to access ${req.url}.`);
|
2021-06-01 14:34:04 +02:00
|
|
|
res.redirect(route('auth', undefined, {
|
2020-10-01 13:59:19 +02:00
|
|
|
redirect_uri: req.url,
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
|
|
|
public getUser(): User {
|
|
|
|
if (!this.user) throw new Error('user not initialized.');
|
|
|
|
return this.user;
|
2020-09-25 22:03:22 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class RequireGuestMiddleware extends Middleware {
|
|
|
|
protected async handle(req: Request, res: Response, next: NextFunction): Promise<void> {
|
2020-11-11 19:08:33 +01:00
|
|
|
const proofs = await req.as(AuthMiddleware).getAuthGuard().getProofsForSession(req.getSession());
|
|
|
|
if (proofs.length > 0) {
|
2021-06-01 14:34:04 +02:00
|
|
|
res.redirect(route('home'));
|
2020-09-25 22:03:22 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
next();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
export class RequireAdminMiddleware extends Middleware {
|
|
|
|
protected async handle(req: Request, res: Response, next: NextFunction): Promise<void> {
|
|
|
|
const user = req.as(AuthMiddleware).getUser();
|
|
|
|
if (!user || !user.is_admin) {
|
|
|
|
throw new ForbiddenHttpError('secret tool', req.url);
|
|
|
|
}
|
|
|
|
|
|
|
|
next();
|
|
|
|
}
|
|
|
|
}
|