'use server' import { revalidatePath } from 'next/cache' import { cookies } from 'next/headers' import { getIronSession } from 'iron-session' import { createHash, randomBytes } from 'crypto' import { prisma } from '@/lib/prisma' import { SessionData, sessionOptions } from '@/lib/session' import { enforceUserRateLimit } from '@/lib/rate-limit' async function getSession() { return getIronSession(await cookies(), sessionOptions) } export async function createApiTokenAction(_prevState: unknown, formData: FormData) { const session = await getSession() if (!session.userId) return { error: 'Niet ingelogd' } if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus' } const limited = enforceUserRateLimit('create-token', session.userId) if (limited) return limited const label = (formData.get('label') as string | null)?.trim() || null // Max 10 active tokens const activeCount = await prisma.apiToken.count({ where: { user_id: session.userId, revoked_at: null }, }) if (activeCount >= 10) return { error: 'Maximaal 10 actieve tokens toegestaan' } const rawToken = randomBytes(32).toString('hex') const tokenHash = createHash('sha256').update(rawToken).digest('hex') await prisma.apiToken.create({ data: { user_id: session.userId, token_hash: tokenHash, label, }, }) revalidatePath('/settings/tokens') // Return the raw token once — it won't be retrievable later return { success: true, token: rawToken } } export async function revokeApiTokenAction(id: string) { const session = await getSession() if (!session.userId) return { error: 'Niet ingelogd' } if (session.isDemo) return { error: 'Niet beschikbaar in demo-modus' } const token = await prisma.apiToken.findFirst({ where: { id, user_id: session.userId }, }) if (!token) return { error: 'Token niet gevonden' } await prisma.apiToken.update({ where: { id }, data: { revoked_at: new Date() }, }) revalidatePath('/settings/tokens') return { success: true } }