// GET /api/admin/webauthn/keys — every enrolled security key across all users (tenant admins). // Backs the overview page /users/security-keys. Reads the credential index fresh (no cache) and // never returns public keys or the vaulted password blocks. import { isAdminRole } from '../../../utils/changeLogHelper' import fetchHelper from '../../../utils/fetchHelper' import { listAllCredentials } from '../../../utils/webauthnIndex' export default defineEventHandler(async (event) => { const token = getCookie(event, 'logship_it') ?? '' const userId = Number(getCookie(event, 'logship_user_id')) if (!token || !userId) throw createError({ statusCode: 401, statusMessage: 'Not authenticated' }) if (!(await isAdminRole(event, token))) { throw createError({ statusCode: 403, statusMessage: 'Tenant administrator role required' }) } const creds = await listAllCredentials(event, true) const adminIds = Array.from(new Set(creds.map(c => c.key.enrolledBy).filter((x): x is number => !!x))) // Resolve the enrolling admins' names (service token, one small call per distinct admin). const names = new Map() const byId = new Map() for (const c of creds) byId.set(c.userId, c.userName) for (const id of adminIds) { if (byId.has(id)) { names.set(id, byId.get(id)!); continue } try { const serviceToken: string | undefined = (useRuntimeConfig().api as any)?.idempieretoken const rec: any = await fetchHelper(event, 'models/ad_user/' + id + '?$select=Name', 'GET', serviceToken ?? token, null) names.set(id, String(rec?.Name ?? rec?.name ?? id)) } catch { names.set(id, String(id)) } } return { keys: creds.map(c => ({ userId: c.userId, userName: c.userName, userValue: c.userValue, credentialId: c.key.credentialId, nickname: c.key.nickname, createdAt: c.key.createdAt, lastUsedAt: c.key.lastUsedAt ?? null, transports: c.key.transports ?? [], enrolledBy: c.key.enrolledBy ?? null, enrolledByName: c.key.enrolledBy ? (names.get(c.key.enrolledBy) ?? String(c.key.enrolledBy)) : null, })), } })