refactor(260607-l6l): extract shared deriveDisplayName helper (BUG 2 DRY)
The displayName claim-preference logic (name → preferred_username → email → sub fallback) was duplicated verbatim in me.ts and events.ts resolveUserId. Extract it to auth/user.ts as deriveDisplayName and use it in both call sites, so the rule has one definition. Update the events.test.ts user.js mock to keep the real helper (spread importActual) while stubbing only upsertUser.
This commit is contained in:
@@ -26,6 +26,34 @@ export const COLOR_PALETTE: string[] = [
|
||||
'#3AAFA9', // teal
|
||||
]
|
||||
|
||||
/** Coerce an OIDC claim to a trimmed non-empty string, else undefined. */
|
||||
const claimStr = (v: unknown): string | undefined =>
|
||||
typeof v === 'string' && v.trim() !== '' ? v.trim() : undefined
|
||||
|
||||
/**
|
||||
* Derive the best available display name from OIDC claims, in preference order:
|
||||
* 1. name — full name set by the IdP (most human-friendly)
|
||||
* 2. preferred_username — often the login handle; still readable
|
||||
* 3. email — readable but reveals contact info; acceptable fallback
|
||||
* 4. `Member <sub>` — sub is always present; never blank
|
||||
*
|
||||
* Shared by every call site that upserts a user (me.ts, events.ts resolveUserId)
|
||||
* so a write-path upsert never overwrites a correctly-derived name with a worse
|
||||
* one. Whether Authelia emits name/preferred_username is an operator config
|
||||
* concern (userinfo scope + claim mappings) — out of scope here.
|
||||
*/
|
||||
export function deriveDisplayName(
|
||||
claims: { name?: unknown; preferred_username?: unknown; email?: unknown },
|
||||
sub: string,
|
||||
): string {
|
||||
return (
|
||||
claimStr(claims.name) ??
|
||||
claimStr(claims.preferred_username) ??
|
||||
claimStr(claims.email) ??
|
||||
`Member ${String(sub).slice(0, 8)}`
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Upsert a user by their OIDC identity (iss + sub).
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user