diff --git a/src/main/java/de/caritas/cob/agencyservice/api/admin/validation/validators/AgencyTenantValidator.java b/src/main/java/de/caritas/cob/agencyservice/api/admin/validation/validators/AgencyTenantValidator.java new file mode 100644 index 00000000..7c9ee7d6 --- /dev/null +++ b/src/main/java/de/caritas/cob/agencyservice/api/admin/validation/validators/AgencyTenantValidator.java @@ -0,0 +1,40 @@ +package de.caritas.cob.agencyservice.api.admin.validation.validators; + +import static com.fasterxml.jackson.databind.util.ClassUtil.nonNull; + +import de.caritas.cob.agencyservice.api.admin.validation.validators.annotation.CreateAgencyValidator; +import de.caritas.cob.agencyservice.api.admin.validation.validators.annotation.UpdateAgencyValidator; +import de.caritas.cob.agencyservice.api.admin.validation.validators.model.ValidateAgencyDTO; +import de.caritas.cob.agencyservice.api.service.ApplicationSettingsService; +import de.caritas.cob.agencyservice.api.service.TenantService; +import de.caritas.cob.agencyservice.api.tenant.TenantContext; +import de.caritas.cob.agencyservice.api.util.AuthenticatedUser; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.stereotype.Component; + +@Component +@RequiredArgsConstructor +@UpdateAgencyValidator +@CreateAgencyValidator +@Slf4j +public class AgencyTenantValidator implements ConcreteAgencyValidator { + + private final @NonNull AuthenticatedUser authenticatedUser; + + @Override + public void validate(ValidateAgencyDTO validateAgencyDto) { + if (authenticatedUser.isTenantSuperAdmin()) { + nonNull(validateAgencyDto.getTenantId(), "Tenant id must not be null."); + } else { + if (validateAgencyDto.getTenantId() != null && !TenantContext.getCurrentTenant() + .equals(validateAgencyDto.getTenantId())) { + throw new AccessDeniedException( + "Access denied. Tenant id in the request does not match current tenant."); + } + } + } +} diff --git a/src/main/java/de/caritas/cob/agencyservice/api/util/AuthenticatedUser.java b/src/main/java/de/caritas/cob/agencyservice/api/util/AuthenticatedUser.java index 1f384afb..6d18f27c 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/util/AuthenticatedUser.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/util/AuthenticatedUser.java @@ -38,7 +38,7 @@ public boolean isRestrictedAgencyAdmin() { } @JsonIgnore - public boolean isAgencySuperAdmin() { + public boolean isAgencyAdmin() { return nonNull(roles) && roles.contains(Authority.AGENCY_ADMIN.getRoleName()); } @@ -49,7 +49,7 @@ public boolean isTenantSuperAdmin() { @JsonIgnore public boolean hasRestrictedAgencyPriviliges() { - return isRestrictedAgencyAdmin() && !isAgencySuperAdmin(); + return isRestrictedAgencyAdmin() && !isAgencyAdmin(); } diff --git a/src/test/java/de/caritas/cob/agencyservice/api/admin/validation/validators/AgencyTenantValidatorTest.java b/src/test/java/de/caritas/cob/agencyservice/api/admin/validation/validators/AgencyTenantValidatorTest.java new file mode 100644 index 00000000..f76ead2a --- /dev/null +++ b/src/test/java/de/caritas/cob/agencyservice/api/admin/validation/validators/AgencyTenantValidatorTest.java @@ -0,0 +1,77 @@ +package de.caritas.cob.agencyservice.api.admin.validation.validators; + +import static org.mockito.Mockito.when; + +import de.caritas.cob.agencyservice.api.admin.validation.validators.model.ValidateAgencyDTO; +import de.caritas.cob.agencyservice.api.tenant.TenantContext; +import de.caritas.cob.agencyservice.api.util.AuthenticatedUser; +import org.assertj.core.api.Fail; +import org.junit.jupiter.api.BeforeEach; +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.springframework.security.access.AccessDeniedException; + +@ExtendWith(MockitoExtension.class) +class AgencyTenantValidatorTest { + + @Mock + AuthenticatedUser authenticatedUser; + AgencyTenantValidator agencyTenantValidator; + + @BeforeEach + public void setup() { + TenantContext.clear(); + agencyTenantValidator = new AgencyTenantValidator(authenticatedUser); + } + + @Test + void validate_shouldNotThrowException_When_AuthenticatedUserIsNotSuperAdminAndTenantIdNull() { + var validateAgencyDTO = ValidateAgencyDTO.builder().tenantId(null).build(); + try { + agencyTenantValidator.validate(validateAgencyDTO); + } catch (Exception e) { + Fail.fail("Should not throw exception"); + } + } + + @Test + void validate_shouldNotThrowException_When_AuthenticatedUserIsNotSuperAdminAndTenantIdMatchesTenantContext() { + TenantContext.setCurrentTenant(1L); + var validateAgencyDTO = ValidateAgencyDTO.builder().tenantId(1L).build(); + try { + agencyTenantValidator.validate(validateAgencyDTO); + } catch (Exception e) { + Fail.fail("Should not throw exception"); + } + } + + @Test + void validate_shouldThrowAccessDeniedException_When_AuthenticatedUserIsNotSuperAdminAndTenantIdDoesNotMatchTenantContext() { + TenantContext.setCurrentTenant(2L); + var validateAgencyDTO = ValidateAgencyDTO.builder().tenantId(1L).build(); + try { + agencyTenantValidator.validate(validateAgencyDTO); + } catch (AccessDeniedException e) { + assert e.getMessage().equals("Access denied. Tenant id in the request does not match current tenant."); + } catch (Exception ex) { + Fail.fail("Unexpected exception: " + ex.getMessage()); + } + } + + @Test + void validate_shouldNotThrowException_When_AuthenticatedUserIsSuperAdminAndTenantIdNotMatchingTenantContext() { + TenantContext.setCurrentTenant(0L); + when(authenticatedUser.isTenantSuperAdmin()).thenReturn(true); + var validateAgencyDTO = ValidateAgencyDTO.builder().tenantId(1L).build(); + try { + agencyTenantValidator.validate(validateAgencyDTO); + } catch (Exception e) { + Fail.fail("Should not throw exception"); + } + } + + + +} \ No newline at end of file