101 lines
4.1 KiB
TypeScript
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);
|
|
};
|
|
}
|