feat: ST-001–ST-005 foundation — scaffolding, Prisma, schema, seed, env
- ST-001: Next.js 16 + React 19 + TypeScript strict + Tailwind + shadcn/ui + all deps - ST-002: Prisma v7 setup with better-sqlite3 adapter (local) and pg adapter (cloud) - ST-003: Full schema migration (users, pbis, stories, sprints, tasks, todos, api_tokens) - ST-004: Seed with 9 PBIs, ~40 stories, demo user (demo/demo1234), lars user - ST-005: Zod-validated env vars, .env.example, lib/session, lib/auth, lib/api-auth Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
4cf5833c1d
commit
7f94bb6359
32 changed files with 8653 additions and 183 deletions
68
actions/auth.ts
Normal file
68
actions/auth.ts
Normal file
|
|
@ -0,0 +1,68 @@
|
|||
'use server'
|
||||
|
||||
import { redirect } from 'next/navigation'
|
||||
import { cookies } from 'next/headers'
|
||||
import { getIronSession } from 'iron-session'
|
||||
import { z } from 'zod'
|
||||
import { registerUser, verifyUser } from '@/lib/auth'
|
||||
import { SessionData, sessionOptions } from '@/lib/session'
|
||||
|
||||
const registerSchema = z.object({
|
||||
username: z.string().min(3, 'Gebruikersnaam moet minimaal 3 tekens bevatten').max(50),
|
||||
password: z.string().min(8, 'Wachtwoord moet minimaal 8 tekens bevatten'),
|
||||
})
|
||||
|
||||
const loginSchema = z.object({
|
||||
username: z.string().min(1),
|
||||
password: z.string().min(1),
|
||||
})
|
||||
|
||||
export async function registerAction(formData: FormData) {
|
||||
const parsed = registerSchema.safeParse({
|
||||
username: formData.get('username'),
|
||||
password: formData.get('password'),
|
||||
})
|
||||
|
||||
if (!parsed.success) {
|
||||
return { error: parsed.error.flatten().fieldErrors }
|
||||
}
|
||||
|
||||
const result = await registerUser(parsed.data.username, parsed.data.password)
|
||||
if (result.error) return { error: result.error }
|
||||
|
||||
const session = await getIronSession<SessionData>(await cookies(), sessionOptions)
|
||||
session.userId = result.user!.id
|
||||
session.isDemo = false
|
||||
await session.save()
|
||||
|
||||
redirect('/dashboard')
|
||||
}
|
||||
|
||||
export async function loginAction(formData: FormData) {
|
||||
const parsed = loginSchema.safeParse({
|
||||
username: formData.get('username'),
|
||||
password: formData.get('password'),
|
||||
})
|
||||
|
||||
if (!parsed.success) {
|
||||
return { error: 'Ongeldige inloggegevens' }
|
||||
}
|
||||
|
||||
const user = await verifyUser(parsed.data.username, parsed.data.password)
|
||||
if (!user) {
|
||||
return { error: 'Onjuiste gebruikersnaam of wachtwoord' }
|
||||
}
|
||||
|
||||
const session = await getIronSession<SessionData>(await cookies(), sessionOptions)
|
||||
session.userId = user.id
|
||||
session.isDemo = user.is_demo
|
||||
await session.save()
|
||||
|
||||
redirect('/dashboard')
|
||||
}
|
||||
|
||||
export async function logoutAction() {
|
||||
const session = await getIronSession<SessionData>(await cookies(), sessionOptions)
|
||||
session.destroy()
|
||||
redirect('/login')
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue