fix(auth): self-healing displayName; drop synthetic Member<sub> from storage

The legend showed 'Member 972be1a3' because Authelia does not emit
name/preferred_username/email in the ID TOKEN (only at the userinfo endpoint),
and @hono/oidc-auth reads ID-token claims only. The real fix is an Authelia
claims_policy adding those claims to id_token for the familysync client.

App-side robustness so it self-heals once Authelia is fixed (no DB surgery):
- deriveDisplayName now returns null (not a synthetic 'Member <sub>') when no
  real claim is present, so we never persist an ugly sub string; the UI degrades
  to a generic 'Member'.
- upsertUser now tracks the IdP name authoritatively: a non-null displayName that
  differs from the stored value updates the row (blank/stale 'Member …'/email →
  real name on next login). A null value never overwrites a good stored name.
This commit is contained in:
Lucas Berger
2026-06-07 16:17:17 -04:00
parent 98753d8e34
commit 2c8f1a28af
3 changed files with 27 additions and 15 deletions
+1 -1
View File
@@ -69,7 +69,7 @@ async function resolveUserId(c: any): Promise<number | null> {
// Derive displayName via the shared helper (name → preferred_username → email
// → sub fallback) so the write-path upsert agrees with me.ts and never
// overwrites a correctly-derived name with a worse one.
const displayName = deriveDisplayName(auth, sub)
const displayName = deriveDisplayName(auth)
const user = await upsertUser(iss, sub, displayName)
return user?.id ?? null