55 lines
2.2 KiB
TypeScript
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 })
|
|
}
|
|
}
|