fix scope grants after creating new members#129
Conversation
📝 WalkthroughWalkthroughChangesUser creation now assigns the Member role assignment
Sequence Diagram(s)sequenceDiagram
participant Caller
participant KeycloakService
participant Keycloak
Caller->>KeycloakService: createUser
KeycloakService->>Keycloak: Create user
Keycloak-->>KeycloakService: User UUID
KeycloakService->>Keycloak: Get available realm roles
Keycloak-->>KeycloakService: Return member role
KeycloakService->>Keycloak: Assign member role
Keycloak-->>KeycloakService: 204 NO_CONTENT
KeycloakService-->>Caller: Return user UUID
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ 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 |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In
`@services/spring-member/src/main/java/tum/devoops/memberservice/service/KeycloakService.java`:
- Around line 87-121: Handle failures from assignMemberRealmRole in
MemberService.createMember by deleting the newly created Keycloak user before
propagating the error, ensuring cleanup occurs for any assignment failure and
preserving the original exception. Use the existing Keycloak user identifier and
deletion client/service method, and keep successful creation behavior unchanged;
alternatively, make both creation and role assignment idempotent so retries do
not leave orphaned users.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: 4f5d2ed2-362b-43fb-9a2e-afe22524403a
📒 Files selected for processing (2)
services/spring-member/src/main/java/tum/devoops/memberservice/service/KeycloakService.javaservices/spring-member/src/test/java/tum/devoops/memberservice/service/KeycloakServiceTest.java
| UUID userId = UUID.fromString(path.substring(path.lastIndexOf("/") + 1)); | ||
|
|
||
| assignMemberRealmRole(userId); | ||
|
|
||
| return userId; | ||
| } | ||
|
|
||
| // Looked up via the user's own "available realm roles" endpoint rather than the | ||
| // realm-wide /roles/{role-name} resource: the org-role-sync service account only | ||
| // holds the manage-users client role (see realm-config.json), which covers a | ||
| // user's own role-mappings sub-resource but not the separate view-realm permission | ||
| // that GET /roles/{role-name} would require. | ||
| private void assignMemberRealmRole(UUID userId) { | ||
| try { | ||
| RoleRepresentation[] availableRoles = restClient.get() | ||
| .uri("/admin/realms/{realm}/users/{id}/role-mappings/realm/available", realm, userId) | ||
| .header(HttpHeaders.AUTHORIZATION, authorizationHeader()) | ||
| .retrieve() | ||
| .body(RoleRepresentation[].class); | ||
|
|
||
| RoleRepresentation memberRole = Arrays.stream(availableRoles != null ? availableRoles : new RoleRepresentation[0]) | ||
| .filter(role -> MEMBER_ROLE_NAME.equals(role.name())) | ||
| .findFirst() | ||
| .orElseThrow(() -> new IllegalStateException("Keycloak realm role not found: " + MEMBER_ROLE_NAME)); | ||
|
|
||
| restClient.post() | ||
| .uri("/admin/realms/{realm}/users/{id}/role-mappings/realm", realm, userId) | ||
| .header(HttpHeaders.AUTHORIZATION, authorizationHeader()) | ||
| .contentType(MediaType.APPLICATION_JSON) | ||
| .body(List.of(memberRole)) | ||
| .retrieve() | ||
| .toBodilessEntity(); | ||
| } catch (HttpClientErrorException.Forbidden e) { | ||
| throw new SecurityException("Insufficient permissions to assign the member realm role"); | ||
| } |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Find callers of createUser to see how failures/rollback are handled
rg -nP --type=java -C4 '\bcreateUser\s*\(' -g '!**/test/**'Repository: AET-DevOps26/team-devoops
Length of output: 163
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Inspect the service implementation around createUser and role assignment
FILE="services/spring-member/src/main/java/tum/devoops/memberservice/service/KeycloakService.java"
wc -l "$FILE"
sed -n '1,260p' "$FILE"
# Find any usages of KeycloakService and createUser in the repo
rg -n --hidden --glob '!**/test/**' 'KeycloakService|createUser\s*\(' services . || trueRepository: AET-DevOps26/team-devoops
Length of output: 11917
🏁 Script executed:
#!/bin/bash
set -euo pipefail
FILE="services/spring-member/src/main/java/tum/devoops/memberservice/service/MemberService.java"
wc -l "$FILE"
sed -n '1,220p' "$FILE"
# Check whether the member creation flow compensates for a Keycloak failure
rg -n --hidden --glob '!**/test/**' 'deleteUser\s*\(|createUser\(|`@Transactional`|rollback|catch .*createUser|KeycloakService' services/spring-member/src/main/javaRepository: AET-DevOps26/team-devoops
Length of output: 5907
Handle cleanup when Keycloak role assignment fails
assignMemberRealmRole() can throw after the Keycloak user has already been created, leaving an orphaned account with no local member record. MemberService.createMember() wraps that failure as a BadRequestException, so the flow is not retry-safe. Delete the new user on failure or make the create/assign flow idempotent.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In
`@services/spring-member/src/main/java/tum/devoops/memberservice/service/KeycloakService.java`
around lines 87 - 121, Handle failures from assignMemberRealmRole in
MemberService.createMember by deleting the newly created Keycloak user before
propagating the error, ensuring cleanup occurs for any assignment failure and
preserving the original exception. Use the existing Keycloak user identifier and
deletion client/service method, and keep successful creation behavior unchanged;
alternatively, make both creation and role assignment idempotent so retries do
not leave orphaned users.
There was an issue that member creation doesn't automatically grant member role in keycloak. I fixed this issue now.
Summary by CodeRabbit
New Features
Bug Fixes