Skip to content

fix: retain omitted name subattributes on PUT /Users#106

Open
nicolamacoir wants to merge 2 commits into
Metatavu:developfrom
nicolamacoir:fix/put-user-omitted-name-subattributes
Open

fix: retain omitted name subattributes on PUT /Users#106
nicolamacoir wants to merge 2 commits into
Metatavu:developfrom
nicolamacoir:fix/put-user-omitted-name-subattributes

Conversation

@nicolamacoir
Copy link
Copy Markdown
Contributor

Summary

  • Fixes PUT /Users clears name.familyName / name.givenName when the subattribute is omitted from the request body #105PUT /Users/{id} with a partial name object (e.g. only givenName) silently cleared the other subattribute (familyName), inconsistent with how other omitted readWrite attributes are handled.
  • UsersController.updateUser now guards each name.* write on a non-null subattribute value, matching the existing handling for emails and additionalProperties.
  • Per RFC 7644 §3.5.1: "Attributes whose mutability is 'readWrite' that are omitted from the request body MAY be assumed to be unchanged." That carries over to subattributes.

Changes

  • UsersController.java:234-241 — only write name.givenName / name.familyName when the corresponding value is non-null.
  • RealmUserUpdateTestsIT.testReplaceUserRetainsOmittedNameSubattributes — regression test that creates a user with both givenName and familyName set, PUTs with only givenName, and asserts the existing familyName is retained both in the SCIM response and in the underlying Keycloak user.

Test plan

  • ./gradlew test --tests "fi.metatavu.keycloak.scim.server.test.tests.functional.RealmUserUpdateTestsIT" passes
  • Existing testReplaceUser (full-payload PUT) still passes — partial-name handling does not regress the full-replace case
  • Manually verify a partial-name PUT no longer clears the omitted subattribute

Note on clearing values

This PR makes omitted name.* subattributes "no change" rather than "clear", which is the consistent interpretation of the RFC. Clients that need to clear a name subattribute should use PATCH op: remove (the normative SCIM way to clear attributes), or send an empty string if the deployment allows it.

UsersController.updateUser wrote name.givenName and name.familyName
unconditionally whenever the parent "name" object was present in the
request body, so a payload with only one of the two subattributes
silently cleared the other.

Sibling top-level attributes (emails, additionalProperties like
displayName / preferredLanguage / externalId) are already gated and
correctly retained when omitted. Only the name.* subattributes were
written through with null. Per RFC 7644 §3.5.1, omitted readWrite
attributes MAY be assumed to be unchanged — applies to subattributes
too.

Guard each name.* write on a non-null subattribute value so the
behaviour matches the rest of the resource.

Adds a regression test that PUTs with only name.givenName and
asserts the existing name.familyName is retained.

Closes Metatavu#105
@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Jun 1, 2026

@nicolamacoir nicolamacoir requested a review from msegurar02 June 1, 2026 10:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PUT /Users clears name.familyName / name.givenName when the subattribute is omitted from the request body

1 participant