import type { GuildMember } from '@/lib/auth/discord' export const SIGN_IN_ERRORS = { notInGuild: 'keine-mitgliedschaft', notAfis: 'keine-afis-rolle', discordUnreachable: 'discord-nicht-erreichbar', } as const export type SignInReason = (typeof SIGN_IN_ERRORS)[keyof typeof SIGN_IN_ERRORS] export type SignInDecision = { ok: true } | { ok: false; reason: SignInReason } /** * Wer darf sich anmelden. * * Bewusst als eigene Funktion und nicht im Auth.js-Callback vergraben: das ist * die Regel, an der alles hängt, und sie gehört einzeln prüfbar. * * - Kein Mitglied der Guild → abgelehnt. Es wird kein Konto angelegt. * - Mitglied ohne Rolle mit `grantsMembership` → abgelehnt. Auf dem * AfiS-Discord sind auch Gäste, die keine Akte sehen dürfen. * - Notfall-Admin → durchgelassen, aber nur solange er Mitglied der Guild * ist. Sonst bliebe die Hintertür auch nach einem Rauswurf offen. * * Siehe docs/03-auth-und-rechte.md und docs/13-entscheidungen.md. */ export function decideSignIn(input: { member: GuildMember | null isBootstrapAdmin: boolean grantingRoleCount: number }): SignInDecision { if (!input.member) return { ok: false, reason: SIGN_IN_ERRORS.notInGuild } if (input.isBootstrapAdmin) return { ok: true } if (input.grantingRoleCount === 0) return { ok: false, reason: SIGN_IN_ERRORS.notAfis } return { ok: true } }