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, cookies: string[], expectedRedirectUrl: string = '/', ): Promise { const mail: Record | 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, cookies: string[], csrf: string, ): Promise { // 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 { return async (addr, port) => { return new class extends TestApp { protected async init(): Promise { 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[] { const migrations = withUsername ? super.getMigrations() : super.getMigrations().filter(m => m !== AddNameToUsersMigration); return migrations; } }('test', addr, port, true, approvalMode); }; }