24 lines
1.7 KiB
TypeScript
24 lines
1.7 KiB
TypeScript
|
|
import type { FastifyInstance } from 'fastify';
|
||
|
|
import { randomUUID } from 'node:crypto';
|
||
|
|
import { hash } from '@node-rs/argon2';
|
||
|
|
import * as OTPAuth from 'otpauth';
|
||
|
|
import { run } from '../src/core/db.js';
|
||
|
|
|
||
|
|
export interface Client { cookie: string; csrf: string }
|
||
|
|
export async function makeUser(o: { email: string; kind?: 'customer' | 'staff'; staffRole?: string; password?: string }) {
|
||
|
|
const id = randomUUID();
|
||
|
|
await run("INSERT INTO users (id,email,name,password_hash,kind,staff_role,status) VALUES (?,?,?,?,?,?, 'active')", [id, o.email, o.email, await hash(o.password ?? 'correct-horse-battery'), o.kind ?? 'customer', o.staffRole ?? null]);
|
||
|
|
return id;
|
||
|
|
}
|
||
|
|
export async function login(app: FastifyInstance, email: string, password = 'correct-horse-battery'): Promise<{ res: any; client: Client }> {
|
||
|
|
const res = await app.inject({ method: 'POST', url: '/v1/auth/login', payload: { email, password } });
|
||
|
|
const cookie = (res.cookies[0] ? `${res.cookies[0].name}=${res.cookies[0].value}` : '');
|
||
|
|
const body = res.json();
|
||
|
|
return { res, client: { cookie, csrf: body.csrf } };
|
||
|
|
}
|
||
|
|
export const call = (app: FastifyInstance, c: Client, method: 'GET' | 'POST' | 'PATCH' | 'PUT' | 'DELETE', url: string, payload?: unknown) =>
|
||
|
|
app.inject({ method, url: `/v1${url}`, payload: payload as never, headers: { cookie: c.cookie, 'x-csrf-token': c.csrf } });
|
||
|
|
export const code = (secret: string) => new OTPAuth.TOTP({ secret: OTPAuth.Secret.fromBase32(secret), digits: 6, period: 30 }).generate();
|
||
|
|
/** Nächster gültiger Code (für zweiten Schritt innerhalb desselben Tests, da Wiederverwendung verboten ist). */
|
||
|
|
export const nextCode = (secret: string) => new OTPAuth.TOTP({ secret: OTPAuth.Secret.fromBase32(secret), digits: 6, period: 30 }).generate({ timestamp: Date.now() + 30000 });
|