swaf/test/_authentication_common.ts

101 lines
4.1 KiB
TypeScript

import supertest from "supertest";
import AuthComponent from "../src/auth/AuthComponent.js";
import AddApprovedFieldToUsersTableMigration from "../src/auth/migrations/AddApprovedFieldToUsersTableMigration.js";
import AddNameToUsersMigration from "../src/auth/migrations/AddNameToUsersMigration.js";
import MagicLink from "../src/auth/models/MagicLink.js";
import PasswordAuthProof from "../src/auth/password/PasswordAuthProof.js";
import CsrfProtectionComponent from "../src/components/CsrfProtectionComponent.js";
import Controller from "../src/Controller.js";
import Migration, {MigrationType} from "../src/db/Migration.js";
import TestApp from "../src/TestApp.js";
import {AppSupplier} from "./_app.js";
import {popEmail} from "./_mail_server.js";
export async function followMagicLinkFromMail(
agent: supertest.SuperTest<supertest.Test>,
cookies: string[],
expectedRedirectUrl: string = '/',
): Promise<void> {
const mail: Record<string, unknown> | null = await popEmail();
expect(mail).not.toBeNull();
const query = (mail?.text as string).split('/magic/link?')[1].split('\n')[0];
expect(query).toBeDefined();
await agent.get('/magic/link?' + query)
.expect(200);
await agent.get('/magic/lobby')
.set('Cookie', cookies)
.expect(302)
.expect('Location', expectedRedirectUrl);
}
export async function testLogout(
agent: supertest.SuperTest<supertest.Test>,
cookies: string[],
csrf: string,
): Promise<void> {
// Authenticated
await agent.get('/is-auth').set('Cookie', cookies).expect(200);
// Logout
await agent.post('/auth/logout')
.set('Cookie', cookies)
.send({csrf: csrf})
.expect(302);
// Not authenticated
await agent.get('/is-auth').set('Cookie', cookies).expect(401);
}
export function authAppProvider(withUsername: boolean = true, approvalMode: boolean = false): AppSupplier<TestApp> {
return async (addr, port) => {
return new class extends TestApp {
protected async init(): Promise<void> {
this.use(new class extends Controller {
public routes(): void {
this.get('/', (req, res) => {
res.render('home');
}, 'home');
this.get('/csrf', (req, res) => {
res.send(CsrfProtectionComponent.getCsrfToken(req.getSession()));
}, 'csrf');
this.get('/is-auth', async (req, res) => {
const proofs = await this.getApp().as(AuthComponent).getAuthGuard().getProofs(req);
if (proofs.length > 0) res.sendStatus(200);
else res.sendStatus(401);
}, 'is-auth');
this.get('/has-any-password-auth-proof', async (req, res) => {
const proof = await PasswordAuthProof.getProofForSession(req.getSession());
if (proof) res.sendStatus(200);
else res.sendStatus(404);
}, 'is-auth');
this.get('/has-any-magic-link', async (req, res) => {
const proofs = await MagicLink.select()
.where('session_id', req.getSession().id)
.get();
if (proofs.length > 0) res.sendStatus(200);
else res.sendStatus(404);
}, 'is-auth');
}
}());
await super.init();
}
protected getMigrations(): MigrationType<Migration>[] {
let migrations = withUsername ?
super.getMigrations() :
super.getMigrations().filter(m => m !== AddNameToUsersMigration);
migrations = approvalMode ?
[...migrations, AddApprovedFieldToUsersTableMigration] :
migrations;
return migrations;
}
}('test', addr, port, true);
};
}