RED-10112: Wrong role permissions in API endpoints for GUEST and RED_USER_ADMIN role

This commit is contained in:
Maverick Studer 2024-10-09 14:40:20 +02:00
parent ec10bbdf8b
commit 9b07def91d
6 changed files with 449 additions and 60 deletions

View File

@ -9,6 +9,7 @@ import java.util.ArrayList;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
@ -42,15 +43,17 @@ import lombok.experimental.FieldDefaults;
@RestController
@RequiredArgsConstructor
@Tag(name = "4. Component endpoints", description = "Provides operations related to components")
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class ComponentControllerV2 implements ComponentResource {
ComponentLogService componentLogService;
UserService userService;
StatusController statusController;
FileStatusService fileStatusService;
DossierTemplatePersistenceService dossierTemplatePersistenceService;
ComponentMapper componentMapper = ComponentMapper.INSTANCE;
private final ComponentLogService componentLogService;
private final UserService userService;
private final StatusController statusController;
private final FileStatusService fileStatusService;
private final DossierTemplatePersistenceService dossierTemplatePersistenceService;
private final ComponentMapper componentMapper = ComponentMapper.INSTANCE;
@Value("${application.type}")
private String applicationType;
@Override
@ -59,8 +62,9 @@ public class ComponentControllerV2 implements ComponentResource {
@PathVariable(FILE_ID_PARAM) String fileId,
@RequestParam(name = INCLUDE_DETAILS_PARAM, defaultValue = "false", required = false) boolean includeDetails) {
dossierTemplatePersistenceService.checkDossierTemplateExistsOrElseThrow404(dossierTemplateId);
checkApplicationType();
validateUserRoles(KeycloakSecurity.getUserId());
dossierTemplatePersistenceService.checkDossierTemplateExistsOrElseThrow404(dossierTemplateId);
var componentLog = componentLogService.getComponentLog(dossierId, fileId);
return componentMapper.toFileComponents(componentLog, dossierTemplateId, dossierId, fileId, fileStatusService.getFileName(fileId), includeDetails);
@ -85,6 +89,7 @@ public class ComponentControllerV2 implements ComponentResource {
@PathVariable(DOSSIER_ID_PARAM) String dossierId,
@RequestParam(name = INCLUDE_DETAILS_PARAM, defaultValue = "false", required = false) boolean includeDetails) {
checkApplicationType();
dossierTemplatePersistenceService.checkDossierTemplateExistsOrElseThrow404(dossierTemplateId);
var dossierFiles = statusController.getDossierStatus(dossierId);
return new FileComponentsList(dossierFiles.stream()
@ -100,6 +105,7 @@ public class ComponentControllerV2 implements ComponentResource {
@PathVariable(FILE_ID_PARAM) String fileId,
@RequestBody Component override) {
checkApplicationType();
dossierTemplatePersistenceService.checkDossierTemplateExistsOrElseThrow404(dossierTemplateId);
componentLogService.overrideComponent(dossierId, fileId, componentMapper.toComponentLogEntry(override));
@ -112,6 +118,7 @@ public class ComponentControllerV2 implements ComponentResource {
@PathVariable(DOSSIER_ID_PARAM) String dossierId,
@PathVariable(FILE_ID_PARAM) String fileId) {
checkApplicationType();
dossierTemplatePersistenceService.checkDossierTemplateExistsOrElseThrow404(dossierTemplateId);
FileModel status = fileStatusService.getStatus(fileId);
@ -138,9 +145,18 @@ public class ComponentControllerV2 implements ComponentResource {
@PathVariable(FILE_ID_PARAM) String fileId,
@RequestBody RevertOverrideRequest revertOverrideRequest) {
checkApplicationType();
dossierTemplatePersistenceService.checkDossierTemplateExistsOrElseThrow404(dossierTemplateId);
componentLogService.revertOverrides(dossierId, fileId, revertOverrideRequest);
}
private void checkApplicationType() {
if(!applicationType.equals("DocuMine")) {
throw new NotAllowedException("Components can only be accessed in DocuMine");
}
}
}

View File

@ -1,6 +1,7 @@
package com.iqser.red.persistence.service.v2.external.api.impl.controller;
import java.util.List;
import java.util.Optional;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
@ -8,7 +9,11 @@ import org.springframework.web.bind.annotation.RestController;
import com.iqser.red.persistence.service.v1.external.api.impl.controller.DownloadController;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.FileEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.ReportTemplateEntity;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotAllowedException;
import com.iqser.red.service.persistence.management.v1.processor.roles.ApplicationRoles;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DownloadStatusPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.users.UserService;
import com.iqser.red.service.persistence.management.v1.processor.service.users.model.User;
import com.iqser.red.service.persistence.service.v1.api.shared.model.RemoveDownloadRequest;
import com.iqser.red.service.persistence.service.v2.api.external.model.DownloadStatus;
import com.iqser.red.service.persistence.service.v2.api.external.model.DownloadStatusList;
@ -26,10 +31,13 @@ public class DownloadControllerV2 implements DownloadResource {
private final DownloadController downloadController;
private final DownloadStatusPersistenceService downloadStatusPersistenceService;
private final UserService userService;
@Transactional
public DownloadStatusList getDownloadStatusList() {
validateUserRoles(KeycloakSecurity.getUserId());
var downloads = downloadStatusPersistenceService.getStatusesByUser(KeycloakSecurity.getUserId());
return new DownloadStatusList(downloads.stream().map(
@ -61,6 +69,7 @@ public class DownloadControllerV2 implements DownloadResource {
@Transactional
public DownloadStatus getDownloadStatus(@PathVariable(DOWNLOAD_ID_PARAM) String downloadId) {
validateUserRoles(KeycloakSecurity.getUserId());
var status = downloadStatusPersistenceService.getStatusesByUuid(downloadId);
return DownloadStatus.builder()
@ -88,6 +97,7 @@ public class DownloadControllerV2 implements DownloadResource {
public void deleteDownload(@PathVariable(DOWNLOAD_ID_PARAM) String downloadId) {
validateUserRoles(KeycloakSecurity.getUserId());
var status = downloadStatusPersistenceService.getStatusesByUuid(downloadId);
downloadController.deleteDownloadStatus(new RemoveDownloadRequest(List.of(status.getStorageId())));
}
@ -95,8 +105,22 @@ public class DownloadControllerV2 implements DownloadResource {
public void download(@PathVariable(DOWNLOAD_ID_PARAM) String downloadId) {
validateUserRoles(KeycloakSecurity.getUserId());
var status = downloadStatusPersistenceService.getStatusesByUuid(downloadId);
downloadController.downloadFile(status.getStorageId());
}
private void validateUserRoles(String userId) {
Optional<User> userOptional = userService.getUserById(userId);
if (userOptional.isPresent()) {
if (userOptional.get().getRoles()
.stream()
.noneMatch(ApplicationRoles.VALID_MEMBER_ROLES::contains)) {
throw new NotAllowedException("User doesn't have appropriate roles");
}
}
}
}

View File

@ -53,7 +53,9 @@ public final class ApplicationRoles {
DOWNLOAD_REDACTION_PREVIEW_FILE,
DOWNLOAD_REPORT_TEMPLATE,
EXCLUDE_INCLUDE_FILE,
EXCLUDE_INCLUDE_PAGES, GET_REPORT_TEMPLATES, GET_SIMILAR_IMAGES,
EXCLUDE_INCLUDE_PAGES,
GET_REPORT_TEMPLATES,
GET_SIMILAR_IMAGES,
MANAGE_USER_PREFERENCES,
MANAGE_VIEWED_PAGES,
PROCESS_DOWNLOAD,
@ -105,7 +107,9 @@ public final class ApplicationRoles {
DELETE_DICTIONARY_TYPE,
DELETE_REPORT_TEMPLATE,
DOWNLOAD_REPORT_TEMPLATE,
GET_REPORT_TEMPLATES, MANAGE_USER_PREFERENCES, GET_SIMILAR_IMAGES,
GET_REPORT_TEMPLATES,
MANAGE_USER_PREFERENCES,
GET_SIMILAR_IMAGES,
READ_COLORS,
READ_DICTIONARY_TYPES,
READ_DIGITAL_SIGNATURE,
@ -147,7 +151,9 @@ public final class ApplicationRoles {
public static final Set<String> RED_USER_ADMIN_ACTION_ROLES = Sets.newHashSet(MANAGE_USER_PREFERENCES,
READ_ALL_USERS,
READ_APP_CONFIG,
READ_GENERAL_CONFIGURATION, READ_GENERAL_CONFIGURATION, GET_SIMILAR_IMAGES,
READ_GENERAL_CONFIGURATION,
READ_GENERAL_CONFIGURATION,
GET_SIMILAR_IMAGES,
READ_NOTIFICATIONS,
READ_USERS,
UPDATE_MY_PROFILE,

View File

@ -1,18 +1,21 @@
package com.iqser.red.service.peristence.v1.server.integration.tests;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.*;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.openMocks;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import org.mockito.MockitoAnnotations;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import org.springframework.test.util.ReflectionTestUtils;
import com.iqser.red.persistence.service.v1.external.api.impl.controller.StatusController;
import com.iqser.red.persistence.service.v2.external.api.impl.controller.ComponentControllerV2;
@ -22,17 +25,26 @@ import com.iqser.red.service.persistence.management.v1.processor.service.FileSta
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DossierTemplatePersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.users.UserService;
import com.iqser.red.service.persistence.management.v1.processor.service.users.model.User;
import com.iqser.red.service.persistence.service.v1.api.shared.model.FileStatus;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLog;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLogEntry;
import com.iqser.red.service.persistence.service.v1.api.shared.model.component.RevertOverrideRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.dossiertemplate.dossier.file.FileModel;
import com.iqser.red.service.persistence.service.v2.api.external.model.Component;
import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity;
import lombok.SneakyThrows;
public class ComponentControllerV2Test {
public static final String USER_ID = "user-111";
public static final String FILE_ID = "file-789";
public static final String DOSSIER_ID = "dossier-456";
public static final String DOSSIER_TEMPLATE_ID = "template-123";
@InjectMocks
private ComponentControllerV2 componentControllerV2;
@Mock
private UserService userService;
@Mock
@ -43,17 +55,22 @@ public class ComponentControllerV2Test {
private DossierTemplatePersistenceService dossierTemplatePersistenceService;
@Mock
private StatusController statusController;
@Mock
private ComponentLog mockComponentLog;
@BeforeEach
@SneakyThrows
void setUp() {
MockitoAnnotations.openMocks(this);
openMocks(this);
ReflectionTestUtils.setField(componentControllerV2, "applicationType", "DocuMine");
}
@Test
void shouldThrowNotAllowedExceptionIfUserHasInvalidRoles() {
void shouldThrowNotAllowedExceptionIfUserHasInvalidRoles_getComponents() {
User invalidUser = new User();
invalidUser.setUserId(USER_ID);
@ -64,43 +81,129 @@ public class ComponentControllerV2Test {
try (MockedStatic<KeycloakSecurity> keycloakSecurityMock = mockStatic(KeycloakSecurity.class)) {
keycloakSecurityMock.when(KeycloakSecurity::getUserId).thenReturn(USER_ID);
assertThrows(NotAllowedException.class, () -> {
componentControllerV2.getComponents(DOSSIER_TEMPLATE_ID, DOSSIER_ID, FILE_ID, false);
});
assertThrows(NotAllowedException.class, () -> componentControllerV2.getComponents(DOSSIER_TEMPLATE_ID, DOSSIER_ID, FILE_ID, false));
}
}
@Test
void shouldNotThrowNotAllowedExceptionIfUserHasValidRoles() {
void shouldNotThrowNotAllowedExceptionIfUserHasValidRoles_getComponents() {
User validUser = new User();
validUser.setUserId(USER_ID);
validUser.setRoles(Set.of("RED_USER"));
User validManager = new User();
validManager.setUserId(USER_ID);
validManager.setRoles(Set.of("RED_MANAGER"));
when(componentLogService.getComponentLog(DOSSIER_ID, FILE_ID)).thenReturn(mockComponentLog);
when(mockComponentLog.getComponentLogEntries()).thenReturn(Collections.emptyList());
when(fileStatusService.getFileName(FILE_ID)).thenReturn("mock-file-name");
try (MockedStatic<KeycloakSecurity> keycloakSecurityMock = mockStatic(KeycloakSecurity.class)) {
keycloakSecurityMock.when(KeycloakSecurity::getUserId).thenReturn(USER_ID);
when(userService.getUserById(USER_ID)).thenReturn(Optional.of(validUser));
assertDoesNotThrow(() -> {
componentControllerV2.getComponents(DOSSIER_TEMPLATE_ID, DOSSIER_ID, FILE_ID, false);
});
when(userService.getUserById(USER_ID)).thenReturn(Optional.of(validManager));
assertDoesNotThrow(() -> {
componentControllerV2.getComponents(DOSSIER_TEMPLATE_ID, DOSSIER_ID, FILE_ID, false);
});
assertDoesNotThrow(() -> componentControllerV2.getComponents(DOSSIER_TEMPLATE_ID, DOSSIER_ID, FILE_ID, false));
}
}
@Test
void shouldThrowNotAllowedExceptionIfApplicationTypeIsRM_getComponents() {
ReflectionTestUtils.setField(componentControllerV2, "applicationType", "RedactManager");
when(userService.getUserById(USER_ID)).thenReturn(Optional.of(new User()));
assertThrows(NotAllowedException.class, () -> componentControllerV2.getComponents(DOSSIER_TEMPLATE_ID, DOSSIER_ID, FILE_ID, false));
}
@Test
void shouldThrowNotAllowedExceptionIfApplicationTypeIsRM_getComponentsOfDossier() {
ReflectionTestUtils.setField(componentControllerV2, "applicationType", "RedactManager");
assertThrows(NotAllowedException.class, () -> componentControllerV2.getComponentsOfDossier(DOSSIER_TEMPLATE_ID, DOSSIER_ID, false));
}
@Test
void shouldNotThrowExceptionIfApplicationTypeIsValid_getComponentsOfDossier() {
FileStatus fileStatus = FileStatus.builder().fileId(FILE_ID).build();
when(statusController.getDossierStatus(DOSSIER_ID)).thenReturn(Collections.singletonList(fileStatus));
when(componentLogService.getComponentLog(DOSSIER_ID, FILE_ID)).thenReturn(mockComponentLog);
when(fileStatusService.getFileName(FILE_ID)).thenReturn("mock-file-name");
when(mockComponentLog.getComponentLogEntries()).thenReturn(Collections.emptyList());
assertDoesNotThrow(() -> componentControllerV2.getComponentsOfDossier(DOSSIER_TEMPLATE_ID, DOSSIER_ID, false));
}
@Test
void shouldThrowNotAllowedExceptionIfApplicationTypeIsRM_addOverride() {
ReflectionTestUtils.setField(componentControllerV2, "applicationType", "RedactManager");
Component component = Component.builder().name("dummy").componentValues(Collections.emptyList()).build();
assertThrows(NotAllowedException.class, () -> componentControllerV2.addOverride(DOSSIER_TEMPLATE_ID, DOSSIER_ID, FILE_ID, component));
}
@Test
void shouldNotThrowException_addOverride() {
Component component = Component.builder().name("dummy").componentValues(Collections.emptyList()).build();
assertDoesNotThrow(() -> componentControllerV2.addOverride(DOSSIER_TEMPLATE_ID, DOSSIER_ID, FILE_ID, component));
}
@Test
void shouldThrowNotAllowedExceptionIfApplicationTypeIsRM_getOverrides() {
ReflectionTestUtils.setField(componentControllerV2, "applicationType", "RedactManager");
assertThrows(NotAllowedException.class, () -> componentControllerV2.getOverrides(DOSSIER_TEMPLATE_ID, DOSSIER_ID, FILE_ID));
}
@Test
void shouldNotThrowException_getOverrides() {
FileModel fileModel = new FileModel();
fileModel.setId(FILE_ID);
when(fileStatusService.getStatus(FILE_ID)).thenReturn(fileModel);
when(componentLogService.getComponentLog(DOSSIER_ID, FILE_ID)).thenReturn(mockComponentLog);
ComponentLogEntry overriddenEntry = new ComponentLogEntry();
overriddenEntry.setName("dummy");
overriddenEntry.setValues(Collections.emptyList());
overriddenEntry.setOverridden(true);
when(mockComponentLog.getComponentLogEntries()).thenReturn(Collections.singletonList(overriddenEntry));
assertDoesNotThrow(() -> componentControllerV2.getOverrides(DOSSIER_TEMPLATE_ID, DOSSIER_ID, FILE_ID));
}
@Test
void shouldThrowNotAllowedExceptionIfApplicationTypeIsRM_revertOverrides() {
ReflectionTestUtils.setField(componentControllerV2, "applicationType", "RedactManager");
RevertOverrideRequest revertOverrideRequest = new RevertOverrideRequest();
assertThrows(NotAllowedException.class, () -> componentControllerV2.revertOverrides(DOSSIER_TEMPLATE_ID, DOSSIER_ID, FILE_ID, revertOverrideRequest));
}
@Test
void shouldNotThrowException_revertOverrides() {
RevertOverrideRequest revertOverrideRequest = new RevertOverrideRequest();
assertDoesNotThrow(() -> componentControllerV2.revertOverrides(DOSSIER_TEMPLATE_ID, DOSSIER_ID, FILE_ID, revertOverrideRequest));
}
}

View File

@ -4,28 +4,28 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.MockitoAnnotations.openMocks;
import java.io.IOException;
import java.util.HashMap;
import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.test.util.ReflectionTestUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.persistence.service.v2.external.api.impl.controller.ComponentControllerV2;
import com.iqser.red.service.peristence.v1.server.integration.client.ComponentClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierTemplateClient;
import com.iqser.red.service.peristence.v1.server.integration.service.DossierTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.service.FileTesterAndProvider;
import com.iqser.red.service.peristence.v1.server.integration.utils.AbstractPersistenceServerServiceTest;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotFoundException;
import com.iqser.red.service.persistence.management.v1.processor.service.FileService;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLog;
import com.iqser.red.service.persistence.service.v1.api.shared.model.analysislog.componentlog.ComponentLogEntry;
import com.iqser.red.service.persistence.service.v1.api.shared.model.component.ComponentsOverrides;
import com.iqser.red.service.persistence.service.v1.api.shared.model.component.RevertOverrideRequest;
import com.iqser.red.service.persistence.service.v2.api.external.model.Component;
import com.iqser.red.service.persistence.service.v2.api.external.model.ComponentValue;
@ -54,6 +54,17 @@ public class ComponentOverrideTest extends AbstractPersistenceServerServiceTest
@Autowired
private FileService fileService;
@Autowired
private ComponentControllerV2 componentControllerV2;
@BeforeEach
@SneakyThrows
void setUp() {
ReflectionTestUtils.setField(componentControllerV2, "applicationType", "DocuMine");
}
@Test
public void testOverrides() throws IOException {
@ -130,21 +141,19 @@ public class ComponentOverrideTest extends AbstractPersistenceServerServiceTest
.get(0).isOverridden());
// add and revert override
Component componentOverrideModel3 = Component.builder()
.name("Report_Number")
.componentValues(List.of(ComponentValue.builder()
.value("WOHOO 11/111-111A")
//.originalValue("11/111-111A")
.valueDescription("First found value of type report_number or else ''")
.componentRuleId("ReportNumber.0.0")
.entityReferences(List.of(EntityReference.builder()
.id("e2a93bcc72e9740bbfc19bd9cd982e01")
.type("report_number")
.entityRuleId("DOC.2.0")
.page(1)
.build()))
.build()))
.build();
Component componentOverrideModel3 = Component.builder().name("Report_Number").componentValues(List.of(ComponentValue.builder()
.value("WOHOO 11/111-111A")
//.originalValue("11/111-111A")
.valueDescription(
"First found value of type report_number or else ''")
.componentRuleId("ReportNumber.0.0")
.entityReferences(List.of(EntityReference.builder()
.id("e2a93bcc72e9740bbfc19bd9cd982e01")
.type("report_number")
.entityRuleId("DOC.2.0")
.page(1)
.build()))
.build())).build();
componentClient.addOverride(dossierTemplate.getId(), dossier.getId(), file.getId(), componentOverrideModel3);
overrides = componentClient.getOverrides(dossierTemplate.getId(), dossier.getId(), file.getId());

View File

@ -0,0 +1,231 @@
package com.iqser.red.service.peristence.v1.server.integration.tests;
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.openMocks;
import java.time.OffsetDateTime;
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.MockedStatic;
import com.iqser.red.persistence.service.v1.external.api.impl.controller.DownloadController;
import com.iqser.red.persistence.service.v2.external.api.impl.controller.DownloadControllerV2;
import com.iqser.red.service.persistence.management.v1.processor.entity.dossier.DossierEntity;
import com.iqser.red.service.persistence.management.v1.processor.entity.download.DownloadStatusEntity;
import com.iqser.red.service.persistence.management.v1.processor.exception.NotAllowedException;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.DownloadStatusPersistenceService;
import com.iqser.red.service.persistence.management.v1.processor.service.users.UserService;
import com.iqser.red.service.persistence.management.v1.processor.service.users.model.User;
import com.iqser.red.service.persistence.service.v1.api.shared.model.RemoveDownloadRequest;
import com.iqser.red.service.persistence.service.v1.api.shared.model.download.DownloadStatusValue;
import com.knecon.fforesight.keycloakcommons.security.KeycloakSecurity;
public class DownloadControllerV2Test {
public static final String USER_ID = "user-111";
public static final String DOWNLOAD_ID = "download-123";
@InjectMocks
private DownloadControllerV2 downloadControllerV2;
@Mock
private DownloadController downloadController;
@Mock
private DownloadStatusPersistenceService downloadStatusPersistenceService;
@Mock
private UserService userService;
@Mock
private DownloadStatusEntity mockDownloadStatusEntity;
@BeforeEach
void setUp() {
openMocks(this);
}
@Test
void shouldThrowNotAllowedExceptionIfUserHasInvalidRoles_getDownloadStatusList() {
User invalidUser = new User();
invalidUser.setUserId(USER_ID);
invalidUser.setRoles(Set.of("RED_ADMIN"));
when(userService.getUserById(USER_ID)).thenReturn(Optional.of(invalidUser));
try (MockedStatic<KeycloakSecurity> keycloakSecurityMock = mockStatic(KeycloakSecurity.class)) {
keycloakSecurityMock.when(KeycloakSecurity::getUserId).thenReturn(USER_ID);
assertThrows(NotAllowedException.class, () -> downloadControllerV2.getDownloadStatusList());
}
}
@Test
void shouldNotThrowExceptionIfUserHasValidRoles_getDownloadStatusList() {
User validUser = new User();
validUser.setUserId(USER_ID);
validUser.setRoles(Set.of("RED_MANAGER"));
when(userService.getUserById(USER_ID)).thenReturn(Optional.of(validUser));
try (MockedStatic<KeycloakSecurity> keycloakSecurityMock = mockStatic(KeycloakSecurity.class)) {
keycloakSecurityMock.when(KeycloakSecurity::getUserId).thenReturn(USER_ID);
when(downloadStatusPersistenceService.getStatusesByUser(USER_ID)).thenReturn(Collections.emptyList());
assertDoesNotThrow(() -> downloadControllerV2.getDownloadStatusList());
}
}
@Test
void shouldThrowNotAllowedExceptionIfUserHasInvalidRoles_getDownloadStatus() {
User invalidUser = new User();
invalidUser.setUserId(USER_ID);
invalidUser.setRoles(Collections.emptySet());
when(userService.getUserById(USER_ID)).thenReturn(Optional.of(invalidUser));
try (MockedStatic<KeycloakSecurity> keycloakSecurityMock = mockStatic(KeycloakSecurity.class)) {
keycloakSecurityMock.when(KeycloakSecurity::getUserId).thenReturn(USER_ID);
assertThrows(NotAllowedException.class, () -> downloadControllerV2.getDownloadStatus(DOWNLOAD_ID));
}
}
@Test
void shouldNotThrowExceptionIfUserHasValidRoles_getDownloadStatus() {
User validUser = new User();
validUser.setUserId(USER_ID);
validUser.setRoles(Set.of("RED_USER"));
when(userService.getUserById(USER_ID)).thenReturn(Optional.of(validUser));
when(downloadStatusPersistenceService.getStatusesByUuid(DOWNLOAD_ID)).thenReturn(mockDownloadStatusEntity);
when(mockDownloadStatusEntity.getUuid()).thenReturn(DOWNLOAD_ID);
when(mockDownloadStatusEntity.getUserId()).thenReturn(USER_ID);
when(mockDownloadStatusEntity.getFilename()).thenReturn("dummy-file");
when(mockDownloadStatusEntity.getMimeType()).thenReturn("application/pdf");
when(mockDownloadStatusEntity.getErrorCause()).thenReturn(null);
when(mockDownloadStatusEntity.getStatus()).thenReturn(DownloadStatusValue.READY);
when(mockDownloadStatusEntity.getCreationDate()).thenReturn(OffsetDateTime.now());
when(mockDownloadStatusEntity.getLastDownload()).thenReturn(OffsetDateTime.now());
when(mockDownloadStatusEntity.getFileSize()).thenReturn(12345L);
DossierEntity dossierEntity = mock(DossierEntity.class);
when(dossierEntity.getId()).thenReturn("dossier-123");
when(mockDownloadStatusEntity.getDossier()).thenReturn(dossierEntity);
when(mockDownloadStatusEntity.getFiles()).thenReturn(Collections.emptyList());
when(mockDownloadStatusEntity.getDownloadFileTypes()).thenReturn(Collections.emptySet());
when(mockDownloadStatusEntity.getReports()).thenReturn(Collections.emptyList());
try (MockedStatic<KeycloakSecurity> keycloakSecurityMock = mockStatic(KeycloakSecurity.class)) {
keycloakSecurityMock.when(KeycloakSecurity::getUserId).thenReturn(USER_ID);
assertDoesNotThrow(() -> downloadControllerV2.getDownloadStatus(DOWNLOAD_ID));
}
}
@Test
void shouldThrowNotAllowedExceptionIfUserHasInvalidRoles_deleteDownload() {
User invalidUser = new User();
invalidUser.setUserId(USER_ID);
invalidUser.setRoles(Set.of("RED_USER_ADMIN"));
when(userService.getUserById(USER_ID)).thenReturn(Optional.of(invalidUser));
try (MockedStatic<KeycloakSecurity> keycloakSecurityMock = mockStatic(KeycloakSecurity.class)) {
keycloakSecurityMock.when(KeycloakSecurity::getUserId).thenReturn(USER_ID);
assertThrows(NotAllowedException.class, () -> downloadControllerV2.deleteDownload(DOWNLOAD_ID));
}
}
@Test
void shouldNotThrowExceptionIfUserHasValidRoles_deleteDownload() {
User validUser = new User();
validUser.setUserId(USER_ID);
validUser.setRoles(Set.of("RED_MANAGER"));
when(userService.getUserById(USER_ID)).thenReturn(Optional.of(validUser));
when(downloadStatusPersistenceService.getStatusesByUuid(DOWNLOAD_ID)).thenReturn(mockDownloadStatusEntity);
when(mockDownloadStatusEntity.getStorageId()).thenReturn("storage-123");
doNothing().when(downloadController).deleteDownloadStatus(any(RemoveDownloadRequest.class));
try (MockedStatic<KeycloakSecurity> keycloakSecurityMock = mockStatic(KeycloakSecurity.class)) {
keycloakSecurityMock.when(KeycloakSecurity::getUserId).thenReturn(USER_ID);
assertDoesNotThrow(() -> downloadControllerV2.deleteDownload(DOWNLOAD_ID));
verify(downloadController).deleteDownloadStatus(any(RemoveDownloadRequest.class));
}
}
@Test
void shouldThrowNotAllowedExceptionIfUserHasInvalidRoles_download() {
User invalidUser = new User();
invalidUser.setUserId(USER_ID);
invalidUser.setRoles(Set.of("NON_ELIGIBLE_ROLE"));
when(userService.getUserById(USER_ID)).thenReturn(Optional.of(invalidUser));
try (MockedStatic<KeycloakSecurity> keycloakSecurityMock = mockStatic(KeycloakSecurity.class)) {
keycloakSecurityMock.when(KeycloakSecurity::getUserId).thenReturn(USER_ID);
assertThrows(NotAllowedException.class, () -> downloadControllerV2.download(DOWNLOAD_ID));
}
}
@Test
void shouldNotThrowExceptionIfUserHasValidRoles_download() {
User validUser = new User();
validUser.setUserId(USER_ID);
validUser.setRoles(Set.of("RED_USER"));
when(userService.getUserById(USER_ID)).thenReturn(Optional.of(validUser));
when(downloadStatusPersistenceService.getStatusesByUuid(DOWNLOAD_ID)).thenReturn(mockDownloadStatusEntity);
when(mockDownloadStatusEntity.getStorageId()).thenReturn("storage-123");
doNothing().when(downloadController).downloadFile("storage-123");
try (MockedStatic<KeycloakSecurity> keycloakSecurityMock = mockStatic(KeycloakSecurity.class)) {
keycloakSecurityMock.when(KeycloakSecurity::getUserId).thenReturn(USER_ID);
assertDoesNotThrow(() -> downloadControllerV2.download(DOWNLOAD_ID));
verify(downloadController).downloadFile("storage-123");
}
}
}