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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ interface RoleData {
|
||||||
emails: Record<string, string>
|
emails: Record<string, string>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Props { setResult: (ok: boolean, msg: string) => void }
|
interface Props { setResult: (ok: boolean, msg: string) => void; onUserUpdated?: () => void }
|
||||||
|
|
||||||
const ss = {
|
const ss = {
|
||||||
bar: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 20 } as React.CSSProperties,
|
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),
|
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 [roleData, setRoleData] = useState<RoleData | null>(null)
|
||||||
const [pending, setPending] = useState<Record<string, { site: string; newRole: string }>>({})
|
const [pending, setPending] = useState<Record<string, { site: string; newRole: string }>>({})
|
||||||
const [saving, setSaving] = useState(false)
|
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),
|
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),
|
issueUsers: prev.issueUsers.map(u => u.username === target ? { ...u, display_name: d.displayName } : u),
|
||||||
} : null)
|
} : null)
|
||||||
setEditingDisplayName(null); setResult(true, `${target} 显示名已更新`)
|
setEditingDisplayName(null); setResult(true, `${target} 显示名已更新`); onUserUpdated?.()
|
||||||
} else { setResult(false, d.error || '修改失败') }
|
} else { setResult(false, d.error || '修改失败') }
|
||||||
} catch { setResult(false, '网络错误') }
|
} catch { setResult(false, '网络错误') }
|
||||||
finally { setSavingDisplayName(false) }
|
finally { setSavingDisplayName(false) }
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,16 @@ import { isLldapAdmin } from '@/lib/ldap'
|
||||||
|
|
||||||
const execAsync = promisify(exec)
|
const execAsync = promisify(exec)
|
||||||
|
|
||||||
async function getLldapEmail(username: string): Promise<string> {
|
async function getLldapInfo(username: string): Promise<{ email: string; displayName: string }> {
|
||||||
try {
|
try {
|
||||||
const safeUser = username.replace(/'/g, "''")
|
const safeUser = username.replace(/'/g, "''")
|
||||||
const { stdout } = await execAsync(
|
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 }
|
{ timeout: 3000 }
|
||||||
)
|
)
|
||||||
return stdout.trim() || ''
|
const parts = stdout.trim().split('|')
|
||||||
} catch { return '' }
|
return { email: parts[0] || '', displayName: parts[1] || username }
|
||||||
|
} catch { return { email: '', displayName: username } }
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function GET() {
|
export async function GET() {
|
||||||
|
|
@ -27,13 +28,13 @@ export async function GET() {
|
||||||
const payload = verifySharedJwt(token)
|
const payload = verifySharedJwt(token)
|
||||||
if (!payload) return NextResponse.json({ error: '会话已过期' }, { status: 401 })
|
if (!payload) return NextResponse.json({ error: '会话已过期' }, { status: 401 })
|
||||||
|
|
||||||
const [admin, email] = await Promise.all([
|
const [admin, info] = await Promise.all([
|
||||||
isLldapAdmin(payload.username),
|
isLldapAdmin(payload.username),
|
||||||
getLldapEmail(payload.username),
|
getLldapInfo(payload.username),
|
||||||
])
|
])
|
||||||
|
|
||||||
return NextResponse.json({
|
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 {
|
} catch {
|
||||||
return NextResponse.json({ error: '获取用户信息失败' }, { status: 500 })
|
return NextResponse.json({ error: '获取用户信息失败' }, { status: 500 })
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue