feat(ST-xmwvqru1): admin jobs-actions (cancelJob, deleteJob)

- lib/session.ts: isAdmin: boolean toegevoegd
- lib/auth-guard.ts: requireAdmin() toegevoegd
- actions/admin/jobs.ts: cancelJobAction (CUID-validatie, eindstatus-check → CANCELLED),
  deleteJobAction (hard delete) — beide 'use server', revalidatePath('/admin/jobs')
This commit is contained in:
Scrum4Me Agent 2026-05-05 14:47:11 +02:00
parent 64b8c7f5d7
commit 788920b790
3 changed files with 50 additions and 0 deletions

41
actions/admin/jobs.ts Normal file
View file

@ -0,0 +1,41 @@
'use server'
import { revalidatePath } from 'next/cache'
import { z } from 'zod'
import { prisma } from '@/lib/prisma'
import { requireAdmin } from '@/lib/auth-guard'
const cuidSchema = z.string().cuid()
export async function cancelJobAction(jobId: string) {
await requireAdmin()
const parsed = cuidSchema.safeParse(jobId)
if (!parsed.success) throw new Error('Ongeldig job-id')
const job = await prisma.claudeJob.findUnique({
where: { id: parsed.data },
select: { status: true },
})
if (!job) throw new Error('Job niet gevonden')
if (job.status === 'DONE' || job.status === 'FAILED' || job.status === 'CANCELLED') {
throw new Error('Job is al in eindstatus')
}
await prisma.claudeJob.update({
where: { id: parsed.data },
data: { status: 'CANCELLED', finished_at: new Date() },
})
revalidatePath('/admin/jobs')
}
export async function deleteJobAction(jobId: string) {
await requireAdmin()
const parsed = cuidSchema.safeParse(jobId)
if (!parsed.success) throw new Error('Ongeldig job-id')
await prisma.claudeJob.delete({ where: { id: parsed.data } })
revalidatePath('/admin/jobs')
}

View file

@ -22,3 +22,11 @@ export async function requireSession() {
return session return session
} }
export async function requireAdmin() {
const session = await getSession()
if (!session.userId || !session.isAdmin) {
redirect('/dashboard')
}
return session
}

View file

@ -3,6 +3,7 @@ import { SessionOptions } from 'iron-session'
export interface SessionData { export interface SessionData {
userId: string userId: string
isDemo: boolean isDemo: boolean
isAdmin: boolean
// ST-1002 (M10) — gezet door /api/auth/pair/claim na een succesvolle QR-pairing. // ST-1002 (M10) — gezet door /api/auth/pair/claim na een succesvolle QR-pairing.
// Beide velden zijn optioneel zodat bestaande wachtwoord-sessies onveranderd blijven. // Beide velden zijn optioneel zodat bestaande wachtwoord-sessies onveranderd blijven.
paired?: boolean paired?: boolean