fix: /api/auth/me 从 LLDAP 实时读取 displayName(非 JWT 缓存)
- 修改显示名后右上角个人信息即时更新 - RoleManager 支持 onUserUpdated 回调刷新用户信息
This commit is contained in:
parent
868c79891f
commit
ae1e58a595
|
|
@ -264,7 +264,7 @@ export default function AdminUsersPage() {
|
|||
)}
|
||||
|
||||
{/* ====== 权限管理 ====== */}
|
||||
{tab === 'roles' && <RoleManager setResult={showResult} />}
|
||||
{tab === 'roles' && <RoleManager setResult={showResult} onUserUpdated={fetchLoginUser} />}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ interface RoleData {
|
|||
emails: Record<string, string>
|
||||
}
|
||||
|
||||
interface Props { setResult: (ok: boolean, msg: string) => void }
|
||||
interface Props { setResult: (ok: boolean, msg: string) => void; onUserUpdated?: () => void }
|
||||
|
||||
const ss = {
|
||||
bar: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } as React.CSSProperties,
|
||||
|
|
@ -23,7 +23,7 @@ const ss = {
|
|||
miniBtn: (primary: boolean) => ({ padding: '4px 12px', borderRadius: 5, border: primary ? 'none' : '1px solid var(--border)', background: primary ? '#2563eb' : 'var(--bg-card)', color: primary ? '#fff' : 'var(--text-secondary)', fontSize: 11, cursor: 'pointer', fontWeight: 500 } as React.CSSProperties),
|
||||
}
|
||||
|
||||
export default function RoleManager({ setResult }: Props) {
|
||||
export default function RoleManager({ setResult, onUserUpdated }: Props) {
|
||||
const [roleData, setRoleData] = useState<RoleData | null>(null)
|
||||
const [pending, setPending] = useState<Record<string, { site: string; newRole: string }>>({})
|
||||
const [saving, setSaving] = useState(false)
|
||||
|
|
@ -69,7 +69,7 @@ export default function RoleManager({ setResult }: Props) {
|
|||
assetsUsers: prev.assetsUsers.map(u => u.username === target ? { ...u, display_name: d.displayName } : u),
|
||||
issueUsers: prev.issueUsers.map(u => u.username === target ? { ...u, display_name: d.displayName } : u),
|
||||
} : null)
|
||||
setEditingDisplayName(null); setResult(true, `${target} 显示名已更新`)
|
||||
setEditingDisplayName(null); setResult(true, `${target} 显示名已更新`); onUserUpdated?.()
|
||||
} else { setResult(false, d.error || '修改失败') }
|
||||
} catch { setResult(false, '网络错误') }
|
||||
finally { setSavingDisplayName(false) }
|
||||
|
|
|
|||
|
|
@ -7,15 +7,16 @@ import { isLldapAdmin } from '@/lib/ldap'
|
|||
|
||||
const execAsync = promisify(exec)
|
||||
|
||||
async function getLldapEmail(username: string): Promise<string> {
|
||||
async function getLldapInfo(username: string): Promise<{ email: string; displayName: string }> {
|
||||
try {
|
||||
const safeUser = username.replace(/'/g, "''")
|
||||
const { stdout } = await execAsync(
|
||||
`docker exec lldap /bin/sh -c "echo 'SELECT email FROM users WHERE user_id='\\''${safeUser}'\\'';' | sqlite3 /data/users.db"`,
|
||||
`docker exec lldap /bin/sh -c "echo 'SELECT email, display_name FROM users WHERE user_id='\\''${safeUser}'\\'';' | sqlite3 /data/users.db"`,
|
||||
{ timeout: 3000 }
|
||||
)
|
||||
return stdout.trim() || ''
|
||||
} catch { return '' }
|
||||
const parts = stdout.trim().split('|')
|
||||
return { email: parts[0] || '', displayName: parts[1] || username }
|
||||
} catch { return { email: '', displayName: username } }
|
||||
}
|
||||
|
||||
export async function GET() {
|
||||
|
|
@ -27,13 +28,13 @@ export async function GET() {
|
|||
const payload = verifySharedJwt(token)
|
||||
if (!payload) return NextResponse.json({ error: '会话已过期' }, { status: 401 })
|
||||
|
||||
const [admin, email] = await Promise.all([
|
||||
const [admin, info] = await Promise.all([
|
||||
isLldapAdmin(payload.username),
|
||||
getLldapEmail(payload.username),
|
||||
getLldapInfo(payload.username),
|
||||
])
|
||||
|
||||
return NextResponse.json({
|
||||
user: { username: payload.username, displayName: payload.displayName, email, isAdmin: admin },
|
||||
user: { username: payload.username, displayName: info.displayName, email: info.email, isAdmin: admin },
|
||||
})
|
||||
} catch {
|
||||
return NextResponse.json({ error: '获取用户信息失败' }, { status: 500 })
|
||||
|
|
|
|||
Loading…
Reference in New Issue