swaf/src/auth/AuthComponent.ts

112 lines
3.4 KiB
TypeScript
Raw Normal View History

2020-04-24 12:12:27 +02:00
import ApplicationComponent from "../ApplicationComponent";
import {NextFunction, Request, Response} from "express";
2020-04-24 12:12:27 +02:00
import AuthGuard from "./AuthGuard";
import Controller from "../Controller";
import {ForbiddenHttpError} from "../HttpError";
import Middleware from "../Middleware";
import User from "./models/User";
import AuthProof from "./AuthProof";
2020-04-24 12:12:27 +02:00
export default class AuthComponent extends ApplicationComponent {
private readonly authGuard: AuthGuard<AuthProof<User>>;
2020-04-24 12:12:27 +02:00
public constructor(authGuard: AuthGuard<AuthProof<User>>) {
2020-04-24 12:12:27 +02:00
super();
this.authGuard = authGuard;
}
public async init(): Promise<void> {
this.use(AuthMiddleware);
2020-04-24 12:12:27 +02:00
}
2020-09-23 08:46:37 +02:00
public getAuthGuard(): AuthGuard<AuthProof<User>> {
2020-09-23 08:46:37 +02:00
return this.authGuard;
}
2020-04-24 12:12:27 +02:00
}
export class AuthMiddleware extends Middleware {
private authGuard?: AuthGuard<AuthProof<User>>;
private user: User | null = null;
2020-06-16 11:12:58 +02:00
protected async handle(req: Request, res: Response, next: NextFunction): Promise<void> {
this.authGuard = this.app.as(AuthComponent).getAuthGuard();
const proof = await this.authGuard.isAuthenticated(req.session!);
if (proof) {
this.user = await proof.getResource();
res.locals.user = this.user;
}
2020-04-24 12:12:27 +02:00
next();
}
public getUser(): User | null {
return this.user;
2020-04-24 12:12:27 +02:00
}
public getAuthGuard(): AuthGuard<AuthProof<User>> {
if (!this.authGuard) throw new Error('AuthGuard was not initialized.');
return this.authGuard;
2020-04-24 12:12:27 +02:00
}
}
export class RequireRequestAuthMiddleware extends Middleware {
protected async handle(req: Request, res: Response, next: NextFunction): Promise<void> {
const proof = await req.as(AuthMiddleware).getAuthGuard().isAuthenticatedViaRequest(req);
if (!proof) {
req.flash('error', `You must be logged in to access ${req.url}.`);
res.redirect(Controller.route('auth', undefined, {
redirect_uri: req.url,
}));
return;
}
2020-04-24 12:12:27 +02:00
next();
2020-04-24 12:12:27 +02:00
}
}
export class RequireAuthMiddleware extends Middleware {
protected async handle(req: Request, res: Response, next: NextFunction): Promise<void> {
const authGuard = req.as(AuthMiddleware).getAuthGuard();
// Via request
if (await authGuard.isAuthenticatedViaRequest(req)) {
next();
return;
}
// Via session
if (!await authGuard.isAuthenticated(req.session!)) {
req.flash('error', `You must be logged in to access ${req.url}.`);
res.redirect(Controller.route('auth', undefined, {
redirect_uri: req.url,
}));
return;
}
2020-04-24 12:12:27 +02:00
next();
}
}
export class RequireGuestMiddleware extends Middleware {
protected async handle(req: Request, res: Response, next: NextFunction): Promise<void> {
if (await req.as(AuthMiddleware).getAuthGuard().isAuthenticated(req.session!)) {
res.redirectBack();
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();
}
}