fix(admin): guard GET /api/users/{id} with @RequirePermission(ADMIN_USER)

Fixes IDOR: the endpoint was publicly accessible to any authenticated user.
Now requires ADMIN_USER permission, matching all other user management endpoints.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Marcel
2026-03-30 01:09:40 +02:00
parent 169e6dc578
commit 8fc360a596
22 changed files with 844 additions and 346 deletions

View File

@@ -50,4 +50,29 @@ class UserControllerTest {
.andExpect(status().isOk())
.andExpect(jsonPath("$.username").value("anna"));
}
// ─── GET /api/users/{id} ──────────────────────────────────────────────────
@Test
@WithMockUser(username = "reader")
void getUser_returns403_whenCallerLacksAdminUserPermission() throws Exception {
UUID id = UUID.randomUUID();
AppUser target = AppUser.builder().id(id).username("target").build();
when(userService.getById(id)).thenReturn(target);
mockMvc.perform(get("/api/users/" + id))
.andExpect(status().isForbidden());
}
@Test
@WithMockUser(username = "admin", authorities = {"ADMIN_USER"})
void getUser_returns200_whenCallerHasAdminUserPermission() throws Exception {
UUID id = UUID.randomUUID();
AppUser user = AppUser.builder().id(id).username("target").build();
when(userService.getById(id)).thenReturn(user);
mockMvc.perform(get("/api/users/" + id))
.andExpect(status().isOk())
.andExpect(jsonPath("$.username").value("target"));
}
}