| |
| |
| |
| |
| |
| |
|
|
| import { NextRequest, NextResponse } from 'next/server'; |
| import { timingSafeEqual } from 'crypto'; |
| import { createSession } from '@/lib/auth/session'; |
| import { getUserByEmail, getUserDefaultWorkspace, getWorkspaceById, getUserCount } from '@/lib/auth/system-database'; |
| import { ensureDefaultWorkspace } from '@/lib/auth/default-workspace'; |
| import { verifyPassword } from '@/lib/auth/passwords'; |
| import { logger } from '@/lib/utils'; |
|
|
| export async function POST(request: NextRequest) { |
| try { |
| const body = await request.json(); |
| const { email, password } = body; |
|
|
| if (!password) { |
| return NextResponse.json({ error: 'Password required' }, { status: 400 }); |
| } |
|
|
| |
| if (email) { |
| const user = getUserByEmail(email); |
| if (!user) { |
| return NextResponse.json({ error: 'Invalid email or password' }, { status: 401 }); |
| } |
|
|
| const valid = await verifyPassword(password, user.password_hash); |
| if (!valid) { |
| return NextResponse.json({ error: 'Invalid email or password' }, { status: 401 }); |
| } |
|
|
| |
| await ensureDefaultWorkspace(user.id); |
|
|
| const token = await createSession(user.id, user.email, user.is_admin === 1); |
| const defaultWorkspaceId = getUserDefaultWorkspace(user.id); |
| const defaultWorkspaceName = defaultWorkspaceId ? getWorkspaceById(defaultWorkspaceId)?.name : undefined; |
| const response = NextResponse.json({ success: true, defaultWorkspaceId, defaultWorkspaceName }); |
| response.cookies.set('osw_session', token, { |
| httpOnly: true, |
| secure: process.env.SECURE_COOKIES !== 'false' && process.env.NODE_ENV === 'production', |
| sameSite: 'lax', |
| maxAge: 24 * 60 * 60, |
| path: '/', |
| }); |
| return response; |
| } |
|
|
| |
| const adminPassword = process.env.ADMIN_PASSWORD; |
| const userCount = getUserCount(); |
|
|
| if (!adminPassword || userCount > 0) { |
| return NextResponse.json( |
| { error: userCount > 0 ? 'Please log in with your email and password' : 'Authentication not configured' }, |
| { status: userCount > 0 ? 400 : 500 } |
| ); |
| } |
|
|
| const passwordsMatch = (() => { |
| try { |
| const a = Buffer.from(password); |
| const b = Buffer.from(adminPassword); |
| if (a.length !== b.length) return false; |
| return timingSafeEqual(a, b); |
| } catch { |
| return false; |
| } |
| })(); |
| if (!passwordsMatch) { |
| return NextResponse.json({ error: 'Invalid password' }, { status: 401 }); |
| } |
|
|
| |
| const adminWorkspaceId = await ensureDefaultWorkspace('admin'); |
|
|
| const token = await createSession('admin', 'admin@localhost', true); |
| const adminWorkspaceName = getWorkspaceById(adminWorkspaceId)?.name; |
| const response = NextResponse.json({ success: true, defaultWorkspaceId: adminWorkspaceId, defaultWorkspaceName: adminWorkspaceName }); |
| response.cookies.set('osw_session', token, { |
| httpOnly: true, |
| secure: process.env.SECURE_COOKIES !== 'false' && process.env.NODE_ENV === 'production', |
| sameSite: 'lax', |
| maxAge: 24 * 60 * 60, |
| path: '/', |
| }); |
| return response; |
| } catch (error) { |
| logger.error('[API /api/auth/login] Error:', error); |
| return NextResponse.json( |
| { error: error instanceof Error ? error.message : 'Login failed' }, |
| { status: 500 } |
| ); |
| } |
| } |
|
|