oa-ai/src/app/api/auth/setup-password/route.ts

55 lines
2.2 KiB
TypeScript

import { NextResponse } from 'next/server'
import { exec } from 'child_process'
import { promisify } from 'util'
import { verifySetupToken } from '@/lib/setup-token'
const execAsync = promisify(exec)
export async function POST(request: Request) {
try {
const { token, password } = await request.json()
if (!token || !password) {
return NextResponse.json({ error: '参数不完整' }, { status: 400 })
}
const payload = verifySetupToken(token)
if (!payload) {
return NextResponse.json({ error: '链接已过期或无效,请联系管理员重新创建账号' }, { status: 403 })
}
if (password.length < 8) {
return NextResponse.json({ error: '密码至少 8 位' }, { status: 400 })
}
const hasUpper = /[A-Z]/.test(password)
const hasLower = /[a-z]/.test(password)
const hasDigit = /[0-9]/.test(password)
const hasSpecial = /[^A-Za-z0-9]/.test(password)
const score = [hasUpper, hasLower, hasDigit, hasSpecial].filter(Boolean).length
if (score < 3) {
return NextResponse.json({ error: '密码需包含大写字母、小写字母、数字、特殊字符中至少 3 种' }, { status: 400 })
}
const { stdout: adminPassOut } = await execAsync(
'docker exec lldap printenv LLDAP_ADMIN_PASSWORD', { timeout: 3000 }
)
const adminPass = (adminPassOut.trim() || 'admin123').replace(/'/g, "'\\''")
const safeUser = payload.username.replace(/'/g, "'\\''")
const safePass = password.replace(/'/g, "'\\''")
const cmd = `docker exec lldap ./lldap_set_password --base-url http://localhost:17170 --admin-username admin --admin-password '${adminPass}' --username '${safeUser}' --password '${safePass}'`
const { stderr } = await execAsync(cmd, { timeout: 10000 })
if (stderr && !stderr.includes('Successfully')) {
return NextResponse.json({ error: stderr.trim() || '设置失败' }, { status: 500 })
}
return NextResponse.json({ success: true })
} catch (err) {
const msg = err instanceof Error ? err.message : '设置失败'
if (msg.includes('command not found') || msg.includes('No such container')) {
return NextResponse.json({ error: '密码服务不可用' }, { status: 503 })
}
return NextResponse.json({ error: msg }, { status: 500 })
}
}