RED-6631 - RED_USER and RED_MANAGER-Role must not delete dossier templates #24

Merged
corina.olariu.ext1 merged 1 commits from RED-6631 into master 2023-06-26 11:25:14 +02:00
5 changed files with 62 additions and 4 deletions

View File

@ -109,6 +109,8 @@ public final class ApplicationRoles {
public static final String RED_ADMIN_ROLE = "RED_ADMIN";
public static final String RED_USER_ADMIN_ROLE = "RED_USER_ADMIN";
public static final Set<String> RED_ROLES = Sets.newHashSet(RED_USER_ROLE, RED_MANAGER_ROLE, RED_ADMIN_ROLE, RED_USER_ADMIN_ROLE);
public static final Set<String> UNMAPPED_ACTION_ROLES = Sets.newHashSet(UNARCHIVE_DOSSIER, UPDATE_LICENSE, GET_RSS);
public static final Set<String> RED_USER_ACTION_ROLES = Sets.newHashSet(ADD_COMMENT,

View File

@ -2,6 +2,8 @@ package com.iqser.red.persistence.service.v1.external.api.impl.controller;
import static com.iqser.red.keycloak.commons.roles.ActionRoles.READ_DOSSIER_TEMPLATES;
import static com.iqser.red.keycloak.commons.roles.ActionRoles.WRITE_DOSSIER_TEMPLATES;
import static com.iqser.red.keycloak.commons.roles.ApplicationRoles.RED_MANAGER_ROLE;
import static com.iqser.red.keycloak.commons.roles.ApplicationRoles.RED_USER_ROLE;
import static com.iqser.red.service.persistence.management.v1.processor.service.FeignExceptionHandler.processFeignException;
import java.io.IOException;
@ -15,6 +17,7 @@ import java.util.stream.Collectors;
import javax.annotation.PostConstruct;
import org.apache.commons.lang3.StringUtils;
import org.keycloak.representations.idm.RoleRepresentation;
import org.springframework.beans.BeanUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PathVariable;
@ -31,6 +34,7 @@ import com.iqser.red.service.persistence.management.v1.processor.exception.Confl
import com.iqser.red.service.persistence.management.v1.processor.service.DossierManagementService;
import com.iqser.red.service.persistence.management.v1.processor.service.DossierTemplateManagementService;
import com.iqser.red.service.persistence.management.v1.processor.service.DossierTemplateStatsService;
import com.iqser.red.service.persistence.management.v1.processor.service.UserService;
import com.iqser.red.service.persistence.management.v1.processor.service.persistence.AuditPersistenceService;
import com.iqser.red.service.persistence.service.v1.api.external.resource.DossierTemplateResource;
import com.iqser.red.service.persistence.service.v1.api.shared.model.AuditCategory;
@ -61,6 +65,7 @@ public class DossierTemplateController implements DossierTemplateResource {
private final AuditPersistenceService auditPersistenceService;
private final DossierManagementService dossierManagementService;
private final DossierACLService dossierACLService;
private final UserService userService;
@Override
@ -113,9 +118,12 @@ public class DossierTemplateController implements DossierTemplateResource {
@PreAuthorize("hasAuthority('" + READ_DOSSIER_TEMPLATES + "')")
public void deleteDossierTemplate(@PathVariable(DOSSIER_TEMPLATE_ID) String dossierTemplateId) {
String userId = KeycloakSecurity.getUserId();
String userId = KeycloakSecurity.getUserId();
if (!userService.checkUserHasAdminRole(userId)) {
throw new BadRequestException("Only admin user can delete the dossier template");
}
List<Dossier> dossiers = dossierManagementService.getAllDossiers(true, false);
List<Dossier> dossiers = dossierManagementService.getAllDossiers(true, false);
if (dossiers != null && dossiers.stream().anyMatch(dossier -> dossier.getDossierTemplateId().equals(dossierTemplateId))) {
throw new ConflictException("Can not delete dossier template because there are dossiers based on it");
}

View File

@ -3,6 +3,7 @@ package com.iqser.red.service.persistence.management.v1.processor.service;
import static com.iqser.red.keycloak.commons.DefaultKeyCloakCommonsConfiguration.USERS_CACHE;
import static com.iqser.red.keycloak.commons.roles.ApplicationRoles.RED_ADMIN_ROLE;
import static com.iqser.red.keycloak.commons.roles.ApplicationRoles.RED_MANAGER_ROLE;
import static com.iqser.red.keycloak.commons.roles.ApplicationRoles.RED_ROLES;
import static com.iqser.red.keycloak.commons.roles.ApplicationRoles.RED_USER_ADMIN_ROLE;
import static com.iqser.red.keycloak.commons.roles.ApplicationRoles.RED_USER_ROLE;
import static com.iqser.red.keycloak.commons.roles.ApplicationRoles.validateRoles;
@ -39,6 +40,7 @@ import org.springframework.cache.annotation.CacheEvict;
import org.springframework.stereotype.Service;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.iqser.red.keycloak.commons.KeyCloakSettings;
import com.iqser.red.keycloak.commons.KeycloakSecurity;
import com.iqser.red.keycloak.commons.RealmService;
@ -268,6 +270,12 @@ public class UserService {
}
}
public boolean checkUserHasAdminRole(String userId) {
var userResource = this.getUserResource(userId);
var userRoles = userResource.roles().realmLevel().listEffective().stream().map(RoleRepresentation::getName).collect(Collectors.toSet());
return userRoles.contains(RED_ADMIN_ROLE);
}
private void removeUserFromDossiers(String userId, UserRemovalModel mode) {

View File

@ -1,19 +1,28 @@
package com.iqser.red.service.peristence.v1.server.integration.tests;
import static com.iqser.red.keycloak.commons.roles.ApplicationRoles.RED_MANAGER_ROLE;
import static com.iqser.red.keycloak.commons.roles.ApplicationRoles.RED_ROLES;
import static com.iqser.red.keycloak.commons.roles.ApplicationRoles.RED_USER_ADMIN_ROLE;
import static com.iqser.red.keycloak.commons.roles.ApplicationRoles.RED_USER_ROLE;
import static org.assertj.core.api.Assertions.assertThat;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.iqser.red.keycloak.commons.KeycloakSecurity;
import com.iqser.red.keycloak.commons.model.User;
import com.iqser.red.persistence.service.v1.external.api.impl.controller.UserController;
import com.iqser.red.service.peristence.v1.server.integration.client.DictionaryClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierAttributeConfigClient;
import com.iqser.red.service.peristence.v1.server.integration.client.DossierClient;
@ -530,6 +539,36 @@ public class DossierTemplateTest extends AbstractPersistenceServerServiceTest {
assertThat(existingLegalBasis.isEmpty()).isTrue();
}
@Test
public void testDeleteDossierTemplate() {
var dossierTemplate = dossierTemplateTesterAndProvider.provideTestTemplate();
var allTemplates = dossierTemplateClient.getAllDossierTemplates();
assertThat(allTemplates.size()).isEqualTo(1);
assertThat(allTemplates.get(0)).isEqualTo(dossierTemplate);
Optional<User> optionalUser = userService.getOptionalUserByUsername(USERNAME);
if(optionalUser.isPresent()) {
String userId = optionalUser.get().getUserId();
userService.setRoles(userId, List.of(RED_USER_ROLE), RED_ROLES.stream().toList());
Assertions.assertThrows(FeignException.BadRequest.class, () -> dossierTemplateClient.deleteDossierTemplate(dossierTemplate.getId()));
userService.setRoles(userId, List.of(RED_MANAGER_ROLE), RED_ROLES.stream().toList());
Assertions.assertThrows(FeignException.BadRequest.class, () -> dossierTemplateClient.deleteDossierTemplate(dossierTemplate.getId()));
userService.setRoles(userId, List.of(RED_USER_ADMIN_ROLE), RED_ROLES.stream().toList());
Assertions.assertThrows(FeignException.Forbidden.class, () -> dossierTemplateClient.deleteDossierTemplate(dossierTemplate.getId()));
userService.setRoles(userId, List.of(RED_USER_ADMIN_ROLE, RED_USER_ROLE), RED_ROLES.stream().toList());
Assertions.assertThrows(FeignException.BadRequest.class, () -> dossierTemplateClient.deleteDossierTemplate(dossierTemplate.getId()));
userService.setRoles(userId, RED_ROLES.stream().toList(), RED_ROLES.stream().toList());
dossierTemplateClient.deleteDossierTemplate(dossierTemplate.getId());
allTemplates = dossierTemplateClient.getAllDossierTemplates();
assertThat(allTemplates.size()).isZero();
}
}
@Test
@SneakyThrows

View File

@ -108,6 +108,7 @@ import lombok.extern.slf4j.Slf4j;
@ContextConfiguration(initializers = {AbstractPersistenceServerServiceTest.Initializer.class})
@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT, properties = "spring-hibernate-query-utils.n-plus-one-queries-detection.error-level=INFO")
public abstract class AbstractPersistenceServerServiceTest {
protected final String USERNAME = "manageradmin1@test.com";
@MockBean
protected RabbitTemplate rabbitTemplate;
@ -203,7 +204,7 @@ public abstract class AbstractPersistenceServerServiceTest {
@Autowired
private ApplicationConfigService applicationConfigService;
@Autowired
private UserService userService;
protected UserService userService;
@Autowired
private TokenService tokenService;
@Autowired
@ -240,7 +241,7 @@ public abstract class AbstractPersistenceServerServiceTest {
KeyCloakTestContainer.getInstance().getKeycloakAdminClient().realm("redaction").clients().create(redactionSystemClient);
tokenService.setUser("manageradmin1@test.com", "secret");
tokenService.setUser(USERNAME, "secret");
TenantContext.clear();