2020-04-24 12:12:27 +02:00
|
|
|
import ApplicationComponent from "../ApplicationComponent";
|
2020-09-25 22:03:22 +02:00
|
|
|
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";
|
2020-09-25 22:03:22 +02:00
|
|
|
import Middleware from "../Middleware";
|
|
|
|
import User from "./models/User";
|
|
|
|
import AuthProof from "./AuthProof";
|
2020-04-24 12:12:27 +02:00
|
|
|
|
2020-09-25 22:03:22 +02:00
|
|
|
export default class AuthComponent extends ApplicationComponent {
|
|
|
|
private readonly authGuard: AuthGuard<AuthProof<User>>;
|
2020-04-24 12:12:27 +02:00
|
|
|
|
2020-09-25 22:03:22 +02:00
|
|
|
public constructor(authGuard: AuthGuard<AuthProof<User>>) {
|
2020-04-24 12:12:27 +02:00
|
|
|
super();
|
|
|
|
this.authGuard = authGuard;
|
|
|
|
}
|
|
|
|
|
2020-09-25 22:03:22 +02:00
|
|
|
public async init(): Promise<void> {
|
|
|
|
this.use(AuthMiddleware);
|
2020-04-24 12:12:27 +02:00
|
|
|
}
|
2020-09-23 08:46:37 +02:00
|
|
|
|
2020-09-25 22:03:22 +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
|
|
|
}
|
|
|
|
|
2020-09-25 22:03:22 +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
|
|
|
|
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();
|
|
|
|
|
|
|
|
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
|
|
|
|
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-09-25 22:03:22 +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
|
|
|
}
|
2020-09-25 22:03:22 +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
|
|
|
|
2020-09-25 22:03:22 +02:00
|
|
|
next();
|
2020-04-24 12:12:27 +02:00
|
|
|
}
|
2020-09-25 22:03:22 +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
|
|
|
|
2020-09-25 22:03:22 +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();
|
|
|
|
}
|
|
|
|
}
|