- 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>
23 lines
716 B
TypeScript
23 lines
716 B
TypeScript
import { createHash } from 'crypto'
|
|
import { prisma } from '@/lib/prisma'
|
|
|
|
export async function authenticateApiRequest(request: Request) {
|
|
const authHeader = request.headers.get('Authorization')
|
|
if (!authHeader?.startsWith('Bearer ')) {
|
|
return { error: 'Unauthorized', status: 401 as const }
|
|
}
|
|
|
|
const token = authHeader.slice(7)
|
|
const tokenHash = createHash('sha256').update(token).digest('hex')
|
|
|
|
const apiToken = await prisma.apiToken.findUnique({
|
|
where: { token_hash: tokenHash },
|
|
include: { user: true },
|
|
})
|
|
|
|
if (!apiToken || apiToken.revoked_at) {
|
|
return { error: 'Unauthorized', status: 401 as const }
|
|
}
|
|
|
|
return { userId: apiToken.user_id, isDemo: apiToken.user.is_demo }
|
|
}
|