From 32c3b46cd7cd6ce071df75b6f73c3c271b23361b Mon Sep 17 00:00:00 2001 From: tkuzynow Date: Wed, 22 Jun 2022 09:41:28 +0200 Subject: [PATCH 1/7] fix: fixing NPE for the case of empty topics --- .../agency/AgencyTopicEnrichmentService.java | 6 ++++++ .../AgencyTopicEnrichmentServiceTest.java | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java b/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java index f331b5d5..ae51678b 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java @@ -1,5 +1,6 @@ package de.caritas.cob.agencyservice.api.admin.service.agency; +import com.google.common.collect.Maps; import de.caritas.cob.agencyservice.api.model.TopicDTO; import de.caritas.cob.agencyservice.api.repository.agency.Agency; import de.caritas.cob.agencyservice.api.repository.agencytopic.AgencyTopic; @@ -47,6 +48,11 @@ private void enrichSingleAgencyTopic(Map availableTopics, private Map getAvailableTopicsMap() { var allTopics = topicService.getAllTopics(); + return allTopics.isEmpty() ? Maps.newHashMap() : getAvailableTopicsMap(allTopics); + } + + private Map getAvailableTopicsMap( + List allTopics) { return allTopics.stream() .collect(Collectors.toMap( de.caritas.cob.agencyservice.topicservice.generated.web.model.TopicDTO::getId, diff --git a/src/test/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentServiceTest.java b/src/test/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentServiceTest.java index 6a643db1..b16cda40 100644 --- a/src/test/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentServiceTest.java +++ b/src/test/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentServiceTest.java @@ -43,6 +43,25 @@ void enrichAgencyWithTopics_Should_EnrichAgencyWithTopicDataFromTopicService() { .contains("first topic", "second topic"); } + + @Test + void enrichAgencyWithTopics_Should_NotEnrichIfNoTopicsAreDefined() { + // given + when(topicService.getAllTopics()).thenReturn( + newArrayList()); + var agencyTopics = newArrayList( + createAgencyTopic(new Agency(), 1L), createAgencyTopic(new Agency(), 2L)); + + // when + var agency = newAgencyWithTopics(agencyTopics); + agencyTopicEnrichmentService.enrichAgencyWithTopics(agency); + + // then + assertThat(agency.getAgencyTopics()) + .extracting(agencyTopic -> agencyTopic.getTopicData().getName()) + .containsOnlyNulls(); + } + @Test void enrichAgencyWithTopics_Should_NotEnrichWithTopicDataIfTopicIdDoNotMatch() { // given From 1de9fca95d32a71d6bf649f5308809703b5ac377 Mon Sep 17 00:00:00 2001 From: tkuzynow Date: Fri, 24 Jun 2022 13:29:55 +0200 Subject: [PATCH 2/7] fix: data passed to logger --- .../api/admin/service/agency/AgencyTopicEnrichmentService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java b/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java index ae51678b..7cfacb4b 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java @@ -27,7 +27,7 @@ public Agency enrichAgencyWithTopics(Agency agency) { var availableTopics = getAvailableTopicsMap(); var agencyTopics = agency.getAgencyTopics(); log.debug("Enriching agency with {} with information about the topics", agency.getId()); - log.debug("Available topics list has size: {} ", agencyTopics.size()); + log.debug("Available topics list has size: {} ", availableTopics.size()); for (AgencyTopic agencyTopic : agencyTopics) { enrichSingleAgencyTopic(availableTopics, agencyTopic); } From d2afd4d38ed0c0bfee61db858ad253f593d5bcb8 Mon Sep 17 00:00:00 2001 From: tkuzynow Date: Wed, 22 Jun 2022 09:41:28 +0200 Subject: [PATCH 3/7] fix: fixing NPE for the case of empty topics --- .../agency/AgencyTopicEnrichmentService.java | 6 ++++++ .../AgencyTopicEnrichmentServiceTest.java | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java b/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java index f331b5d5..ae51678b 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java @@ -1,5 +1,6 @@ package de.caritas.cob.agencyservice.api.admin.service.agency; +import com.google.common.collect.Maps; import de.caritas.cob.agencyservice.api.model.TopicDTO; import de.caritas.cob.agencyservice.api.repository.agency.Agency; import de.caritas.cob.agencyservice.api.repository.agencytopic.AgencyTopic; @@ -47,6 +48,11 @@ private void enrichSingleAgencyTopic(Map availableTopics, private Map getAvailableTopicsMap() { var allTopics = topicService.getAllTopics(); + return allTopics.isEmpty() ? Maps.newHashMap() : getAvailableTopicsMap(allTopics); + } + + private Map getAvailableTopicsMap( + List allTopics) { return allTopics.stream() .collect(Collectors.toMap( de.caritas.cob.agencyservice.topicservice.generated.web.model.TopicDTO::getId, diff --git a/src/test/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentServiceTest.java b/src/test/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentServiceTest.java index 6a643db1..b16cda40 100644 --- a/src/test/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentServiceTest.java +++ b/src/test/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentServiceTest.java @@ -43,6 +43,25 @@ void enrichAgencyWithTopics_Should_EnrichAgencyWithTopicDataFromTopicService() { .contains("first topic", "second topic"); } + + @Test + void enrichAgencyWithTopics_Should_NotEnrichIfNoTopicsAreDefined() { + // given + when(topicService.getAllTopics()).thenReturn( + newArrayList()); + var agencyTopics = newArrayList( + createAgencyTopic(new Agency(), 1L), createAgencyTopic(new Agency(), 2L)); + + // when + var agency = newAgencyWithTopics(agencyTopics); + agencyTopicEnrichmentService.enrichAgencyWithTopics(agency); + + // then + assertThat(agency.getAgencyTopics()) + .extracting(agencyTopic -> agencyTopic.getTopicData().getName()) + .containsOnlyNulls(); + } + @Test void enrichAgencyWithTopics_Should_NotEnrichWithTopicDataIfTopicIdDoNotMatch() { // given From ee329b24f41e818ef64c5ef7b26215fa1ae7108b Mon Sep 17 00:00:00 2001 From: Patric Dosch Date: Tue, 28 Jun 2022 14:39:59 +0200 Subject: [PATCH 4/7] feat: VIC-665 Registration | Basic registration with a main topic (and no PLZ) - impl. isTopicFeatureActivatedInRegistration() - receive the RestrictedTenant Information (in multiTenancy mode by tenantId, in singleTenancy mode by receiving the single tenant from the TenantService) --- services/tenantservice.yaml | 132 +++++++++++++++++- .../api/controller/AgencyController.java | 1 + .../api/service/AgencyService.java | 22 ++- .../api/service/TenantService.java | 8 ++ .../config/CacheManagerConfig.java | 48 +++++++ src/main/resources/application.properties | 10 ++ .../service/AgencyServiceTenantAwareTest.java | 94 +++++++++++++ .../api/service/AgencyServiceTest.java | 19 ++- 8 files changed, 325 insertions(+), 9 deletions(-) create mode 100644 src/test/java/de/caritas/cob/agencyservice/api/service/AgencyServiceTenantAwareTest.java diff --git a/services/tenantservice.yaml b/services/tenantservice.yaml index 4c8dd557..1196fdd3 100644 --- a/services/tenantservice.yaml +++ b/services/tenantservice.yaml @@ -26,6 +26,30 @@ paths: $ref: '#/components/schemas/TenantDTO' 400: description: BAD REQUEST - invalid/incomplete request or body object + 401: + description: UNAUTHORIZED - no/invalid Keycloak token + 500: + description: INTERNAL SERVER ERROR - server encountered unexpected condition + get: + tags: + - tenant-controller + summary: 'Get all tenants' + operationId: getAllTenants + responses: + 200: + description: OK - successful operation + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/BasicTenantLicensingDTO' + 204: + description: NO CONTENT - no content found + 400: + description: BAD REQUEST - invalid/incomplete request or body object + 401: + description: UNAUTHORIZED - no/invalid Keycloak token 500: description: INTERNAL SERVER ERROR - server encountered unexpected condition /tenant/{id}: @@ -51,10 +75,12 @@ paths: application/json: schema: $ref: '#/components/schemas/TenantDTO' - 404: - description: Not found 400: description: BAD REQUEST - invalid/incomplete request or body object + 401: + description: UNAUTHORIZED - no/invalid Keycloak token + 404: + description: Not found 500: description: INTERNAL SERVER ERROR - server encountered unexpected condition put: @@ -82,6 +108,8 @@ paths: application/json: schema: $ref: '#/components/schemas/TenantDTO' + 401: + description: UNAUTHORIZED - no/invalid Keycloak token 409: description: CONFLICT - unique constraint validation fails 500: @@ -114,6 +142,55 @@ paths: description: BAD REQUEST - invalid/incomplete request or body object 500: description: INTERNAL SERVER ERROR - server encountered unexpected condition + /tenant/public/id/{tenantId}: + summary: 'Represents a publicly allowed tenant data' + description: This resource represents an individual tenant in a system. + get: + tags: + - tenant-controller + summary: 'Gets a tenant public information [Authorization: no-auth]' + operationId: getRestrictedTenantDataByTenantId + parameters: + - name: tenantId + in: path + description: Tenant ID + required: true + schema: + type: long + responses: + 200: + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/RestrictedTenantDTO' + 404: + description: Not found + 400: + description: BAD REQUEST - invalid/incomplete request or body object + 500: + description: INTERNAL SERVER ERROR - server encountered unexpected condition + /tenant/public/single: + summary: 'Represents a publicly allowed tenant data' + description: This resource represents the tenant in a single-tenant system. + get: + tags: + - tenant-controller + summary: 'Gets a tenant public information [Authorization: no-auth]' + operationId: getRestrictedSingleTenantData + responses: + 200: + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/RestrictedTenantDTO' + 404: + description: Not found + 400: + description: BAD REQUEST - invalid/incomplete request or body object + 500: + description: INTERNAL SERVER ERROR - server encountered unexpected condition components: schemas: TenantDTO: @@ -129,7 +206,7 @@ components: name: type: string example: "Company name AG" - maxLength: 100 + maxLength: 40 subdomain: type: string example: "companyname" @@ -146,6 +223,33 @@ components: content: $ref: '#/components/schemas/Content' + settings: + $ref: + '#/components/schemas/Settings' + BasicTenantLicensingDTO: + type: object + required: + - id + - name + - subdomain + properties: + id: + type: long + example: 12132 + name: + type: string + example: "Company name AG" + maxLength: 40 + subdomain: + type: string + example: "companyname" + maxLength: 100 + createDate: + type: string + updateDate: + type: string + licensing: + $ref: '#/components/schemas/Licensing' RestrictedTenantDTO: type: object required: @@ -158,6 +262,10 @@ components: name: type: string example: "Company name AG" + maxLength: 40 + subdomain: + type: string + example: "subdomain" maxLength: 100 theming: $ref: @@ -165,6 +273,9 @@ components: content: $ref: '#/components/schemas/Content' + settings: + $ref: + '#/components/schemas/Settings' Licensing: type: object required: @@ -199,3 +310,18 @@ components: claim: type: string example: "Llorem ipsum..." + maxLength: 40 + privacy: + type: string + example: "Llorem ipsum..." + termsAndConditions: + type: string + example: "Llorem ipsum..." + Settings: + type: object + required: + - impressum + properties: + topicsInRegistrationEnabled: + type: boolean + example: "false" diff --git a/src/main/java/de/caritas/cob/agencyservice/api/controller/AgencyController.java b/src/main/java/de/caritas/cob/agencyservice/api/controller/AgencyController.java index 4b276ba6..09773ddb 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/controller/AgencyController.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/controller/AgencyController.java @@ -32,6 +32,7 @@ public class AgencyController implements AgenciesApi { * * @param postcode the postcode for regarding agencies * @param consultingType the type used to filter the agencies + * @param topicId the (optional) main topicId to filter the agencies * @return the List of agencies with information */ @Override diff --git a/src/main/java/de/caritas/cob/agencyservice/api/service/AgencyService.java b/src/main/java/de/caritas/cob/agencyservice/api/service/AgencyService.java index 38b8f2bd..ae93596b 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/service/AgencyService.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/service/AgencyService.java @@ -13,8 +13,9 @@ import de.caritas.cob.agencyservice.api.model.FullAgencyResponseDTO; import de.caritas.cob.agencyservice.api.repository.agency.Agency; import de.caritas.cob.agencyservice.api.repository.agency.AgencyRepository; -import de.caritas.cob.agencyservice.consultingtypeservice.generated.web.model.ExtendedConsultingTypeResponseDTO; import de.caritas.cob.agencyservice.api.tenant.TenantContext; +import de.caritas.cob.agencyservice.consultingtypeservice.generated.web.model.ExtendedConsultingTypeResponseDTO; +import de.caritas.cob.agencyservice.tenantservice.generated.web.model.RestrictedTenantDTO; import java.time.LocalDateTime; import java.time.ZoneOffset; import java.util.Collections; @@ -36,10 +37,14 @@ public class AgencyService { private final @NonNull ConsultingTypeManager consultingTypeManager; private final @NonNull AgencyRepository agencyRepository; + private final @NonNull TenantService tenantService; @Value("${feature.topics.enabled}") private boolean topicsFeatureEnabled; + @Value("${multitenancy.enabled}") + private boolean multitenancy; + /** * Returns a list of {@link AgencyResponseDTO} which match the provided agencyIds. * @@ -125,8 +130,19 @@ private boolean isTopicFeatureEnabledAndActivatedInRegistration() { } private boolean isTopicFeatureActivatedInRegistration() { - // TODO get this flag from the tenant service, implement within VIC-797 - return true; + RestrictedTenantDTO restrictedTenantDTO; + if (multitenancy) { + Long tenantId = TenantContext.getCurrentTenant(); + restrictedTenantDTO = tenantService.getRestrictedTenantDataByTenantId(tenantId); + } else { + restrictedTenantDTO = tenantService.getRestrictedTenantDataForSingleTenant(); + } + + if (nonNull(restrictedTenantDTO) && nonNull(restrictedTenantDTO.getSettings())) { + return Boolean.TRUE.equals( + restrictedTenantDTO.getSettings().getTopicsInRegistrationEnabled()); + } + return false; } private void verifyConsultingTypeExists(int consultingTypeId) diff --git a/src/main/java/de/caritas/cob/agencyservice/api/service/TenantService.java b/src/main/java/de/caritas/cob/agencyservice/api/service/TenantService.java index ae73a24a..b473c137 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/service/TenantService.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/service/TenantService.java @@ -19,5 +19,13 @@ public RestrictedTenantDTO getRestrictedTenantDataBySubdomain(String subdomain) return tenantControllerApi.getRestrictedTenantDataBySubdomainWithHttpInfo(subdomain).getBody(); } + @Cacheable(cacheNames = CacheManagerConfig.TENANT_ID_CACHE, key = "#tenantId") + public RestrictedTenantDTO getRestrictedTenantDataByTenantId(Long tenantId) { + return tenantControllerApi.getRestrictedTenantDataByTenantId(tenantId); + } + @Cacheable(cacheNames = CacheManagerConfig.SINGLE_TENANT_CACHE) + public RestrictedTenantDTO getRestrictedTenantDataForSingleTenant() { + return tenantControllerApi.getRestrictedSingleTenantData(); + } } diff --git a/src/main/java/de/caritas/cob/agencyservice/config/CacheManagerConfig.java b/src/main/java/de/caritas/cob/agencyservice/config/CacheManagerConfig.java index 50e8a3db..81305895 100644 --- a/src/main/java/de/caritas/cob/agencyservice/config/CacheManagerConfig.java +++ b/src/main/java/de/caritas/cob/agencyservice/config/CacheManagerConfig.java @@ -14,6 +14,8 @@ public class CacheManagerConfig { public static final String CONSULTING_TYPE_CACHE = "consultingTypeCache"; public static final String TENANT_CACHE = "tenantCache"; + public static final String TENANT_ID_CACHE = "tenantIdCache"; + public static final String SINGLE_TENANT_CACHE = "singleTenantCache"; public static final String TOPICS_CACHE = "topicsCache"; @Value("${cache.consulting.type.configuration.maxEntriesLocalHeap}") @@ -40,6 +42,30 @@ public class CacheManagerConfig { @Value("${cache.tenant.configuration.timeToLiveSeconds}") private long tenantTimeToLiveSeconds; + @Value("${cache.tenantId.configuration.maxEntriesLocalHeap}") + private long tenantIdMaxEntriesLocalHeap; + + @Value("${cache.tenantId.configuration.eternal}") + private boolean tenantIdEternal; + + @Value("${cache.tenantId.configuration.timeToIdleSeconds}") + private long tenantIdTimeToIdleSeconds; + + @Value("${cache.singleTenant.configuration.timeToLiveSeconds}") + private long tenantIdTimeToLiveSeconds; + + @Value("${cache.singleTenant.configuration.maxEntriesLocalHeap}") + private long singleTenantMaxEntriesLocalHeap; + + @Value("${cache.singleTenant.configuration.eternal}") + private boolean singleTenantEternal; + + @Value("${cache.singleTenant.configuration.timeToIdleSeconds}") + private long singleTenantTimeToIdleSeconds; + + @Value("${cache.singleTenant.configuration.timeToLiveSeconds}") + private long singleTenantTimeToLiveSeconds; + @Value("${cache.topic.configuration.maxEntriesLocalHeap}") private long topicMaxEntriesLocalHeap; @@ -62,6 +88,8 @@ public net.sf.ehcache.CacheManager ehCacheManager() { var config = new net.sf.ehcache.config.Configuration(); config.addCache(buildConsultingTypeCacheConfiguration()); config.addCache(buildTenantCacheConfiguration()); + config.addCache(buildTenantIdCacheConfiguration()); + config.addCache(buildSingleTenantCacheConfiguration()); config.addCache(buildTopicCacheConfiguration()); return net.sf.ehcache.CacheManager.newInstance(config); } @@ -95,4 +123,24 @@ private CacheConfiguration buildTenantCacheConfiguration() { tenantCacheConfiguration.setTimeToLiveSeconds(tenantTimeToLiveSeconds); return tenantCacheConfiguration; } + + private CacheConfiguration buildTenantIdCacheConfiguration() { + var tenantCacheConfiguration = new CacheConfiguration(); + tenantCacheConfiguration.setName(TENANT_ID_CACHE); + tenantCacheConfiguration.setMaxEntriesLocalHeap(tenantIdMaxEntriesLocalHeap); + tenantCacheConfiguration.setEternal(tenantIdEternal); + tenantCacheConfiguration.setTimeToIdleSeconds(tenantIdTimeToIdleSeconds); + tenantCacheConfiguration.setTimeToLiveSeconds(tenantIdTimeToLiveSeconds); + return tenantCacheConfiguration; + } + + private CacheConfiguration buildSingleTenantCacheConfiguration() { + var tenantCacheConfiguration = new CacheConfiguration(); + tenantCacheConfiguration.setName(SINGLE_TENANT_CACHE); + tenantCacheConfiguration.setMaxEntriesLocalHeap(singleTenantMaxEntriesLocalHeap); + tenantCacheConfiguration.setEternal(singleTenantEternal); + tenantCacheConfiguration.setTimeToIdleSeconds(singleTenantTimeToIdleSeconds); + tenantCacheConfiguration.setTimeToLiveSeconds(singleTenantTimeToLiveSeconds); + return tenantCacheConfiguration; + } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 0ab85218..38ecaa73 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -54,6 +54,16 @@ cache.tenant.configuration.eternal=false cache.tenant.configuration.timeToIdleSeconds=0 cache.tenant.configuration.timeToLiveSeconds=86400 +cache.tenantId.configuration.maxEntriesLocalHeap=100 +cache.tenantId.configuration.eternal=false +cache.tenantId.configuration.timeToIdleSeconds=0 +cache.tenantId.configuration.timeToLiveSeconds=86400 + +cache.singleTenant.configuration.maxEntriesLocalHeap=100 +cache.singleTenant.configuration.eternal=false +cache.singleTenant.configuration.timeToIdleSeconds=0 +cache.singleTenant.configuration.timeToLiveSeconds=86400 + cache.topic.configuration.maxEntriesLocalHeap=100 cache.topic.configuration.eternal=false cache.topic.configuration.timeToIdleSeconds=0 diff --git a/src/test/java/de/caritas/cob/agencyservice/api/service/AgencyServiceTenantAwareTest.java b/src/test/java/de/caritas/cob/agencyservice/api/service/AgencyServiceTenantAwareTest.java new file mode 100644 index 00000000..873a141e --- /dev/null +++ b/src/test/java/de/caritas/cob/agencyservice/api/service/AgencyServiceTenantAwareTest.java @@ -0,0 +1,94 @@ +package de.caritas.cob.agencyservice.api.service; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import de.caritas.cob.agencyservice.api.exception.MissingConsultingTypeException; +import de.caritas.cob.agencyservice.api.exception.httpresponses.BadRequestException; +import de.caritas.cob.agencyservice.api.manager.consultingtype.ConsultingTypeManager; +import de.caritas.cob.agencyservice.api.repository.agency.AgencyRepository; +import de.caritas.cob.agencyservice.api.tenant.TenantContext; +import de.caritas.cob.agencyservice.consultingtypeservice.generated.web.model.ExtendedConsultingTypeResponseDTO; +import de.caritas.cob.agencyservice.consultingtypeservice.generated.web.model.RegistrationDTO; +import de.caritas.cob.agencyservice.tenantservice.generated.web.model.RestrictedTenantDTO; +import de.caritas.cob.agencyservice.tenantservice.generated.web.model.Settings; +import java.util.Optional; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; +import org.springframework.test.util.ReflectionTestUtils; + +@RunWith(MockitoJUnitRunner.class) +public class AgencyServiceTenantAwareTest { + + @InjectMocks + private AgencyService agencyService; + + @Mock + ConsultingTypeManager consultingTypeManager; + + @Mock + TenantService tenantService; + + @Mock + private AgencyRepository agencyRepository; + + private static final Long TENANT_ID = 1L; + + @Before + public void before() { + ReflectionTestUtils.setField(agencyService, "multitenancy", true); + TenantContext.setCurrentTenant(TENANT_ID); + } + + @After + public void tearDown() { + ReflectionTestUtils.setField(agencyService, "topicsFeatureEnabled", false); + } + + @Test(expected = BadRequestException.class) + public void getAgencies_Should_throwBadRequestException_When_topicIdNotProvidedAndFeatureEnabled() + throws MissingConsultingTypeException { + // given + ReflectionTestUtils.setField(agencyService, "topicsFeatureEnabled", true); + ExtendedConsultingTypeResponseDTO dto = new ExtendedConsultingTypeResponseDTO().registration( + new RegistrationDTO().minPostcodeSize(5)); + when(consultingTypeManager.getConsultingTypeSettings(1)).thenReturn(dto); + RestrictedTenantDTO restrictedTenantDTO = new RestrictedTenantDTO().settings( + new Settings().topicsInRegistrationEnabled(true)); + when(tenantService.getRestrictedTenantDataByTenantId(TENANT_ID)).thenReturn( + restrictedTenantDTO); + + // when + this.agencyService.getAgencies("12123", 1, Optional.empty()); + + // then + verify(agencyRepository).findByPostCodeAndConsultingTypeIdAndTopicId("12123", 5, 1, 2, + TENANT_ID); + } + + @Test + public void getAgencies_Should_searchByTopicId_When_topicIdProvidedAndFeatureEnabled() + throws MissingConsultingTypeException { + // given + ReflectionTestUtils.setField(agencyService, "topicsFeatureEnabled", true); + ExtendedConsultingTypeResponseDTO dto = new ExtendedConsultingTypeResponseDTO().registration( + new RegistrationDTO().minPostcodeSize(5)); + when(consultingTypeManager.getConsultingTypeSettings(1)).thenReturn(dto); + RestrictedTenantDTO restrictedTenantDTO = new RestrictedTenantDTO().settings( + new Settings().topicsInRegistrationEnabled(true)); + when(tenantService.getRestrictedTenantDataByTenantId(TENANT_ID)).thenReturn( + restrictedTenantDTO); + + // when + this.agencyService.getAgencies("12123", 1, Optional.of(2)); + + // then + verify(agencyRepository).findByPostCodeAndConsultingTypeIdAndTopicId("12123", 5, 1, 2, + TENANT_ID); + } +} diff --git a/src/test/java/de/caritas/cob/agencyservice/api/service/AgencyServiceTest.java b/src/test/java/de/caritas/cob/agencyservice/api/service/AgencyServiceTest.java index a9087af7..c42f661f 100644 --- a/src/test/java/de/caritas/cob/agencyservice/api/service/AgencyServiceTest.java +++ b/src/test/java/de/caritas/cob/agencyservice/api/service/AgencyServiceTest.java @@ -41,10 +41,11 @@ import de.caritas.cob.agencyservice.api.repository.agency.AgencyRepository; import de.caritas.cob.agencyservice.consultingtypeservice.generated.web.model.ExtendedConsultingTypeResponseDTO; import de.caritas.cob.agencyservice.consultingtypeservice.generated.web.model.RegistrationDTO; +import de.caritas.cob.agencyservice.tenantservice.generated.web.model.RestrictedTenantDTO; +import de.caritas.cob.agencyservice.tenantservice.generated.web.model.Settings; import java.util.ArrayList; import java.util.Collections; import java.util.Optional; -import javax.swing.text.html.Option; import org.hamcrest.collection.IsEmptyCollection; import org.jeasy.random.EasyRandom; import org.junit.After; @@ -66,6 +67,9 @@ public class AgencyServiceTest { @Mock ConsultingTypeManager consultingTypeManager; + @Mock + TenantService tenantService; + @Mock private AgencyRepository agencyRepository; @@ -74,6 +78,7 @@ public class AgencyServiceTest { @After public void tearDown() { ReflectionTestUtils.setField(agencyService, "topicsFeatureEnabled", false); + ReflectionTestUtils.setField(agencyService, "multitenancy", false); } @Test @@ -279,8 +284,12 @@ public void getAgencies_Should_throwBadRequestException_When_TopicIdNotProvidedA throws MissingConsultingTypeException { // given ReflectionTestUtils.setField(agencyService, "topicsFeatureEnabled", true); - ExtendedConsultingTypeResponseDTO dto = new ExtendedConsultingTypeResponseDTO().registration(new RegistrationDTO().minPostcodeSize(5)); + ExtendedConsultingTypeResponseDTO dto = new ExtendedConsultingTypeResponseDTO().registration( + new RegistrationDTO().minPostcodeSize(5)); when(consultingTypeManager.getConsultingTypeSettings(1)).thenReturn(dto); + RestrictedTenantDTO restrictedTenantDTO = new RestrictedTenantDTO().settings( + new Settings().topicsInRegistrationEnabled(true)); + when(tenantService.getRestrictedTenantDataForSingleTenant()).thenReturn(restrictedTenantDTO); // when this.agencyService.getAgencies("12123", 1, Optional.empty()); @@ -291,8 +300,12 @@ public void getAgencies_Should_searchByTopicId_When_TopicIdProvidedAndFeatureEna throws MissingConsultingTypeException { // given ReflectionTestUtils.setField(agencyService, "topicsFeatureEnabled", true); - ExtendedConsultingTypeResponseDTO dto = new ExtendedConsultingTypeResponseDTO().registration(new RegistrationDTO().minPostcodeSize(5)); + ExtendedConsultingTypeResponseDTO dto = new ExtendedConsultingTypeResponseDTO().registration( + new RegistrationDTO().minPostcodeSize(5)); when(consultingTypeManager.getConsultingTypeSettings(1)).thenReturn(dto); + RestrictedTenantDTO restrictedTenantDTO = new RestrictedTenantDTO().settings( + new Settings().topicsInRegistrationEnabled(true)); + when(tenantService.getRestrictedTenantDataForSingleTenant()).thenReturn(restrictedTenantDTO); // when this.agencyService.getAgencies("12123", 1, Optional.of(2)); From 487c0c997c38ff5eeb87dd82d893fb3ea15af8d8 Mon Sep 17 00:00:00 2001 From: tkuzynow Date: Tue, 28 Jun 2022 10:59:09 +0200 Subject: [PATCH 5/7] fix: NPE when topics are empty --- .../agency/AgencyTopicEnrichmentService.java | 7 ++++++- .../AgencyTopicEnrichmentServiceTest.java | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java b/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java index 7cfacb4b..8174bcc1 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java @@ -48,7 +48,12 @@ private void enrichSingleAgencyTopic(Map availableTopics, private Map getAvailableTopicsMap() { var allTopics = topicService.getAllTopics(); - return allTopics.isEmpty() ? Maps.newHashMap() : getAvailableTopicsMap(allTopics); + return isEmptyOrNull(allTopics) ? Maps.newHashMap() : getAvailableTopicsMap(allTopics); + } + + private boolean isEmptyOrNull( + List allTopics) { + return allTopics == null || allTopics.isEmpty(); } private Map getAvailableTopicsMap( diff --git a/src/test/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentServiceTest.java b/src/test/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentServiceTest.java index b16cda40..0118c575 100644 --- a/src/test/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentServiceTest.java +++ b/src/test/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentServiceTest.java @@ -62,6 +62,25 @@ void enrichAgencyWithTopics_Should_NotEnrichIfNoTopicsAreDefined() { .containsOnlyNulls(); } + + @Test + void enrichAgencyWithTopics_Should_NotEnrichIfTopicsListIsNull() { + // given + when(topicService.getAllTopics()).thenReturn( + null); + var agencyTopics = newArrayList( + createAgencyTopic(new Agency(), 1L), createAgencyTopic(new Agency(), 2L)); + + // when + var agency = newAgencyWithTopics(agencyTopics); + agencyTopicEnrichmentService.enrichAgencyWithTopics(agency); + + // then + assertThat(agency.getAgencyTopics()) + .extracting(agencyTopic -> agencyTopic.getTopicData().getName()) + .containsOnlyNulls(); + } + @Test void enrichAgencyWithTopics_Should_NotEnrichWithTopicDataIfTopicIdDoNotMatch() { // given From 1700f197357c3f2716d0a2be0d4fc54234049787 Mon Sep 17 00:00:00 2001 From: tkuzynow Date: Wed, 29 Jun 2022 09:49:33 +0200 Subject: [PATCH 6/7] fix: checkstyle --- .../service/agency/AgencyTopicEnrichmentService.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java b/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java index 8174bcc1..adb74079 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/admin/service/agency/AgencyTopicEnrichmentService.java @@ -51,11 +51,6 @@ private Map getAvailableTopicsMap() { return isEmptyOrNull(allTopics) ? Maps.newHashMap() : getAvailableTopicsMap(allTopics); } - private boolean isEmptyOrNull( - List allTopics) { - return allTopics == null || allTopics.isEmpty(); - } - private Map getAvailableTopicsMap( List allTopics) { return allTopics.stream() @@ -64,6 +59,11 @@ private Map getAvailableTopicsMap( this::convertToAgencyServiceTopicViewDTO)); } + private boolean isEmptyOrNull( + List allTopics) { + return allTopics == null || allTopics.isEmpty(); + } + private TopicDTO convertToAgencyServiceTopicViewDTO( de.caritas.cob.agencyservice.topicservice.generated.web.model.TopicDTO source) { return new TopicDTO().id(source.getId()) From 0fcdc630bb26efae6f38c31dbce39aaedf6bfdfc Mon Sep 17 00:00:00 2001 From: Patric Dosch Date: Wed, 29 Jun 2022 14:03:56 +0200 Subject: [PATCH 7/7] feat: VIC-665 Registration | Basic registration with a main topic (and no PLZ) - changes from PR comments --- .../api/service/AgencyService.java | 18 +++---- .../api/service/TenantService.java | 8 +++- .../config/CacheManagerConfig.java | 48 ------------------- src/main/resources/application.properties | 10 ---- 4 files changed, 16 insertions(+), 68 deletions(-) diff --git a/src/main/java/de/caritas/cob/agencyservice/api/service/AgencyService.java b/src/main/java/de/caritas/cob/agencyservice/api/service/AgencyService.java index ae93596b..0946647a 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/service/AgencyService.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/service/AgencyService.java @@ -130,14 +130,7 @@ private boolean isTopicFeatureEnabledAndActivatedInRegistration() { } private boolean isTopicFeatureActivatedInRegistration() { - RestrictedTenantDTO restrictedTenantDTO; - if (multitenancy) { - Long tenantId = TenantContext.getCurrentTenant(); - restrictedTenantDTO = tenantService.getRestrictedTenantDataByTenantId(tenantId); - } else { - restrictedTenantDTO = tenantService.getRestrictedTenantDataForSingleTenant(); - } - + RestrictedTenantDTO restrictedTenantDTO = getRestrictedTenantData(); if (nonNull(restrictedTenantDTO) && nonNull(restrictedTenantDTO.getSettings())) { return Boolean.TRUE.equals( restrictedTenantDTO.getSettings().getTopicsInRegistrationEnabled()); @@ -145,6 +138,15 @@ private boolean isTopicFeatureActivatedInRegistration() { return false; } + private RestrictedTenantDTO getRestrictedTenantData() { + if (multitenancy) { + Long tenantId = TenantContext.getCurrentTenant(); + return tenantService.getRestrictedTenantDataByTenantId(tenantId); + } else { + return tenantService.getRestrictedTenantDataForSingleTenant(); + } + } + private void verifyConsultingTypeExists(int consultingTypeId) throws MissingConsultingTypeException { consultingTypeManager.getConsultingTypeSettings(consultingTypeId); diff --git a/src/main/java/de/caritas/cob/agencyservice/api/service/TenantService.java b/src/main/java/de/caritas/cob/agencyservice/api/service/TenantService.java index b473c137..e6224447 100644 --- a/src/main/java/de/caritas/cob/agencyservice/api/service/TenantService.java +++ b/src/main/java/de/caritas/cob/agencyservice/api/service/TenantService.java @@ -5,6 +5,7 @@ import de.caritas.cob.agencyservice.tenantservice.generated.web.model.RestrictedTenantDTO; import lombok.NonNull; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; @@ -14,17 +15,20 @@ public class TenantService { private final @NonNull TenantControllerApi tenantControllerApi; + @Value("${multitenancy.enabled}") + private boolean multitenancy; + @Cacheable(cacheNames = CacheManagerConfig.TENANT_CACHE, key = "#subdomain") public RestrictedTenantDTO getRestrictedTenantDataBySubdomain(String subdomain) { return tenantControllerApi.getRestrictedTenantDataBySubdomainWithHttpInfo(subdomain).getBody(); } - @Cacheable(cacheNames = CacheManagerConfig.TENANT_ID_CACHE, key = "#tenantId") + @Cacheable(cacheNames = CacheManagerConfig.TENANT_CACHE, key = "#tenantId") public RestrictedTenantDTO getRestrictedTenantDataByTenantId(Long tenantId) { return tenantControllerApi.getRestrictedTenantDataByTenantId(tenantId); } - @Cacheable(cacheNames = CacheManagerConfig.SINGLE_TENANT_CACHE) + @Cacheable(cacheNames = CacheManagerConfig.TENANT_CACHE) public RestrictedTenantDTO getRestrictedTenantDataForSingleTenant() { return tenantControllerApi.getRestrictedSingleTenantData(); } diff --git a/src/main/java/de/caritas/cob/agencyservice/config/CacheManagerConfig.java b/src/main/java/de/caritas/cob/agencyservice/config/CacheManagerConfig.java index 81305895..50e8a3db 100644 --- a/src/main/java/de/caritas/cob/agencyservice/config/CacheManagerConfig.java +++ b/src/main/java/de/caritas/cob/agencyservice/config/CacheManagerConfig.java @@ -14,8 +14,6 @@ public class CacheManagerConfig { public static final String CONSULTING_TYPE_CACHE = "consultingTypeCache"; public static final String TENANT_CACHE = "tenantCache"; - public static final String TENANT_ID_CACHE = "tenantIdCache"; - public static final String SINGLE_TENANT_CACHE = "singleTenantCache"; public static final String TOPICS_CACHE = "topicsCache"; @Value("${cache.consulting.type.configuration.maxEntriesLocalHeap}") @@ -42,30 +40,6 @@ public class CacheManagerConfig { @Value("${cache.tenant.configuration.timeToLiveSeconds}") private long tenantTimeToLiveSeconds; - @Value("${cache.tenantId.configuration.maxEntriesLocalHeap}") - private long tenantIdMaxEntriesLocalHeap; - - @Value("${cache.tenantId.configuration.eternal}") - private boolean tenantIdEternal; - - @Value("${cache.tenantId.configuration.timeToIdleSeconds}") - private long tenantIdTimeToIdleSeconds; - - @Value("${cache.singleTenant.configuration.timeToLiveSeconds}") - private long tenantIdTimeToLiveSeconds; - - @Value("${cache.singleTenant.configuration.maxEntriesLocalHeap}") - private long singleTenantMaxEntriesLocalHeap; - - @Value("${cache.singleTenant.configuration.eternal}") - private boolean singleTenantEternal; - - @Value("${cache.singleTenant.configuration.timeToIdleSeconds}") - private long singleTenantTimeToIdleSeconds; - - @Value("${cache.singleTenant.configuration.timeToLiveSeconds}") - private long singleTenantTimeToLiveSeconds; - @Value("${cache.topic.configuration.maxEntriesLocalHeap}") private long topicMaxEntriesLocalHeap; @@ -88,8 +62,6 @@ public net.sf.ehcache.CacheManager ehCacheManager() { var config = new net.sf.ehcache.config.Configuration(); config.addCache(buildConsultingTypeCacheConfiguration()); config.addCache(buildTenantCacheConfiguration()); - config.addCache(buildTenantIdCacheConfiguration()); - config.addCache(buildSingleTenantCacheConfiguration()); config.addCache(buildTopicCacheConfiguration()); return net.sf.ehcache.CacheManager.newInstance(config); } @@ -123,24 +95,4 @@ private CacheConfiguration buildTenantCacheConfiguration() { tenantCacheConfiguration.setTimeToLiveSeconds(tenantTimeToLiveSeconds); return tenantCacheConfiguration; } - - private CacheConfiguration buildTenantIdCacheConfiguration() { - var tenantCacheConfiguration = new CacheConfiguration(); - tenantCacheConfiguration.setName(TENANT_ID_CACHE); - tenantCacheConfiguration.setMaxEntriesLocalHeap(tenantIdMaxEntriesLocalHeap); - tenantCacheConfiguration.setEternal(tenantIdEternal); - tenantCacheConfiguration.setTimeToIdleSeconds(tenantIdTimeToIdleSeconds); - tenantCacheConfiguration.setTimeToLiveSeconds(tenantIdTimeToLiveSeconds); - return tenantCacheConfiguration; - } - - private CacheConfiguration buildSingleTenantCacheConfiguration() { - var tenantCacheConfiguration = new CacheConfiguration(); - tenantCacheConfiguration.setName(SINGLE_TENANT_CACHE); - tenantCacheConfiguration.setMaxEntriesLocalHeap(singleTenantMaxEntriesLocalHeap); - tenantCacheConfiguration.setEternal(singleTenantEternal); - tenantCacheConfiguration.setTimeToIdleSeconds(singleTenantTimeToIdleSeconds); - tenantCacheConfiguration.setTimeToLiveSeconds(singleTenantTimeToLiveSeconds); - return tenantCacheConfiguration; - } } diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 38ecaa73..0ab85218 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -54,16 +54,6 @@ cache.tenant.configuration.eternal=false cache.tenant.configuration.timeToIdleSeconds=0 cache.tenant.configuration.timeToLiveSeconds=86400 -cache.tenantId.configuration.maxEntriesLocalHeap=100 -cache.tenantId.configuration.eternal=false -cache.tenantId.configuration.timeToIdleSeconds=0 -cache.tenantId.configuration.timeToLiveSeconds=86400 - -cache.singleTenant.configuration.maxEntriesLocalHeap=100 -cache.singleTenant.configuration.eternal=false -cache.singleTenant.configuration.timeToIdleSeconds=0 -cache.singleTenant.configuration.timeToLiveSeconds=86400 - cache.topic.configuration.maxEntriesLocalHeap=100 cache.topic.configuration.eternal=false cache.topic.configuration.timeToIdleSeconds=0