mirror of
https://github.com/velocitatem/cvfs.git
synced 2026-07-16 03:13:36 +00:00
feat(dashboard): complete CV branching dashboard with auth and full editing workflow
- Visual branch heritage tree with colored dots and connecting lines, depth-aware expand/collapse - Dashboard 3-tab layout: Content (inline block editing + patch staging), Patches (diff view), Submissions (AI suggestions) - Inline block editing: click to edit any CV block, stage edits, save as named branch with pre-filled patches - Submissions tab: create applications, request AI tailoring suggestions, accept/reject per suggestion - Simple hardcoded login (username/password via env vars LOGIN_USER/LOGIN_PASS, defaults admin/admin) - Authentik OIDC integration: authorize redirect + callback exchange, configurable via NEXT_PUBLIC_AUTHENTIK_* - Middleware protecting /dashboard with session cookie verification (HMAC-SHA256) - Auth API routes: /api/auth/login, /api/auth/logout, /api/auth/callback, /api/auth/token - Backend: GET/PATCH submission routes for listing submissions and accepting/rejecting AI suggestions - API client: OIDC bearer token forwarding from client-readable cookie https://claude.ai/code/session_01CdisLhbC2kVt2hxfJ7TNPf
This commit is contained in:
27
apps/webapp/src/app/api/auth/login/route.ts
Normal file
27
apps/webapp/src/app/api/auth/login/route.ts
Normal file
@@ -0,0 +1,27 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import crypto from 'node:crypto';
|
||||
|
||||
const SECRET = process.env.SESSION_SECRET ?? 'dev-secret-change-in-production';
|
||||
const LOGIN_USER = process.env.LOGIN_USER ?? 'admin';
|
||||
const LOGIN_PASS = process.env.LOGIN_PASS ?? 'admin';
|
||||
|
||||
function sign(value: string) {
|
||||
return crypto.createHmac('sha256', SECRET).update(value).digest('hex');
|
||||
}
|
||||
|
||||
export async function POST(req: NextRequest) {
|
||||
const body = await req.json().catch(() => ({}));
|
||||
const { username, password } = body as Record<string, string>;
|
||||
if (!username || !password || username !== LOGIN_USER || password !== LOGIN_PASS) {
|
||||
return NextResponse.json({ error: 'Invalid credentials' }, { status: 401 });
|
||||
}
|
||||
const payload = `${username}:${Date.now()}`;
|
||||
const token = `${payload}.${sign(payload)}`;
|
||||
const res = NextResponse.json({ ok: true });
|
||||
res.cookies.set('session', token, {
|
||||
httpOnly: true, sameSite: 'lax', path: '/',
|
||||
maxAge: 60 * 60 * 24 * 7,
|
||||
secure: process.env.NODE_ENV === 'production',
|
||||
});
|
||||
return res;
|
||||
}
|
||||
Reference in New Issue
Block a user