Reduce the amount of SQL requests made for authentication
This commit is contained in:
parent
95632f5880
commit
272688da26
@ -15,14 +15,15 @@ export default class AuthComponent extends ApplicationComponent<void> {
|
|||||||
public async init(router: Router): Promise<void> {
|
public async init(router: Router): Promise<void> {
|
||||||
router.use(async (req, res, next) => {
|
router.use(async (req, res, next) => {
|
||||||
req.authGuard = this.authGuard;
|
req.authGuard = this.authGuard;
|
||||||
res.locals.user = await (await req.authGuard.getProofForSession(req.session!))?.getResource();
|
res.locals.user = await (await req.authGuard.getProof(req))?.getResource();
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const REQUIRE_REQUEST_AUTH_MIDDLEWARE = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
export const REQUIRE_REQUEST_AUTH_MIDDLEWARE = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
if (!await req.authGuard.isAuthenticatedViaRequest(req)) {
|
let proof = await req.authGuard.isAuthenticatedViaRequest(req);
|
||||||
|
if (!proof) {
|
||||||
req.flash('error', `You must be logged in to access ${req.url}.`);
|
req.flash('error', `You must be logged in to access ${req.url}.`);
|
||||||
res.redirect(Controller.route('auth', undefined, {
|
res.redirect(Controller.route('auth', undefined, {
|
||||||
redirect_uri: req.url,
|
redirect_uri: req.url,
|
||||||
@ -30,26 +31,31 @@ export const REQUIRE_REQUEST_AUTH_MIDDLEWARE = async (req: Request, res: Respons
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
req.models.user = await (await req.authGuard.getProofForRequest(req))?.getResource();
|
req.models.user = await proof.getResource();
|
||||||
next();
|
next();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const REQUIRE_AUTH_MIDDLEWARE = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
export const REQUIRE_AUTH_MIDDLEWARE = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
if (await req.authGuard.isAuthenticatedViaRequest(req)) {
|
// Via request
|
||||||
req.models.user = await (await req.authGuard.getProofForRequest(req))?.getResource();
|
let proof = await req.authGuard.isAuthenticatedViaRequest(req);
|
||||||
next();
|
if (proof) {
|
||||||
} else {
|
req.models.user = await proof.getResource();
|
||||||
if (!await req.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;
|
|
||||||
}
|
|
||||||
|
|
||||||
req.models.user = await (await req.authGuard.getProofForSession(req.session!))?.getResource();
|
|
||||||
next();
|
next();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Via session
|
||||||
|
proof = await req.authGuard.isAuthenticated(req.session!);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
req.models.user = await proof.getResource();
|
||||||
|
next();
|
||||||
};
|
};
|
||||||
export const REQUIRE_GUEST_MIDDLEWARE = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
export const REQUIRE_GUEST_MIDDLEWARE = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
|
||||||
if (await req.authGuard.isAuthenticated(req.session!)) {
|
if (await req.authGuard.isAuthenticated(req.session!)) {
|
||||||
|
@ -26,7 +26,7 @@ export default abstract class AuthController extends Controller {
|
|||||||
protected abstract async getCheckAuth(req: Request, res: Response, next: NextFunction): Promise<void>;
|
protected abstract async getCheckAuth(req: Request, res: Response, next: NextFunction): Promise<void>;
|
||||||
|
|
||||||
protected async postLogout(req: Request, res: Response, next: NextFunction): Promise<void> {
|
protected async postLogout(req: Request, res: Response, next: NextFunction): Promise<void> {
|
||||||
const proof = await req.authGuard.getProofForSession(req.session!);
|
const proof = await req.authGuard.getProof(req);
|
||||||
await proof?.revoke();
|
await proof?.revoke();
|
||||||
req.flash('success', 'Successfully logged out.');
|
req.flash('success', 'Successfully logged out.');
|
||||||
res.redirect(req.query.redirect_uri?.toString() || '/');
|
res.redirect(req.query.redirect_uri?.toString() || '/');
|
||||||
|
@ -7,15 +7,47 @@ import {PENDING_ACCOUNT_REVIEW_MAIL_TEMPLATE} from "../Mails";
|
|||||||
import Mail from "../Mail";
|
import Mail from "../Mail";
|
||||||
import Controller from "../Controller";
|
import Controller from "../Controller";
|
||||||
import config from "config";
|
import config from "config";
|
||||||
import ModelFactory from "../db/ModelFactory";
|
|
||||||
|
|
||||||
export default abstract class AuthGuard<P extends AuthProof<User>> {
|
export default abstract class AuthGuard<P extends AuthProof<User>> {
|
||||||
public abstract async getProofForSession(session: Express.Session): Promise<P | null>;
|
protected abstract async getProofForSession(session: Express.Session): Promise<P | null>;
|
||||||
|
|
||||||
public async getProofForRequest(req: Request): Promise<P | null> {
|
protected async getProofForRequest(req: Request): Promise<P | null> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async getProof(req: Request): Promise<P | null> {
|
||||||
|
let proof = await this.isAuthenticatedViaRequest(req);
|
||||||
|
if (!proof && req.session) {
|
||||||
|
proof = await this.isAuthenticated(req.session);
|
||||||
|
}
|
||||||
|
return proof;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async isAuthenticated(session: Express.Session): Promise<P | null> {
|
||||||
|
if (!session.is_authenticated) return null;
|
||||||
|
|
||||||
|
const proof = await this.getProofForSession(session);
|
||||||
|
|
||||||
|
if (!proof || !await proof.isValid() || !await proof.isAuthorized()) {
|
||||||
|
await proof?.revoke();
|
||||||
|
session.is_authenticated = false;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return proof;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async isAuthenticatedViaRequest(req: Request): Promise<P | null> {
|
||||||
|
const proof = await this.getProofForRequest(req);
|
||||||
|
|
||||||
|
if (!proof || !await proof.isValid() || !await proof.isAuthorized()) {
|
||||||
|
await proof?.revoke();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return proof;
|
||||||
|
}
|
||||||
|
|
||||||
public async authenticateOrRegister(
|
public async authenticateOrRegister(
|
||||||
session: Express.Session,
|
session: Express.Session,
|
||||||
proof: P,
|
proof: P,
|
||||||
@ -61,28 +93,10 @@ export default abstract class AuthGuard<P extends AuthProof<User>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Login
|
// Login
|
||||||
session.auth_id = user.id;
|
session.is_authenticated = true;
|
||||||
if (onLogin) await onLogin(user);
|
if (onLogin) await onLogin(user);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async isAuthenticated(session: Express.Session): Promise<boolean> {
|
|
||||||
if (typeof session.auth_id !== 'number') return false;
|
|
||||||
|
|
||||||
const proof = await this.getProofForSession(session);
|
|
||||||
|
|
||||||
if (!proof || !await proof.isValid() || !await proof.isAuthorized()) {
|
|
||||||
await proof?.revoke();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public async isAuthenticatedViaRequest(req: Request): Promise<boolean> {
|
|
||||||
const proof = await this.getProofForRequest(req);
|
|
||||||
return Boolean(proof && await proof.isValid() && await proof.isAuthorized());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AuthError extends Error {
|
export class AuthError extends Error {
|
||||||
|
Loading…
Reference in New Issue
Block a user