export const dynamic = 'force-dynamic'; export const runtime = 'nodejs'; import { NextRequest, NextResponse } from 'next/server'; import { supabase } from '@/lib/supabase'; import { hashPassword, verifyPassword } from '@/lib/password'; const DEFAULT_OWNER_USERNAME = 'baicaimiao'; const DEFAULT_OWNER_PASSWORD = 'baicaimiao123'; const DEFAULT_OWNER_NAME = '兜爸'; export async function POST(request: NextRequest) { const body = await request.json().catch(() => ({})); const username = typeof body.username === 'string' ? body.username.trim() : ''; const password = typeof body.password === 'string' ? body.password : ''; if (!username || !password) { return NextResponse.json({ error: '请输入账号和密码' }, { status: 400 }); } const { data: userByUsername, error: usernameError } = await supabase .from('users') .select('id,name,role,avatar_url,username,password_hash,created_at,updated_at') .eq('username', username) .maybeSingle(); if (usernameError) { return NextResponse.json({ error: usernameError.message }, { status: 500 }); } if (userByUsername?.password_hash) { const ok = verifyPassword(password, userByUsername.password_hash); if (!ok) { return NextResponse.json({ error: '账号或密码错误' }, { status: 401 }); } const { password_hash, ...safeUser } = userByUsername as any; const res = NextResponse.json({ user: safeUser }); res.cookies.set('okr_user_id', safeUser.id, { httpOnly: true, sameSite: 'lax', secure: process.env.NODE_ENV === 'production', path: '/', }); return res; } if (username === DEFAULT_OWNER_USERNAME && password === DEFAULT_OWNER_PASSWORD) { const { data: ownerUser, error: ownerError } = await supabase .from('users') .select('id,name,role,avatar_url,username,password_hash,created_at,updated_at') .eq('role', 'owner') .order('created_at', { ascending: true }) .limit(1) .maybeSingle(); if (ownerError) { return NextResponse.json({ error: ownerError.message }, { status: 500 }); } const passwordHash = hashPassword(DEFAULT_OWNER_PASSWORD); if (ownerUser) { const { data: updated, error: updateError } = await supabase .from('users') .update({ name: DEFAULT_OWNER_NAME, username: DEFAULT_OWNER_USERNAME, password_hash: passwordHash, role: 'owner', updated_at: new Date().toISOString(), }) .eq('id', ownerUser.id) .select('id,name,role,avatar_url,username,created_at,updated_at') .single(); if (updateError) { return NextResponse.json({ error: updateError.message }, { status: 500 }); } const res = NextResponse.json({ user: updated }); res.cookies.set('okr_user_id', updated.id, { httpOnly: true, sameSite: 'lax', secure: process.env.NODE_ENV === 'production', path: '/', }); return res; } const { data: created, error: createError } = await supabase .from('users') .insert({ name: DEFAULT_OWNER_NAME, role: 'owner', avatar_url: null, username: DEFAULT_OWNER_USERNAME, password_hash: passwordHash, }) .select('id,name,role,avatar_url,username,created_at,updated_at') .single(); if (createError) { return NextResponse.json({ error: createError.message }, { status: 500 }); } const res = NextResponse.json({ user: created }); res.cookies.set('okr_user_id', created.id, { httpOnly: true, sameSite: 'lax', secure: process.env.NODE_ENV === 'production', path: '/', }); return res; } return NextResponse.json({ error: '账号或密码错误' }, { status: 401 }); }