import { afterAll, beforeAll, describe, expect, it } from 'vitest' import { createPrismaClient, type PrismaClient } from '@afis/db' import { enforceMembership, handleDeparture } from '../src/sync.js' /** * „Rollenentzug in Discord beendet laufende Sitzungen" aus * docs/03-auth-und-rechte.md. * * Das Zeitbudget von fünf Sekunden ist im Betrieb die Summe aus * Gateway-Ereignis und diesem Schritt. Geprüft wird hier der Schritt, der in * unserer Hand liegt: die Sitzungen müssen weg sein, und der Datensatz muss * stehen bleiben, damit Autorenangaben in alten Akten gültig bleiben. */ const url = process.env.DIRECT_DATABASE_URL ?? process.env.DATABASE_URL const suite = url ? describe : describe.skip let db: PrismaClient const marke = `worker-${Date.now()}` const rolleAfis = `${marke}-afis` const rolleGast = `${marke}-gast` suite('Sitzungen beim Rollenentzug', () => { beforeAll(async () => { db = createPrismaClient(url) await db.roleMapping.createMany({ data: [ { discordRoleId: rolleAfis, label: 'AfiS', category: 'MEMBERSHIP', grantsMembership: true }, { discordRoleId: rolleGast, label: 'Gast', category: 'UNSORTED' }, ], }) }) afterAll(async () => { await db.$disconnect() }) async function nutzerMitSitzung(id: string, rollen: string[]): Promise { await db.user.create({ data: { id, username: id, displayName: id } }) if (rollen.length > 0) { await db.userRole.createMany({ data: rollen.map((discordRoleId) => ({ userId: id, discordRoleId })), }) } await db.session.create({ data: { userId: id, expiresAt: new Date(Date.now() + 86_400_000) }, }) } it('lässt eine Sitzung stehen, solange die AfiS-Rolle vorliegt', async () => { const id = `${marke}-bleibt` await nutzerMitSitzung(id, [rolleAfis]) const beendet = await enforceMembership(db, id) expect(beendet).toBe(false) expect(await db.session.count({ where: { userId: id } })).toBe(1) }) it('beendet alle Sitzungen, sobald die AfiS-Rolle fehlt', async () => { const id = `${marke}-verliert` await nutzerMitSitzung(id, [rolleAfis, rolleGast]) await db.session.create({ data: { userId: id, expiresAt: new Date(Date.now() + 86_400_000) }, }) expect(await db.session.count({ where: { userId: id } })).toBe(2) // Rollenentzug in Discord, hier direkt nachgestellt. await db.userRole.deleteMany({ where: { userId: id, discordRoleId: rolleAfis } }) const start = Date.now() const beendet = await enforceMembership(db, id) const dauer = Date.now() - start expect(beendet).toBe(true) expect(await db.session.count({ where: { userId: id } })).toBe(0) expect(dauer).toBeLessThan(5000) // Der Datensatz bleibt, nur inaktiv. const nutzer = await db.user.findUnique({ where: { id } }) expect(nutzer).not.toBeNull() expect(nutzer?.isActive).toBe(false) }) it('beendet Sitzungen beim Serveraustritt und behält den Nutzer', async () => { const id = `${marke}-austritt` await nutzerMitSitzung(id, [rolleAfis]) await handleDeparture(db, id) expect(await db.session.count({ where: { userId: id } })).toBe(0) expect(await db.userRole.count({ where: { userId: id } })).toBe(0) const nutzer = await db.user.findUnique({ where: { id } }) expect(nutzer?.isActive).toBe(false) }) })