feat(auth): make profile names Bunyip-owned and read-only #481
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/PMS-512-bunyip-owned-profile-names"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Bunyip is the identity source of truth, so mokosh's
users.first_name/users.last_namebecome a read-only local cache refreshed from thegiven_name/family_nameclaims on every login, andfirst_name/last_name/phonestop being editable through the mokosh API.upsert_user_from_oidc'sON CONFLICT (id) DO UPDATEbranch now overwrites both name columns from the raw hints instead of leaving them at their seeded value. The hints bind as NULL when absent or empty after trimming, soCOALESCEkeeps the existing value and neitherNOT NULLcolumn is ever written as an empty string or clobbered by the synthetic email-derived placeholder.That upsert only runs on first sight of a
sub, so the already-provisioned path needed the other half:place_bunyip_usernow calls the newAuthService::refresh_names_from_oidcwhen a non-empty claim differs from the cached value. The bunyip branch runs per request rather than per login, hence the change check before the write.UpdateUserRequestdropsfirst_name,last_name, andphone, which removes them from bothPUT /meand the adminPUT /users/{id}; the conditional UPDATE builder and the name-drivenprofile_completed_atstamp inupdate_usergo with them (that stamp now comes solely from the login whose claims carry both names).GET /mestill returns all three for display and the columns stay in place as an inert cache, so every query that joinsusersfor a display name is untouched. Nophone_numberextraction is added; sourcing phone from Bunyip stays deferred.Tests pin the contract mechanically:
put_me_cannot_mutate_bunyip_owned_profile_fieldsfails if any of the three fields is re-added to the request type, and three bunyip-login tests cover refresh-on-every-login, the absent/empty-hint guard, and theON CONFLICTbranch directly.#PMS-512
Bunyip is the identity source of truth, so mokosh's `users.first_name` / `users.last_name` become a read-only local cache refreshed from the `given_name` / `family_name` claims on every login, and `first_name` / `last_name` / `phone` stop being editable through the mokosh API. `upsert_user_from_oidc`'s `ON CONFLICT (id) DO UPDATE` branch now overwrites both name columns from the raw hints instead of leaving them at their seeded value. The hints bind as NULL when absent or empty after trimming, so `COALESCE` keeps the existing value and neither `NOT NULL` column is ever written as an empty string or clobbered by the synthetic email-derived placeholder. That upsert only runs on first sight of a `sub`, so the already-provisioned path needed the other half: `place_bunyip_user` now calls the new `AuthService::refresh_names_from_oidc` when a non-empty claim differs from the cached value. The bunyip branch runs per request rather than per login, hence the change check before the write. `UpdateUserRequest` drops `first_name`, `last_name`, and `phone`, which removes them from both `PUT /me` and the admin `PUT /users/{id}`; the conditional UPDATE builder and the name-driven `profile_completed_at` stamp in `update_user` go with them (that stamp now comes solely from the login whose claims carry both names). `GET /me` still returns all three for display and the columns stay in place as an inert cache, so every query that joins `users` for a display name is untouched. No `phone_number` extraction is added; sourcing phone from Bunyip stays deferred. Tests pin the contract mechanically: `put_me_cannot_mutate_bunyip_owned_profile_fields` fails if any of the three fields is re-added to the request type, and three bunyip-login tests cover refresh-on-every-login, the absent/empty-hint guard, and the `ON CONFLICT` branch directly. #PMS-512