From 811b3a099dc6b7eaec019beee9b57db663c47f2d Mon Sep 17 00:00:00 2001 From: Tomasz Kuzynowski Date: Wed, 13 Sep 2023 11:32:45 +0200 Subject: [PATCH] Revert "Revert "feat: accept tenant id passed as superadmin for agency create"" --- api/agencyadminservice.yaml | 4 ++ .../api/admin/service/AgencyAdminService.java | 35 ++++++++++++-- .../AgencyAdminFullResponseDTOBuilder.java | 6 +-- .../api/authorization/Authority.java | 2 + .../api/helper/AuthenticatedUser.java | 5 ++ .../service/AgencyAdminServiceITBase.java | 3 ++ .../admin/service/AgencyAdminServiceTest.java | 4 ++ .../controller/AgencyAdminControllerIT.java | 46 +++++++++++++++++++ 8 files changed, 99 insertions(+), 6 deletions(-) diff --git a/api/agencyadminservice.yaml b/api/agencyadminservice.yaml index 25fc7699..b8ed6c70 100644 --- a/api/agencyadminservice.yaml +++ b/api/agencyadminservice.yaml @@ -526,6 +526,10 @@ components: items: type: string enum: [ RELATIVE_COUNSELLING, SELF_COUNSELLING, PARENTAL_COUNSELLING ] + tenantId: + type: integer + format: int64 + example: 12 PostcodeRangeDTO: diff --git a/src/main/java/de/caritas/cob/agencyservice/api/admin/service/AgencyAdminService.java b/src/main/java/de/caritas/cob/agencyservice/api/admin/service/AgencyAdminService.java index 95753b25..0816bd0b 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/admin/service/AgencyAdminService.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/admin/service/AgencyAdminService.java @@ -4,6 +4,7 @@ import static de.caritas.cob.agencyservice.api.exception.httpresponses.HttpStatusExceptionReason.AGENCY_IS_ALREADY_TEAM_AGENCY; import static de.caritas.cob.agencyservice.api.model.AgencyTypeRequestDTO.AgencyTypeEnum.TEAM_AGENCY; import static java.util.Objects.nonNull; +import static org.apache.commons.lang3.Validate.notNull; import com.google.common.base.Joiner; import de.caritas.cob.agencyservice.api.admin.service.agency.AgencyAdminFullResponseDTOBuilder; @@ -12,6 +13,7 @@ import de.caritas.cob.agencyservice.api.admin.validation.DeleteAgencyValidator; import de.caritas.cob.agencyservice.api.exception.httpresponses.ConflictException; import de.caritas.cob.agencyservice.api.exception.httpresponses.NotFoundException; +import de.caritas.cob.agencyservice.api.helper.AuthenticatedUser; import de.caritas.cob.agencyservice.api.model.AgencyAdminFullResponseDTO; import de.caritas.cob.agencyservice.api.model.AgencyDTO; import de.caritas.cob.agencyservice.api.model.AgencyTypeRequestDTO; @@ -29,6 +31,7 @@ import lombok.NonNull; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @@ -38,6 +41,7 @@ */ @Service @RequiredArgsConstructor +@Slf4j public class AgencyAdminService { private final @NonNull AgencyRepository agencyRepository; @@ -46,6 +50,11 @@ public class AgencyAdminService { private final @NonNull AgencyTopicMergeService agencyTopicMergeService; private final @NonNull AppointmentService appointmentService; + private final @NonNull AuthenticatedUser authenticatedUser; + @Value("${multitenancy.enabled}") + private boolean multitenancy; + + @Autowired(required = false) private AgencyTopicEnrichmentService agencyTopicEnrichmentService; @@ -96,7 +105,7 @@ public Agency findAgencyById(Long agencyId) { public AgencyAdminFullResponseDTO createAgency(AgencyDTO agencyDTO) { setDefaultCounsellingRelationsIfEmpty(agencyDTO); Agency agency = fromAgencyDTO(agencyDTO); - agency.setTenantId(TenantContext.getCurrentTenant()); + setTenantIdOnCreate(agencyDTO, agency); var savedAgency = agencyRepository.save(agency); enrichWithAgencyTopicsIfTopicFeatureEnabled(savedAgency); this.appointmentService.syncAgencyDataToAppointmentService(savedAgency); @@ -104,6 +113,26 @@ public AgencyAdminFullResponseDTO createAgency(AgencyDTO agencyDTO) { .fromAgency(); } + private void setTenantIdOnCreate(AgencyDTO agencyDTO, Agency agency) { + if (authenticatedUser.isTenantSuperAdmin()) { + notNull(agencyDTO.getTenantId()); + agency.setTenantId(agencyDTO.getTenantId()); + } else { + checkIfTenantIdMatch(agencyDTO); + agency.setTenantId(TenantContext.getCurrentTenant()); + } + } + + private void checkIfTenantIdMatch(AgencyDTO agencyDTO) { + if (agencyDTO.getTenantId() != null && !agencyDTO.getTenantId() + .equals(TenantContext.getCurrentTenant())) { + log.warn("TenantId of agencyDTO {} does not match current tenant {}", + agencyDTO.getTenantId(), TenantContext.getCurrentTenant()); + log.warn("Setting tenantId of agency {} to current tenant {}", + agencyDTO.getName(), TenantContext.getCurrentTenant()); + } + } + private void setDefaultCounsellingRelationsIfEmpty(AgencyDTO agencyDTO) { if (agencyDTO.getCounsellingRelations() == null || agencyDTO.getCounsellingRelations().isEmpty()) { agencyDTO.setCounsellingRelations(getAllPossibleCounsellingRelations()); @@ -111,8 +140,7 @@ private void setDefaultCounsellingRelationsIfEmpty(AgencyDTO agencyDTO) { } private List getAllPossibleCounsellingRelations() { - return Arrays.stream(AgencyDTO.CounsellingRelationsEnum.values()) - .collect(Collectors.toList()); + return Arrays.stream(AgencyDTO.CounsellingRelationsEnum.values()).toList(); } @@ -140,6 +168,7 @@ private Agency fromAgencyDTO(AgencyDTO agencyDTO) { .createDate(LocalDateTime.now(ZoneOffset.UTC)) .updateDate(LocalDateTime.now(ZoneOffset.UTC)); + if (featureDemographicsEnabled && agencyDTO.getDemographics() != null) { demographicsConverter.convertToEntity(agencyDTO.getDemographics(), agencyBuilder); } diff --git a/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyAdminFullResponseDTOBuilder.java b/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyAdminFullResponseDTOBuilder.java index 67b378d8..a3fcbfa2 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyAdminFullResponseDTOBuilder.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyAdminFullResponseDTOBuilder.java @@ -11,7 +11,6 @@ import de.caritas.cob.agencyservice.api.repository.agency.Agency; import de.caritas.cob.agencyservice.api.repository.agencytopic.AgencyTopic; import java.util.List; -import java.util.stream.Collectors; import lombok.NonNull; import lombok.RequiredArgsConstructor; @@ -49,6 +48,7 @@ private AgencyAdminResponseDTO createAgency() { .external((this.agency.isExternal())) .offline(this.agency.isOffline()) .topics(getTopics()) + .tenantId(this.agency.getTenantId()) .counsellingRelations(splitToList(agency.getCounsellingRelations())) .createDate(String.valueOf(this.agency.getCreateDate())) .updateDate(String.valueOf(this.agency.getUpdateDate())) @@ -63,7 +63,7 @@ private List splitToList(String return Lists.newArrayList(); } else { return Splitter.on(",").trimResults() - .splitToList(counsellingRelationsAsCommaSeparatedString).stream().map(AgencyAdminResponseDTO.CounsellingRelationsEnum::valueOf).collect(Collectors.toList()); + .splitToList(counsellingRelationsAsCommaSeparatedString).stream().map(AgencyAdminResponseDTO.CounsellingRelationsEnum::valueOf).toList(); } } @@ -84,7 +84,7 @@ private List getTopics() { } private List getTopics(List agencyTopics) { - return agencyTopics.stream().map(AgencyTopic::getTopicData).collect(Collectors.toList()); + return agencyTopics.stream().map(AgencyTopic::getTopicData).toList(); } private AgencyLinks createAgencyLinks() { diff --git a/src/main/java/de/caritas/cob/agencyservice/api/authorization/Authority.java b/src/main/java/de/caritas/cob/agencyservice/api/authorization/Authority.java index a227a36f..8bd035c4 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/authorization/Authority.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/authorization/Authority.java @@ -10,6 +10,8 @@ public enum Authority { AGENCY_ADMIN("agency-admin", "AUTHORIZATION_AGENCY_ADMIN"), + + TENANT_ADMIN("tenant-admin", "AUTHORIZATION_TENANT_ADMIN"), RESTRICTED_AGENCY_ADMIN("restricted-agency-admin", "AUTHORIZATION_RESTRICTED_AGENCY_ADMIN"); private final String roleName; diff --git a/src/main/java/de/caritas/cob/agencyservice/api/helper/AuthenticatedUser.java b/src/main/java/de/caritas/cob/agencyservice/api/helper/AuthenticatedUser.java index 9e1fb6fc..8bc26e74 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/helper/AuthenticatedUser.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/helper/AuthenticatedUser.java @@ -42,6 +42,11 @@ public boolean isAgencySuperAdmin() { return nonNull(roles) && roles.contains(Authority.AGENCY_ADMIN.getRoleName()); } + @JsonIgnore + public boolean isTenantSuperAdmin() { + return nonNull(roles) && roles.contains(Authority.TENANT_ADMIN.getRoleName()); + } + @JsonIgnore public boolean hasRestrictedAgencyPriviliges() { return isRestrictedAgencyAdmin() && !isAgencySuperAdmin(); diff --git a/src/test/java/de/caritas/cob/agencyservice/api/admin/service/AgencyAdminServiceITBase.java b/src/test/java/de/caritas/cob/agencyservice/api/admin/service/AgencyAdminServiceITBase.java index fcfbc129..4f89e8e5 100644 --- a/src/test/java/de/caritas/cob/agencyservice/api/admin/service/AgencyAdminServiceITBase.java +++ b/src/test/java/de/caritas/cob/agencyservice/api/admin/service/AgencyAdminServiceITBase.java @@ -8,6 +8,7 @@ import static org.junit.Assert.assertTrue; import com.google.common.collect.Lists; +import de.caritas.cob.agencyservice.api.helper.AuthenticatedUser; import de.caritas.cob.agencyservice.api.model.AgencyAdminFullResponseDTO; import de.caritas.cob.agencyservice.api.model.AgencyDTO; import de.caritas.cob.agencyservice.api.model.DemographicsDTO; @@ -18,11 +19,13 @@ import jakarta.persistence.EntityManager; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.mock.mockito.MockBean; public class AgencyAdminServiceITBase { @Autowired protected AgencyAdminService agencyAdminService; @Autowired protected AgencyRepository agencyRepository; + @MockBean protected AuthenticatedUser authenticatedUser; public void saveAgency_Should_PersistsAgency() { diff --git a/src/test/java/de/caritas/cob/agencyservice/api/admin/service/AgencyAdminServiceTest.java b/src/test/java/de/caritas/cob/agencyservice/api/admin/service/AgencyAdminServiceTest.java index 6548ace2..e3cb5fca 100644 --- a/src/test/java/de/caritas/cob/agencyservice/api/admin/service/AgencyAdminServiceTest.java +++ b/src/test/java/de/caritas/cob/agencyservice/api/admin/service/AgencyAdminServiceTest.java @@ -21,6 +21,7 @@ import de.caritas.cob.agencyservice.api.admin.validation.DeleteAgencyValidator; import de.caritas.cob.agencyservice.api.exception.httpresponses.ConflictException; import de.caritas.cob.agencyservice.api.exception.httpresponses.NotFoundException; +import de.caritas.cob.agencyservice.api.helper.AuthenticatedUser; import de.caritas.cob.agencyservice.api.model.AgencyAdminResponseDTO; import de.caritas.cob.agencyservice.api.model.AgencyTypeRequestDTO; import de.caritas.cob.agencyservice.api.model.DemographicsDTO; @@ -75,6 +76,9 @@ class AgencyAdminServiceTest { @Mock private Logger logger; + @Mock + AuthenticatedUser authenticatedUser; + @Captor private ArgumentCaptor agencyArgumentCaptor; private EasyRandom easyRandom; diff --git a/src/test/java/de/caritas/cob/agencyservice/api/controller/AgencyAdminControllerIT.java b/src/test/java/de/caritas/cob/agencyservice/api/controller/AgencyAdminControllerIT.java index 3655fcf4..aa56a9e0 100644 --- a/src/test/java/de/caritas/cob/agencyservice/api/controller/AgencyAdminControllerIT.java +++ b/src/test/java/de/caritas/cob/agencyservice/api/controller/AgencyAdminControllerIT.java @@ -33,6 +33,7 @@ import org.springframework.http.MediaType; import org.springframework.security.test.context.support.WithMockUser; import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.TestPropertySource; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.transaction.annotation.Transactional; @@ -137,6 +138,51 @@ void createAgency_Should_returnStatusCreated_When_calledWithValidCreateParamsAnd .andExpect(jsonPath("_embedded.deleteDate").exists()); } + @Test + @WithMockUser(authorities = {"AUTHORIZATION_AGENCY_ADMIN", "AUTHORIZATION_TENANT_ADMIN"}) + void createAgency_Should_returnStatusCreated_And_SetTenantIdFromRequest_When_calledWithValidCreateParamsAndTenantSuperAdminAuthority() + throws Exception { + // given + when(authenticatedUser.isTenantSuperAdmin()).thenReturn(true); + when(consultingTypeManager.getConsultingTypeSettings(anyInt())) + .thenReturn(new ExtendedConsultingTypeResponseDTO()); + + AgencyDTO agencyDTO = new AgencyDTO() + .dioceseId(0L) + .name("Test name") + .description("Test description") + .postcode("12345") + .city("Test city") + .teamAgency(true) + .consultingType(0) + .url("https://www.test.de") + .external(true) + .tenantId(100L); + String payload = JsonConverter.convert(agencyDTO); + + // when, then + mockMvc.perform(post(PathConstants.CREATE_AGENCY_PATH) + .contentType(APPLICATION_JSON) + .content(payload)) + .andExpect(status().isCreated()) + .andExpect(jsonPath("_embedded.id").exists()) + .andExpect(jsonPath("_embedded.name").value("Test name")) + .andExpect(jsonPath("_embedded.dioceseId").value(0)) + .andExpect(jsonPath("_embedded.city").value("Test city")) + .andExpect(jsonPath("_embedded.consultingType").value(0)) + .andExpect(jsonPath("_embedded.description").value("Test description")) + .andExpect(jsonPath("_embedded.postcode").value("12345")) + .andExpect(jsonPath("_embedded.teamAgency").value("true")) + .andExpect(jsonPath("_embedded.url").value("https://www.test.de")) + .andExpect(jsonPath("_embedded.external").value("true")) + .andExpect(jsonPath("_embedded.offline").exists()) + .andExpect(jsonPath("_embedded.tenantId").value("100")) + .andExpect(jsonPath("_embedded.topics").exists()) + .andExpect(jsonPath("_embedded.createDate").exists()) + .andExpect(jsonPath("_embedded.updateDate").exists()) + .andExpect(jsonPath("_embedded.deleteDate").exists()); + } + @Test @WithMockUser(authorities = "AUTHORIZATION_RESTRICTED_AGENCY_ADMIN") void createAgency_Should_returnAcessDenied_When_tryingToCreateAgencyAsRestrictedAgencyAdmin()