From 8af5354f22a70ea55e08316656368e60dd32e634 Mon Sep 17 00:00:00 2001 From: Scrum4Me Agent <30029041+madhura68@users.noreply.github.com> Date: Tue, 5 May 2026 14:22:04 +0200 Subject: [PATCH] feat(ST-nma6ylbl): SessionData isAdmin + loginAction admin-redirect + must_reset_password-interceptie MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - SessionData: isAdmin: boolean toegevoegd (na isDemo) - loginAction: UserRole-query voor ADMIN, session.isAdmin gezet, redirect-volgorde: must_reset_password → /reset-password, adminRole → /admin, phone-UA, dashboard - registerAction: session.isAdmin = false - pair/claim route: session.isAdmin = false (QR-pairing is geen admin-flow) --- actions/auth.ts | 13 +++++++++++++ app/api/auth/pair/claim/route.ts | 1 + lib/session.ts | 1 + 3 files changed, 15 insertions(+) diff --git a/actions/auth.ts b/actions/auth.ts index 575178e..b4c0d59 100644 --- a/actions/auth.ts +++ b/actions/auth.ts @@ -4,6 +4,7 @@ import { redirect } from 'next/navigation' import { cookies, headers } from 'next/headers' import { getIronSession } from 'iron-session' import { z } from 'zod' +import { prisma } from '@/lib/prisma' import { registerUser, verifyUser } from '@/lib/auth' import { SessionData, sessionOptions } from '@/lib/session' import { checkRateLimit } from '@/lib/rate-limit' @@ -45,6 +46,7 @@ export async function registerAction(_prevState: unknown, formData: FormData) { const session = await getIronSession(await cookies(), sessionOptions) session.userId = result.user!.id session.isDemo = false + session.isAdmin = false await session.save() redirect('/dashboard') @@ -70,11 +72,22 @@ export async function loginAction(_prevState: unknown, formData: FormData) { return { error: 'Onjuiste gebruikersnaam of wachtwoord' } } + const adminRole = await prisma.userRole.findFirst({ + where: { user_id: user.id, role: 'ADMIN' }, + }) + const session = await getIronSession(await cookies(), sessionOptions) session.userId = user.id session.isDemo = user.is_demo + session.isAdmin = !!adminRole await session.save() + if (user.must_reset_password) { + redirect('/reset-password') + } else if (adminRole) { + redirect('/admin') + } + // PBI-11 / ST-1135: telefoon-UA's krijgen de mobile-shell. // Tablets en desktop volgen het bestaande /dashboard-pad. const ua = (await headers()).get('user-agent') diff --git a/app/api/auth/pair/claim/route.ts b/app/api/auth/pair/claim/route.ts index 555cd39..40d27b8 100644 --- a/app/api/auth/pair/claim/route.ts +++ b/app/api/auth/pair/claim/route.ts @@ -88,6 +88,7 @@ export async function POST(request: Request) { const session = await getIronSession(await cookies(), sessionOptions) session.userId = pairing.user_id session.isDemo = pairing.user?.is_demo ?? false + session.isAdmin = false session.paired = true session.pairedExpiresAt = Date.now() + PAIRED_TTL_MS await session.save() diff --git a/lib/session.ts b/lib/session.ts index bf1f9a9..5d7c587 100644 --- a/lib/session.ts +++ b/lib/session.ts @@ -3,6 +3,7 @@ import { SessionOptions } from 'iron-session' export interface SessionData { userId: string isDemo: boolean + isAdmin: boolean // ST-1002 (M10) — gezet door /api/auth/pair/claim na een succesvolle QR-pairing. // Beide velden zijn optioneel zodat bestaande wachtwoord-sessies onveranderd blijven. paired?: boolean