Sync realm roles from Keycloak in admin service#423
Sync realm roles from Keycloak in admin service#423
Conversation
iammajid
commented
Mar 16, 2026
- Sync effective realm roles from Keycloak during user sync
- Read back effective roles from Keycloak after role update instead of writing submitted roles directly to DB
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
WalkthroughThe change adds reading of effective realm roles from Keycloak into KeycloakAdminService. In Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
overheadhunter
left a comment
There was a problem hiding this comment.
We deliberately chose to first sync to db and then sync to KC.
This ensures consistency: If DB sync fails, no data will reach KC. If KC sync fails, the DB sync will be rolled back (due to the @Transactional method finishing exceptionally)
There was a problem hiding this comment.
🧹 Nitpick comments (1)
backend/src/main/java/org/cryptomator/hub/keycloak/KeycloakAdminService.java (1)
208-211: Consider extracting the duplicated effective-role mapping into one helper.Both blocks implement the same mapping pipeline; centralizing it reduces drift risk.
♻️ Suggested refactor
@@ - var kcRoleNames = userResource.roles().realmLevel().listEffective().stream() - .map(RoleRepresentation::getName) - .toList(); - dbUser.setRealmRoles(RealmRole.fromKcNames(kcRoleNames).stream().map(RealmRole::kcName).toArray(String[]::new)); + dbUser.setRealmRoles(mapEffectiveRealmRoles(userResource.roles().realmLevel().listEffective())); @@ - var kcRoleNames = roleMappings.listEffective().stream() - .map(RoleRepresentation::getName) - .toList(); - dbUser.setRealmRoles(RealmRole.fromKcNames(kcRoleNames).stream().map(RealmRole::kcName).toArray(String[]::new)); + dbUser.setRealmRoles(mapEffectiveRealmRoles(roleMappings.listEffective())); @@ + private static String[] mapEffectiveRealmRoles(List<RoleRepresentation> effectiveRoles) { + var kcRoleNames = effectiveRoles.stream().map(RoleRepresentation::getName).toList(); + return RealmRole.fromKcNames(kcRoleNames).stream().map(RealmRole::kcName).toArray(String[]::new); + }Also applies to: 307-310
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@backend/src/main/java/org/cryptomator/hub/keycloak/KeycloakAdminService.java` around lines 208 - 211, Duplication: two identical pipelines transform Keycloak effective role representations into String[] for dbUser; extract that logic into a single private helper in KeycloakAdminService (e.g., a method like extractRealmRoleNames(UserResource userResource) or convertEffectiveKcRolesToRealmRoleNames) that calls userResource.roles().realmLevel().listEffective(), maps RoleRepresentation::getName, passes through RealmRole.fromKcNames(...).stream().map(RealmRole::kcName).toArray(String[]::new) and return the String[]; then replace both occurrences (the block using kcRoleNames and the similar block at 307-310) to call the new helper and setRealmRoles with its result.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In
`@backend/src/main/java/org/cryptomator/hub/keycloak/KeycloakAdminService.java`:
- Around line 208-211: Duplication: two identical pipelines transform Keycloak
effective role representations into String[] for dbUser; extract that logic into
a single private helper in KeycloakAdminService (e.g., a method like
extractRealmRoleNames(UserResource userResource) or
convertEffectiveKcRolesToRealmRoleNames) that calls
userResource.roles().realmLevel().listEffective(), maps
RoleRepresentation::getName, passes through
RealmRole.fromKcNames(...).stream().map(RealmRole::kcName).toArray(String[]::new)
and return the String[]; then replace both occurrences (the block using
kcRoleNames and the similar block at 307-310) to call the new helper and
setRealmRoles with its result.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: a214198b-a1b6-4747-ab7a-2c4808e96b06
📒 Files selected for processing (1)
backend/src/main/java/org/cryptomator/hub/keycloak/KeycloakAdminService.java
overheadhunter
left a comment
There was a problem hiding this comment.
What are "effective roles"? Do they include roles inherited from groups?
If yes, should we really attach them to "users" in our db? Doesn't this produce inconsistencies? Or incorrectly sync back to kc users?