79 lines
3.2 KiB
TypeScript
79 lines
3.2 KiB
TypeScript
import { NextResponse } from 'next/server'
|
||
import { cookies } from 'next/headers'
|
||
import { verifySharedJwt } from '@/lib/jwt'
|
||
import { isLldapAdmin } from '@/lib/ldap'
|
||
import { queryLldap, execLldap, esc } from '@/lib/lldap-db'
|
||
import { execFileSync } from 'child_process'
|
||
|
||
async function getLldapInfo(username: string): Promise<{ email: string; displayName: string }> {
|
||
try {
|
||
const safe = esc(username)
|
||
const out = queryLldap(`SELECT email, display_name FROM users WHERE user_id = '${safe}'`)
|
||
const parts = out.split('|')
|
||
return { email: parts[0] || '', displayName: parts[1] || username }
|
||
} catch { return { email: '', displayName: username } }
|
||
}
|
||
|
||
export async function GET() {
|
||
try {
|
||
const cookieStore = await cookies()
|
||
const token = cookieStore.get('tlyq_session')?.value
|
||
if (!token) return NextResponse.json({ error: '未登录' }, { status: 401 })
|
||
|
||
const payload = verifySharedJwt(token)
|
||
if (!payload) return NextResponse.json({ error: '会话已过期' }, { status: 401 })
|
||
|
||
const [admin, info] = await Promise.all([
|
||
isLldapAdmin(payload.username),
|
||
getLldapInfo(payload.username),
|
||
])
|
||
|
||
return NextResponse.json({
|
||
user: { username: payload.username, displayName: info.displayName, email: info.email, isAdmin: admin },
|
||
})
|
||
} catch {
|
||
return NextResponse.json({ error: '获取用户信息失败' }, { status: 500 })
|
||
}
|
||
}
|
||
|
||
export async function PUT(request: Request) {
|
||
try {
|
||
const cookieStore = await cookies()
|
||
const token = cookieStore.get('tlyq_session')?.value
|
||
if (!token) return NextResponse.json({ error: '未登录' }, { status: 401 })
|
||
|
||
const payload = verifySharedJwt(token)
|
||
if (!payload) return NextResponse.json({ error: '会话已过期' }, { status: 401 })
|
||
|
||
const { email } = await request.json()
|
||
if (email !== '' && !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
|
||
return NextResponse.json({ error: '邮箱格式不合法' }, { status: 400 })
|
||
}
|
||
|
||
const safeUser = esc(payload.username)
|
||
const safeEmail = esc(email || '')
|
||
const d = new Date()
|
||
const now = `${d.getFullYear()}-${String(d.getMonth()+1).padStart(2,'0')}-${String(d.getDate()).padStart(2,'0')} ${String(d.getHours()).padStart(2,'0')}:${String(d.getMinutes()).padStart(2,'0')}:${String(d.getSeconds()).padStart(2,'0')}`
|
||
|
||
// docker exec lldap 更新邮箱(LLDAP DELETE 模式不可并发写)
|
||
execLldap(`UPDATE users SET email = '${safeEmail}', lowercase_email = LOWER('${safeEmail}'), modified_date = '${now}' WHERE user_id = '${safeUser}'`)
|
||
|
||
// 同步更新 assets / issue 本地用户表
|
||
const assetsDb = process.env.ASSETS_DB_PATH || '/data/other-sites/assets/assets.db'
|
||
const issueDb = process.env.ISSUE_DB_PATH || '/data/other-sites/issue/issue.db'
|
||
for (const dbPath of [assetsDb, issueDb]) {
|
||
try {
|
||
execFileSync('sqlite3', [dbPath], {
|
||
input: `UPDATE users SET email = '${safeEmail}', updated_at = datetime('now', '+8 hours') WHERE username = '${safeUser}';`,
|
||
timeout: 3000,
|
||
})
|
||
} catch {}
|
||
}
|
||
|
||
return NextResponse.json({ success: true, email: email || '' })
|
||
} catch (e) {
|
||
const msg = e instanceof Error ? e.message : '修改失败'
|
||
return NextResponse.json({ error: msg }, { status: 500 })
|
||
}
|
||
}
|