refactor(stats): introduce StatsService and require READ_ALL
StatsController previously injected PersonRepository and DocumentRepository directly, violating the controller→service→repository layering rule. Move the two count() calls into a thin StatsService that delegates to PersonService.count and DocumentService.count. While here, add the missing @RequirePermission(READ_ALL) flagged by AUDIT-2 §7 — anonymous callers were able to read aggregate document/ person counts. Refs #417 (C6.1 violation #1). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -2,10 +2,10 @@ package org.raddatz.familienarchiv.controller;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.raddatz.familienarchiv.config.SecurityConfig;
|
||||
import org.raddatz.familienarchiv.repository.DocumentRepository;
|
||||
import org.raddatz.familienarchiv.repository.PersonRepository;
|
||||
import org.raddatz.familienarchiv.dto.StatsDTO;
|
||||
import org.raddatz.familienarchiv.security.PermissionAspect;
|
||||
import org.raddatz.familienarchiv.service.CustomUserDetailsService;
|
||||
import org.raddatz.familienarchiv.service.StatsService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.aop.AopAutoConfiguration;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
|
||||
@@ -25,8 +25,7 @@ class StatsControllerTest {
|
||||
|
||||
@Autowired MockMvc mockMvc;
|
||||
|
||||
@MockitoBean PersonRepository personRepository;
|
||||
@MockitoBean DocumentRepository documentRepository;
|
||||
@MockitoBean StatsService statsService;
|
||||
@MockitoBean CustomUserDetailsService customUserDetailsService;
|
||||
|
||||
@Test
|
||||
@@ -37,9 +36,15 @@ class StatsControllerTest {
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
void getStats_returns403_whenUserLacksReadAll() throws Exception {
|
||||
mockMvc.perform(get("/api/stats"))
|
||||
.andExpect(status().isForbidden());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(authorities = "READ_ALL")
|
||||
void getStats_returns200_withCorrectCounts() throws Exception {
|
||||
when(personRepository.count()).thenReturn(4L);
|
||||
when(documentRepository.count()).thenReturn(12L);
|
||||
when(statsService.getStats()).thenReturn(new StatsDTO(4L, 12L));
|
||||
|
||||
mockMvc.perform(get("/api/stats"))
|
||||
.andExpect(status().isOk())
|
||||
@@ -48,10 +53,9 @@ class StatsControllerTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser
|
||||
@WithMockUser(authorities = "READ_ALL")
|
||||
void getStats_returns200_withZeroCounts() throws Exception {
|
||||
when(personRepository.count()).thenReturn(0L);
|
||||
when(documentRepository.count()).thenReturn(0L);
|
||||
when(statsService.getStats()).thenReturn(new StatsDTO(0L, 0L));
|
||||
|
||||
mockMvc.perform(get("/api/stats"))
|
||||
.andExpect(status().isOk())
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
package org.raddatz.familienarchiv.service;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.raddatz.familienarchiv.dto.StatsDTO;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
class StatsServiceTest {
|
||||
|
||||
@Mock PersonService personService;
|
||||
@Mock DocumentService documentService;
|
||||
@InjectMocks StatsService statsService;
|
||||
|
||||
@Test
|
||||
void getStats_returnsCountsFromServices() {
|
||||
when(personService.count()).thenReturn(4L);
|
||||
when(documentService.count()).thenReturn(12L);
|
||||
|
||||
StatsDTO stats = statsService.getStats();
|
||||
|
||||
assertThat(stats.totalPersons()).isEqualTo(4L);
|
||||
assertThat(stats.totalDocuments()).isEqualTo(12L);
|
||||
}
|
||||
|
||||
@Test
|
||||
void getStats_returnsZero_whenNoEntities() {
|
||||
when(personService.count()).thenReturn(0L);
|
||||
when(documentService.count()).thenReturn(0L);
|
||||
|
||||
StatsDTO stats = statsService.getStats();
|
||||
|
||||
assertThat(stats.totalPersons()).isZero();
|
||||
assertThat(stats.totalDocuments()).isZero();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user