refactor(security): extract requireUserId to SecurityUtils
Both DocumentController and TranscriptionBlockController contained identical private requireUserId helpers. Extracted to a shared static utility in the security package ahead of DashboardController which also needs actor resolution. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -28,6 +28,7 @@ import org.raddatz.familienarchiv.model.DocumentVersion;
|
|||||||
import org.raddatz.familienarchiv.model.AppUser;
|
import org.raddatz.familienarchiv.model.AppUser;
|
||||||
import org.raddatz.familienarchiv.security.Permission;
|
import org.raddatz.familienarchiv.security.Permission;
|
||||||
import org.raddatz.familienarchiv.security.RequirePermission;
|
import org.raddatz.familienarchiv.security.RequirePermission;
|
||||||
|
import org.raddatz.familienarchiv.security.SecurityUtils;
|
||||||
import org.raddatz.familienarchiv.service.DocumentService;
|
import org.raddatz.familienarchiv.service.DocumentService;
|
||||||
import org.raddatz.familienarchiv.service.DocumentVersionService;
|
import org.raddatz.familienarchiv.service.DocumentVersionService;
|
||||||
import org.raddatz.familienarchiv.service.FileService;
|
import org.raddatz.familienarchiv.service.FileService;
|
||||||
@@ -286,13 +287,6 @@ public class DocumentController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private UUID requireUserId(Authentication authentication) {
|
private UUID requireUserId(Authentication authentication) {
|
||||||
if (authentication == null || !authentication.isAuthenticated()) {
|
return SecurityUtils.requireUserId(authentication, userService);
|
||||||
throw DomainException.unauthorized("Authentication required");
|
|
||||||
}
|
|
||||||
AppUser user = userService.findByEmail(authentication.getName());
|
|
||||||
if (user == null) {
|
|
||||||
throw DomainException.unauthorized("User not found");
|
|
||||||
}
|
|
||||||
return user.getId();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,11 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.raddatz.familienarchiv.dto.CreateTranscriptionBlockDTO;
|
import org.raddatz.familienarchiv.dto.CreateTranscriptionBlockDTO;
|
||||||
import org.raddatz.familienarchiv.dto.ReorderTranscriptionBlocksDTO;
|
import org.raddatz.familienarchiv.dto.ReorderTranscriptionBlocksDTO;
|
||||||
import org.raddatz.familienarchiv.dto.UpdateTranscriptionBlockDTO;
|
import org.raddatz.familienarchiv.dto.UpdateTranscriptionBlockDTO;
|
||||||
import org.raddatz.familienarchiv.exception.DomainException;
|
|
||||||
import org.raddatz.familienarchiv.model.AppUser;
|
|
||||||
import org.raddatz.familienarchiv.model.TranscriptionBlock;
|
import org.raddatz.familienarchiv.model.TranscriptionBlock;
|
||||||
import org.raddatz.familienarchiv.model.TranscriptionBlockVersion;
|
import org.raddatz.familienarchiv.model.TranscriptionBlockVersion;
|
||||||
import org.raddatz.familienarchiv.security.Permission;
|
import org.raddatz.familienarchiv.security.Permission;
|
||||||
import org.raddatz.familienarchiv.security.RequirePermission;
|
import org.raddatz.familienarchiv.security.RequirePermission;
|
||||||
|
import org.raddatz.familienarchiv.security.SecurityUtils;
|
||||||
import org.raddatz.familienarchiv.service.TranscriptionService;
|
import org.raddatz.familienarchiv.service.TranscriptionService;
|
||||||
import org.raddatz.familienarchiv.service.UserService;
|
import org.raddatz.familienarchiv.service.UserService;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
@@ -100,13 +99,6 @@ public class TranscriptionBlockController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private UUID requireUserId(Authentication authentication) {
|
private UUID requireUserId(Authentication authentication) {
|
||||||
if (authentication == null || !authentication.isAuthenticated()) {
|
return SecurityUtils.requireUserId(authentication, userService);
|
||||||
throw DomainException.unauthorized("Authentication required");
|
|
||||||
}
|
|
||||||
AppUser user = userService.findByEmail(authentication.getName());
|
|
||||||
if (user == null) {
|
|
||||||
throw DomainException.unauthorized("User not found");
|
|
||||||
}
|
|
||||||
return user.getId();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package org.raddatz.familienarchiv.security;
|
||||||
|
|
||||||
|
import org.raddatz.familienarchiv.exception.DomainException;
|
||||||
|
import org.raddatz.familienarchiv.model.AppUser;
|
||||||
|
import org.raddatz.familienarchiv.service.UserService;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public final class SecurityUtils {
|
||||||
|
|
||||||
|
private SecurityUtils() {}
|
||||||
|
|
||||||
|
public static UUID requireUserId(Authentication authentication, UserService userService) {
|
||||||
|
if (authentication == null || !authentication.isAuthenticated()) {
|
||||||
|
throw DomainException.unauthorized("Authentication required");
|
||||||
|
}
|
||||||
|
AppUser user = userService.findByEmail(authentication.getName());
|
||||||
|
if (user == null) {
|
||||||
|
throw DomainException.unauthorized("User not found");
|
||||||
|
}
|
||||||
|
return user.getId();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
package org.raddatz.familienarchiv.security;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.ExtendWith;
|
||||||
|
import org.mockito.Mock;
|
||||||
|
import org.mockito.junit.jupiter.MockitoExtension;
|
||||||
|
import org.raddatz.familienarchiv.exception.DomainException;
|
||||||
|
import org.raddatz.familienarchiv.model.AppUser;
|
||||||
|
import org.raddatz.familienarchiv.service.UserService;
|
||||||
|
import org.springframework.security.core.Authentication;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
|
@ExtendWith(MockitoExtension.class)
|
||||||
|
class SecurityUtilsTest {
|
||||||
|
|
||||||
|
@Mock Authentication authentication;
|
||||||
|
@Mock UserService userService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void requireUserId_throwsUnauthorized_whenAuthenticationIsNull() {
|
||||||
|
assertThatThrownBy(() -> SecurityUtils.requireUserId(null, userService))
|
||||||
|
.isInstanceOf(DomainException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void requireUserId_throwsUnauthorized_whenNotAuthenticated() {
|
||||||
|
when(authentication.isAuthenticated()).thenReturn(false);
|
||||||
|
assertThatThrownBy(() -> SecurityUtils.requireUserId(authentication, userService))
|
||||||
|
.isInstanceOf(DomainException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void requireUserId_throwsUnauthorized_whenUserNotFound() {
|
||||||
|
when(authentication.isAuthenticated()).thenReturn(true);
|
||||||
|
when(authentication.getName()).thenReturn("ghost@example.com");
|
||||||
|
when(userService.findByEmail("ghost@example.com")).thenReturn(null);
|
||||||
|
assertThatThrownBy(() -> SecurityUtils.requireUserId(authentication, userService))
|
||||||
|
.isInstanceOf(DomainException.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void requireUserId_returnsUserId_whenAuthenticated() {
|
||||||
|
UUID userId = UUID.randomUUID();
|
||||||
|
AppUser user = AppUser.builder().id(userId).email("user@example.com").password("pw").build();
|
||||||
|
when(authentication.isAuthenticated()).thenReturn(true);
|
||||||
|
when(authentication.getName()).thenReturn("user@example.com");
|
||||||
|
when(userService.findByEmail("user@example.com")).thenReturn(user);
|
||||||
|
|
||||||
|
UUID result = SecurityUtils.requireUserId(authentication, userService);
|
||||||
|
|
||||||
|
assertThat(result).isEqualTo(userId);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user