diff --git a/descriptors/ModuleDescriptor-template.json b/descriptors/ModuleDescriptor-template.json index b5dd6917..eecca252 100644 --- a/descriptors/ModuleDescriptor-template.json +++ b/descriptors/ModuleDescriptor-template.json @@ -794,15 +794,19 @@ "circulation-storage.cancellation-reasons.item.delete", "user-settings.custom-fields.item.post", "user-settings.custom-fields.collection.get", + "roles.collection.get", "roles.item.post", "roles.item.put", "roles.item.delete", + "policies.item.get", "policies.item.post", "policies.item.put", "policies.item.delete", + "role-capabilities.collection.get", "role-capabilities.collection.post", "role-capabilities.collection.put", "role-capabilities.collection.delete", + "role-capability-sets.collection.get", "role-capability-sets.collection.post", "role-capability-sets.collection.put", "role-capability-sets.collection.delete" diff --git a/src/main/java/org/folio/consortia/client/PoliciesClient.java b/src/main/java/org/folio/consortia/client/PoliciesClient.java new file mode 100644 index 00000000..40819baf --- /dev/null +++ b/src/main/java/org/folio/consortia/client/PoliciesClient.java @@ -0,0 +1,14 @@ +package org.folio.consortia.client; + +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +import java.util.UUID; + +@FeignClient(name = "policies") +public interface PoliciesClient { + + @GetMapping(value = "/{policyId}") + void getPolicyById(@PathVariable UUID policyId); +} diff --git a/src/main/java/org/folio/consortia/client/RoleCapabilitiesClient.java b/src/main/java/org/folio/consortia/client/RoleCapabilitiesClient.java new file mode 100644 index 00000000..ef589316 --- /dev/null +++ b/src/main/java/org/folio/consortia/client/RoleCapabilitiesClient.java @@ -0,0 +1,16 @@ +package org.folio.consortia.client; + + +import java.util.UUID; + +import org.folio.consortia.domain.dto.Capabilities; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +@FeignClient(name = "role-capabilities", url = "roles") +public interface RoleCapabilitiesClient { + + @GetMapping(value = "/{roleId}/capabilities") + Capabilities getRoleCapabilitiesByRoleId(@PathVariable UUID roleId); +} diff --git a/src/main/java/org/folio/consortia/client/RoleCapabilitySetsClient.java b/src/main/java/org/folio/consortia/client/RoleCapabilitySetsClient.java new file mode 100644 index 00000000..78e8f67f --- /dev/null +++ b/src/main/java/org/folio/consortia/client/RoleCapabilitySetsClient.java @@ -0,0 +1,15 @@ +package org.folio.consortia.client; + +import java.util.UUID; + +import org.folio.consortia.domain.dto.CapabilitySets; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; + +@FeignClient(name = "role-capability-sets", url = "roles") +public interface RoleCapabilitySetsClient { + + @GetMapping(value = "/{roleId}/capability-sets") + CapabilitySets getRoleCapabilitySetsRoleId(@PathVariable UUID roleId); +} diff --git a/src/main/java/org/folio/consortia/client/RolesClient.java b/src/main/java/org/folio/consortia/client/RolesClient.java new file mode 100644 index 00000000..d871da46 --- /dev/null +++ b/src/main/java/org/folio/consortia/client/RolesClient.java @@ -0,0 +1,14 @@ +package org.folio.consortia.client; + +import org.folio.consortia.domain.dto.Roles; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; + +@FeignClient(name = "roles") +public interface RolesClient { + + @GetMapping + Roles getRolesByQuery(@RequestParam("query") String query); + +} diff --git a/src/main/java/org/folio/consortia/domain/entity/SharingRoleEntity.java b/src/main/java/org/folio/consortia/domain/entity/SharingRoleEntity.java index 7ca41a35..2bfa1f0c 100644 --- a/src/main/java/org/folio/consortia/domain/entity/SharingRoleEntity.java +++ b/src/main/java/org/folio/consortia/domain/entity/SharingRoleEntity.java @@ -24,6 +24,7 @@ public class SharingRoleEntity extends AuditableEntity { @Id private UUID id; private UUID roleId; + private String roleName; private String tenantId; private Boolean isCapabilitySetsShared; private Boolean isCapabilitiesShared; diff --git a/src/main/java/org/folio/consortia/repository/SharingPolicyRepository.java b/src/main/java/org/folio/consortia/repository/SharingPolicyRepository.java index ebf4df17..d1442c0f 100644 --- a/src/main/java/org/folio/consortia/repository/SharingPolicyRepository.java +++ b/src/main/java/org/folio/consortia/repository/SharingPolicyRepository.java @@ -17,6 +17,8 @@ public interface SharingPolicyRepository extends JpaRepository { - List findByRoleId(UUID roleId); + List findByRoleName(String roleName); - SharingRoleEntity findByRoleIdAndTenantId(UUID roleId, String tenantId); + Optional findByRoleNameAndTenantId(String roleName, String tenantId); - @Query("SELECT sr.tenantId FROM SharingRoleEntity sr WHERE sr.roleId = ?1") - Set findTenantsByRoleId(UUID roleId); + Optional findByRoleIdAndTenantId(UUID roleId, String tenantId); - Set findTenantsByRoleIdAndIsCapabilitySetsSharedTrue(UUID roleId); + @Query("SELECT sr.tenantId FROM SharingRoleEntity sr WHERE sr.roleName = ?1") + Set findTenantsByRoleName(String roleName); - Set findTenantsByRoleIdAndIsCapabilitiesSharedTrue(UUID roleId); + @Query("SELECT sr.tenantId FROM SharingRoleEntity sr WHERE sr.roleName = ?1 and sr.isCapabilitiesShared = true") + Set findTenantsByRoleNameAndIsCapabilitiesSharedTrue(String roleName); + + @Query("SELECT sr.tenantId FROM SharingRoleEntity sr WHERE sr.roleName = ?1 and sr.isCapabilitySetsShared = true") + Set findTenantsByRoleNameAndIsCapabilitySetsSharedTrue(String roleName); + + @Query("select s.roleId from SharingRoleEntity s where s.roleName = ?1 and s.tenantId = ?2") + UUID findRoleIdByRoleNameAndTenantId(String roleName, String tenantId); boolean existsByRoleId(UUID roleId); + boolean existsByRoleIdAndTenantId(UUID roleId, String tenantId); + + boolean existsByRoleNameAndTenantIdAndIsCapabilitiesSharedTrue(String roleName, String tenantId); + boolean existsByRoleNameAndTenantIdAndIsCapabilitySetsSharedTrue(String roleName, String tenantId); + @Modifying - void deleteByRoleId(UUID roleId); + void deleteByRoleName(String roleName); } diff --git a/src/main/java/org/folio/consortia/service/BaseSharingService.java b/src/main/java/org/folio/consortia/service/BaseSharingService.java index 29489e52..f579ed14 100644 --- a/src/main/java/org/folio/consortia/service/BaseSharingService.java +++ b/src/main/java/org/folio/consortia/service/BaseSharingService.java @@ -3,11 +3,11 @@ import static org.folio.spring.scope.FolioExecutionScopeExecutionContextManager.getRunnableWithCurrentFolioContext; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.UUID; import java.util.stream.Collectors; +import java.util.stream.Stream; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; @@ -49,163 +49,113 @@ public abstract class BaseSharingService sharingConfigTenants = findTenantsForConfig(sharingConfigRequest); + syncConfigWithTenants(request); + + Set sharedConfigTenants = findTenantsForConfig(request); TenantCollection allTenants = tenantService.getAll(consortiumId); - var publicationPostRequest = createPublicationRequest(sharingConfigRequest, HttpMethod.POST); - var publicationPutRequest = createPublicationRequest(sharingConfigRequest, HttpMethod.PUT); + List pubPostRequests = new ArrayList<>(); + List pubPutRequests = new ArrayList<>(); + + List sharingConfigEntityList = new ArrayList<>(); + + for (Tenant tenant : allTenants.getTenants()) { + var method = sharedConfigTenants.contains(tenant.getId()) ? HttpMethod.PUT : HttpMethod.POST; + var publicationRequest = buildPublicationRequestForTenant(request, tenant.getId(), method); + + if (method == HttpMethod.PUT) { + pubPutRequests.add(publicationRequest); + } else { + pubPostRequests.add(publicationRequest); + sharingConfigEntityList.add(createSharingConfigEntityFromRequest(request, tenant.getId())); + } + + log.info("start:: tenant={} added to publication {} request for {}={}", + tenant.getId(), method.toString(), getClassName(request), getConfigId(request)); + } + + // make to one request for all tenants if required by configuration + compactPublishRequestsIfNeed(pubPostRequests); + compactPublishRequestsIfNeed(pubPutRequests); - List sharingConfigEntityList = linkTenantsToPublicationPutPostRequestAndEntity(allTenants, - sharingConfigRequest, sharingConfigTenants, publicationPutRequest, publicationPostRequest); saveSharingConfig(sharingConfigEntityList); log.info("start:: The Sharing {}s for {} ID '{}' and '{}' unique tenant(s) were successfully" + - " saved to the database", configName, configName, configId, publicationPostRequest.getTenants().size()); + " saved to the database", configName, configName, configId, sharingConfigEntityList.size()); var sourceValue = getSourceValue(SourceValues.CONSORTIUM); - ObjectNode updatedPayload = updatePayload(sharingConfigRequest, sourceValue); - publicationPostRequest.setPayload(updatedPayload); - publicationPutRequest.setPayload(updatedPayload); + Stream.of(pubPostRequests, pubPutRequests) + .forEach(requests -> requests.forEach(pubRequest -> + pubRequest.setPayload(updateSourcePayload(pubRequest.getPayload(), sourceValue)))); + log.info("start:: set source as '{}' in payload of {}: {}", sourceValue, configName, configId); // create PC request with POST and PUT Http method to create configs, using 'mod-consortia-keycloak' system user return systemUserScopedExecutionService.executeSystemUserScoped(folioExecutionContext.getTenantId(), () -> { - UUID createConfigsPcId = publishRequest(consortiumId, publicationPostRequest); - UUID updateConfigsPcId = publishRequest(consortiumId, publicationPutRequest); - return createSharingConfigResponse(createConfigsPcId, updateConfigsPcId); + var createConfigsPcIds = executePublishRequests(consortiumId, pubPostRequests); + var updateConfigsPcIds = executePublishRequests(consortiumId, pubPutRequests); + + return createSharingConfigResponse(createConfigsPcIds, updateConfigsPcIds); }); } - @Transactional @SneakyThrows - public TDeleteResponse delete(UUID consortiumId, UUID configId, TRequest sharingConfigRequest) { - String configName = getClassName(sharingConfigRequest); + public TDeleteResponse delete(UUID consortiumId, UUID configId, TRequest request) { + String configName = getClassName(request); log.debug("delete:: Trying to delete sharing '{}' with consortiumId: {}, sharing {} ID: {}", configName, consortiumId, configName, configId); - validateSharingConfigRequestOrThrow(configId, sharingConfigRequest); + validateSharingConfigRequestOrThrow(configId, request); consortiumService.checkConsortiumExistsOrThrow(consortiumId); - Set sharingConfigTenants = findTenantsForConfig(sharingConfigRequest); + syncConfigWithTenants(request); + + Set sharedTenants = findTenantsForConfig(request); TenantCollection allTenants = tenantService.getAll(consortiumId); - var publicationDeleteRequest = createPublicationRequest(sharingConfigRequest, HttpMethod.DELETE); - linkTenantsToPublicationDeleteRequest(allTenants, sharingConfigRequest, sharingConfigTenants, publicationDeleteRequest); - log.info("delete:: Tenants with size: {} successfully added to appropriate DELETE publication " + - "request for {}: {}", allTenants.getTotalRecords(), configName, configId); - deleteSharingConfig(configId); - log.info("delete:: The Sharing {}s for {} ID '{}' and '{}' unique tenant(s) were successfully " + - "deleted from the database", configName, configName, configId, publicationDeleteRequest.getTenants().size()); + List pubDeleteRequests = new ArrayList<>(); + + for (Tenant tenant : allTenants.getTenants()) { + if (sharedTenants.contains(tenant.getId())) { + pubDeleteRequests.add(buildPublicationRequestForTenant(request, tenant.getId(), HttpMethod.DELETE)); + } + } + + compactPublishRequestsIfNeed(pubDeleteRequests); + deleteSharingConfig(request); + log.info("delete:: The Sharing {}s for {} ID '{}' and '{}' tenant(s) were successfully" + + " deleted from the database", configName, configName, configId, sharedTenants); // create PC request with DELETE Http method to create configs, using 'mod-consortia-keycloak' system user return systemUserScopedExecutionService.executeSystemUserScoped(folioExecutionContext.getTenantId(), () -> { - var pcId = publishRequest(consortiumId, publicationDeleteRequest); - var sharingConfigDeleteResponse = createSharingConfigResponse(pcId); + var pcIds = executePublishRequests(consortiumId, pubDeleteRequests); + var sharingConfigDeleteResponse = createSharingConfigDeleteResponse(pcIds); // update sources of failed requests asyncTaskExecutor.execute(getRunnableWithCurrentFolioContext(() -> - updateConfigsForFailedTenantsWithRetry(consortiumId, pcId, sharingConfigRequest))); + pcIds.forEach(pcId -> updateConfigsForFailedTenantsWithRetry(consortiumId, pcId, request)))); return sharingConfigDeleteResponse; }); } - private String getClassName(TRequest sharingConfigRequest) { - return sharingConfigRequest.getClass().getName(); - } - - private void checkEqualsOfPayloadIdWithConfigId(TRequest sharingConfigRequest) { - String sharingConfigId = String.valueOf(getConfigId(sharingConfigRequest)); - var payloadNode = objectMapper.convertValue(getPayload(sharingConfigRequest), ObjectNode.class); - String payloadId = getPayloadId(payloadNode); - if (ObjectUtils.notEqual(sharingConfigId, payloadId)) { - throw new IllegalArgumentException("Mismatch ID in payload with ID"); - } - } - - /** - * Method traverse through all tenants in db. - * It will add tenant to 'PUT' method publication tenant list if it exists in config tenant associations. - * Otherwise, it will add it to 'POST' method publication tenant list and add to sharingConfigEntityList - * - * @param allTenants all existing tenants in db - * @param sharingConfigRequest sharing config request - * @param sharingConfigTenants existing tenants in configs - * @param publicationPutRequest publication put request - * @param publicationPostRequest publication post request - * @return List of SharingConfigEntity objects - */ - private List linkTenantsToPublicationPutPostRequestAndEntity(TenantCollection allTenants, - TRequest sharingConfigRequest, - Set sharingConfigTenants, - PublicationRequest publicationPutRequest, - PublicationRequest publicationPostRequest) { - List sharingConfigEntityList = new ArrayList<>(); - for (Tenant tenant : allTenants.getTenants()) { - if (sharingConfigTenants.contains(tenant.getId())) { - publicationPutRequest.getTenants().add(tenant.getId()); - log.info("linkTenantsToPublicationPutPostRequestAndEntity:: tenant={} added to publication update request for {}={}", - tenant.getId(), getClassName(sharingConfigRequest), getConfigId(sharingConfigRequest)); - } else { - publicationPostRequest.getTenants().add(tenant.getId()); - log.info("linkTenantsToPublicationPutPostRequestAndEntity:: tenant={} added to publication create request for {}={}", - tenant.getId(), getClassName(sharingConfigRequest), getConfigId(sharingConfigRequest)); - sharingConfigEntityList.add(createSharingConfigEntityFromRequest(sharingConfigRequest, tenant.getId())); - } - } - return sharingConfigEntityList; - } - - /** - * Method traverse through all tenants in db. - * It will add a tenant to delete a request publication tenant list - * if it exists in config tenant associations - * - * @param allTenants all existing tenants in db - * @param sharingConfigRequest sharing config request - * @param sharingConfigTenants existing tenants in configs - * @param publicationDeleteRequest publication delete request - */ - private void linkTenantsToPublicationDeleteRequest(TenantCollection allTenants, - TRequest sharingConfigRequest, - Set sharingConfigTenants, - PublicationRequest publicationDeleteRequest) { - - for (Tenant tenant : allTenants.getTenants()) { - if (sharingConfigTenants.contains(tenant.getId())) { - publicationDeleteRequest.getTenants().add(tenant.getId()); - log.info("linkTenantsToPublicationDeleteRequest:: tenant={} added to publication delete request for {}={}", - tenant.getId(), getClassName(sharingConfigRequest), getConfigId(sharingConfigRequest)); - } - } - } - - - private UUID publishRequest(UUID consortiumId, PublicationRequest publicationRequest) { - if (CollectionUtils.isNotEmpty(publicationRequest.getTenants())) { - return publicationService.publishRequest(consortiumId, publicationRequest).getId(); - } - log.info("publishRequest:: Tenant list of publishing for http method: {} is empty", publicationRequest.getMethod()); - return null; - } - /** * The method execute updateConfigsForFailedTenants method with retry. * Retry based on maxTries @@ -217,6 +167,10 @@ private UUID publishRequest(UUID consortiumId, PublicationRequest publicationReq */ private void updateConfigsForFailedTenantsWithRetry(UUID consortiumId, UUID publicationId, TRequest sharingConfigRequest) { + if (publicationId == null) { + return; + } + RetryTemplate retryTemplate = new RetryTemplate(); SimpleRetryPolicy retryPolicy = new SimpleRetryPolicy(maxTries); @@ -268,45 +222,94 @@ private Set getFailedTenantList(UUID consortiumId, UUID publicationId) { .map(PublicationResult::getTenantId).collect(Collectors.toSet()); } - private void updateFailedConfigsToLocalSource(UUID consortiumId, TRequest sharingConfigRequest, + private void updateFailedConfigsToLocalSource(UUID consortiumId, TRequest request, Set failedTenantList) { log.info("updateFailedConfigsToLocalSource:: Updating failed '{}' tenants {}s ", - failedTenantList.size(), getClassName(sharingConfigRequest)); - var sourceValue = getSourceValue(SourceValues.USER); - ObjectNode updatedPayload = updatePayload(sharingConfigRequest, sourceValue); + failedTenantList.size(), getClassName(request)); + + List pubPutRequests = new ArrayList<>(); + failedTenantList.forEach(tenantId -> + pubPutRequests.add(buildPublicationRequestForTenant(request, tenantId, HttpMethod.PUT))); - PublicationRequest publicationPutRequest = createPublicationRequest(sharingConfigRequest, HttpMethod.PUT); - publicationPutRequest.setPayload(updatedPayload); - publicationPutRequest.setTenants(failedTenantList); + compactPublishRequestsIfNeed(pubPutRequests); + var sourceValue = getSourceValue(SourceValues.USER); + pubPutRequests.forEach(pubRequest -> pubRequest.setPayload(updateSourcePayload(pubRequest.getPayload(), sourceValue))); log.info("updateFailedConfigsToLocalSource:: send PUT request to publication with new source in " + "payload={} by system user of {}", sourceValue, folioExecutionContext.getTenantId()); - publishRequest(consortiumId, publicationPutRequest); + executePublishRequests(consortiumId, pubPutRequests); + } + + private void checkEqualsOfPayloadIdWithConfigId(TRequest sharingConfigRequest) { + String sharingConfigId = String.valueOf(getConfigId(sharingConfigRequest)); + var payloadNode = objectMapper.convertValue(getPayload(sharingConfigRequest), ObjectNode.class); + String payloadId = getPayloadId(payloadNode); + if (ObjectUtils.notEqual(sharingConfigId, payloadId)) { + throw new IllegalArgumentException("Mismatch ID in payload with ID"); + } + } + + private void compactPublishRequestsIfNeed(List publicationRequests) { + if (CollectionUtils.isEmpty(publicationRequests)) { + return; + } + + if (shouldCompactRequests()) { + log.info("compactPublishRequestsIfNeed:: compacting '{}' publish request(s) to one with all tenants and same payload", + publicationRequests.size()); + Set tenants = publicationRequests.stream() + .map(PublicationRequest::getTenants) + .flatMap(Set::stream) + .collect(Collectors.toSet()); + + publicationRequests.get(0).setTenants(tenants); + publicationRequests.subList(1, publicationRequests.size()).clear(); + } + } + + /** + * Execute all publish request and return list of response uuids + * @param consortiumId id of consortium + * @param publicationRequests list of publication request + * @return list of response uuids + */ + private List executePublishRequests(UUID consortiumId, List publicationRequests) { + return publicationRequests.stream() + .map(publicationRequest -> publishRequest(consortiumId, publicationRequest)) + .toList(); } - private PublicationRequest createPublicationRequest(TRequest sharingConfigRequest, HttpMethod method) { - String urlForRequest = getUrl(sharingConfigRequest, method); - return new PublicationRequest() - .method(method.toString()) - .url(urlForRequest) - .payload(getPayload(sharingConfigRequest)) - .tenants(new HashSet<>()); + private UUID publishRequest(UUID consortiumId, PublicationRequest publicationRequest) { + if (CollectionUtils.isEmpty(publicationRequest.getTenants())) { + log.info("publishRequest:: Tenant list of publishing for http method: {} is empty", publicationRequest.getMethod()); + return null; + } + + log.info("publishRequest:: Sending {} request to publication with {} tenants for consortiumId={} and url={}", + publicationRequest.getMethod(), publicationRequest.getTenants().size(), consortiumId, publicationRequest.getUrl()); + return publicationService.publishRequest(consortiumId, publicationRequest).getId(); } protected abstract UUID getConfigId(TRequest request); protected abstract Object getPayload(TRequest request); protected abstract String getPayloadId(ObjectNode payload); - protected abstract String getUrl(TRequest request, HttpMethod httpMethod); + protected abstract String getSourceValue(SourceValues sourceValue); + protected abstract boolean shouldCompactRequests(); protected abstract void validateSharingConfigRequestOrThrow(UUID configId, TRequest request); + protected abstract void syncConfigWithTenants(TRequest request); protected abstract Set findTenantsForConfig(TRequest request); protected abstract void saveSharingConfig(List enetityList); - protected abstract void deleteSharingConfig(UUID configId); + protected abstract void deleteSharingConfig(TRequest request); + protected abstract PublicationRequest buildPublicationRequestForTenant(TRequest request, String tenantId, + HttpMethod method); protected abstract TEntity createSharingConfigEntityFromRequest(TRequest request, String tenantId); - protected abstract TResponse createSharingConfigResponse(UUID createConfigsPcId, UUID updateConfigsPcId); - protected abstract TDeleteResponse createSharingConfigResponse(UUID publishRequestId); - protected abstract String getSourceValue(SourceValues sourceValue); - protected abstract ObjectNode updatePayload(TRequest request, String sourceValue); + protected abstract TResponse createSharingConfigResponse(List createConfigsPcId, List updateConfigsPcId); + protected abstract TDeleteResponse createSharingConfigDeleteResponse(List publishRequestId); + protected abstract ObjectNode updateSourcePayload(Object payload, String sourceValue); + private String getClassName(TRequest sharingConfigRequest) { + return sharingConfigRequest.getClass().getSimpleName(); + } } diff --git a/src/main/java/org/folio/consortia/service/impl/SharingPolicyService.java b/src/main/java/org/folio/consortia/service/impl/SharingPolicyService.java index 4f33fe22..ee9d173e 100644 --- a/src/main/java/org/folio/consortia/service/impl/SharingPolicyService.java +++ b/src/main/java/org/folio/consortia/service/impl/SharingPolicyService.java @@ -3,8 +3,12 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; +import feign.FeignException; import lombok.extern.log4j.Log4j2; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; +import org.folio.consortia.client.PoliciesClient; +import org.folio.consortia.domain.dto.PublicationRequest; import org.folio.consortia.domain.dto.SharingPolicyDeleteResponse; import org.folio.consortia.domain.dto.SharingPolicyRequest; import org.folio.consortia.domain.dto.SharingPolicyResponse; @@ -32,15 +36,17 @@ public class SharingPolicyService extends BaseSharingService { + private final PoliciesClient policiesClient; private final SharingPolicyRepository sharingPolicyRepository; public SharingPolicyService(TenantService tenantService, ConsortiumService consortiumService, SystemUserScopedExecutionService systemUserScopedExecutionService, PublicationService publicationService, FolioExecutionContext folioExecutionContext, - ObjectMapper parentObjectMapper, TaskExecutor asyncTaskExecutor, + ObjectMapper parentObjectMapper, TaskExecutor asyncTaskExecutor, PoliciesClient policiesClient, SharingPolicyRepository sharingPolicyRepository) { super(tenantService, consortiumService, systemUserScopedExecutionService, publicationService, folioExecutionContext, parentObjectMapper, asyncTaskExecutor); + this.policiesClient = policiesClient; this.sharingPolicyRepository = sharingPolicyRepository; } @@ -60,12 +66,8 @@ protected String getPayloadId(ObjectNode payload) { } @Override - protected String getUrl(SharingPolicyRequest request, HttpMethod httpMethod) { - String url = request.getUrl(); - if (httpMethod.equals(HttpMethod.PUT) || httpMethod.equals(HttpMethod.DELETE)) { - url += "/" + getConfigId(request); - } - return url; + protected String getSourceValue(SourceValues sourceValue) { + return sourceValue.getPolicyValue(); } @Override @@ -81,6 +83,48 @@ protected void validateSharingConfigRequestOrThrow(UUID policyId, SharingPolicyR } } + /** + * Policy has unique id, so payload should be same for all tenant + */ + @Override + protected boolean shouldCompactRequests() { + return true; + } + + @Override + protected void syncConfigWithTenants(SharingPolicyRequest request) { + String tenantId = folioExecutionContext.getTenantId(); + UUID policyId = request.getPolicyId(); + log.debug("syncConfig:: Trying to syncing sharing policy table with policy table for policy '{}'", policyId); + + if (sharingPolicyRepository.existsByPolicyIdAndTenantId(policyId, tenantId)) { + log.info("syncConfig:: Policy '{}' with tenant '{}' already exists in sharing role table, No need to sync", + policyId, tenantId); + return; + } + syncSharingPolicyWithPolicyInTenant(request, tenantId, policyId); + } + + private void syncSharingPolicyWithPolicyInTenant(SharingPolicyRequest request, String tenantId, UUID policyId) { + systemUserScopedExecutionService.executeSystemUserScoped(tenantId, () -> { + try { + policiesClient.getPolicyById(policyId); + log.info("syncConfig:: Policy '{}' found in tenant '{}', but not found in sharing policy table, " + + "creating new entry", policyId, tenantId); + + var sharingPolicyEntity = createSharingConfigEntity(request.getPolicyId(), tenantId); + sharingPolicyRepository.save(sharingPolicyEntity); + } catch (FeignException.NotFound e) { + log.info("syncConfig:: Policy '{}' not found in tenant '{}' and sharing policy table, No need to sync", + policyId, tenantId); + } catch (Exception e) { + log.error("syncConfig:: Error while fetching policies", e); + throw new IllegalStateException("Error while fetching policies", e); + } + return null; + }); + } + @Override protected Set findTenantsForConfig(SharingPolicyRequest request) { return sharingPolicyRepository.findTenantsByPolicyId(request.getPolicyId()); @@ -92,40 +136,65 @@ protected void saveSharingConfig(List sharingPolicyEntityLi } @Override - protected void deleteSharingConfig(UUID policyId) { - sharingPolicyRepository.deleteByPolicyId(policyId); + protected void deleteSharingConfig(SharingPolicyRequest request) { + sharingPolicyRepository.deleteByPolicyId(request.getPolicyId()); + } + + @Override + protected PublicationRequest buildPublicationRequestForTenant(SharingPolicyRequest request, String tenantId, HttpMethod method) { + String urlForRequest = getUrl(request, method); + return new PublicationRequest() + .method(method.toString()) + .url(urlForRequest) + .payload(getPayload(request)) + .tenants(Set.of(tenantId)); + } + + private String getUrl(SharingPolicyRequest request, HttpMethod httpMethod) { + String url = request.getUrl(); + if (httpMethod.equals(HttpMethod.PUT) || httpMethod.equals(HttpMethod.DELETE)) { + url += "/" + getConfigId(request); + } + return url; } @Override protected SharingPolicyEntity createSharingConfigEntityFromRequest(SharingPolicyRequest request, String tenantId) { + return createSharingConfigEntity(request.getPolicyId(), tenantId); + } + + private SharingPolicyEntity createSharingConfigEntity(UUID policyId, String tenantId) { return SharingPolicyEntity.builder() .id(UUID.randomUUID()) - .policyId(request.getPolicyId()) + .policyId(policyId) .tenantId(tenantId) .build(); } @Override - protected SharingPolicyResponse createSharingConfigResponse(UUID createSettingsPcId, UUID updateSettingsPcId) { - return new SharingPolicyResponse() - .createPoliciesPCId(createSettingsPcId) - .updatePoliciesPCId(updateSettingsPcId); - } - - @Override - protected SharingPolicyDeleteResponse createSharingConfigResponse(UUID publishRequestId) { - return new SharingPolicyDeleteResponse() - .pcId(publishRequestId); + protected SharingPolicyResponse createSharingConfigResponse(List createPcIds, List updatePcIds) { + var response = new SharingPolicyResponse(); + if (CollectionUtils.isNotEmpty(createPcIds)) { + response.setCreatePCId(createPcIds.get(0)); + } + if (CollectionUtils.isNotEmpty(updatePcIds)) { + response.setUpdatePCId(updatePcIds.get(0)); + } + return response; } @Override - protected ObjectNode updatePayload(SharingPolicyRequest sharingConfigRequest, String sourceValue) { - var payload = objectMapper.convertValue(getPayload(sharingConfigRequest), ObjectNode.class); - return payload.set(SOURCE, new TextNode(sourceValue)); + protected SharingPolicyDeleteResponse createSharingConfigDeleteResponse(List pcIds) { + var response = new SharingPolicyDeleteResponse(); + if (CollectionUtils.isNotEmpty(pcIds)) { + response.setPcId(pcIds.get(0)); + } + return response; } @Override - protected String getSourceValue(SourceValues sourceValue) { - return sourceValue.getPolicyValue(); + protected ObjectNode updateSourcePayload(Object payload, String sourceValue) { + var payloadNode = objectMapper.convertValue(payload, ObjectNode.class); + return payloadNode.set(SOURCE, new TextNode(sourceValue)); } } diff --git a/src/main/java/org/folio/consortia/service/impl/SharingRoleCapabilityService.java b/src/main/java/org/folio/consortia/service/impl/SharingRoleCapabilityService.java index 7e34751f..8bbd2ca3 100644 --- a/src/main/java/org/folio/consortia/service/impl/SharingRoleCapabilityService.java +++ b/src/main/java/org/folio/consortia/service/impl/SharingRoleCapabilityService.java @@ -1,13 +1,22 @@ package org.folio.consortia.service.impl; + +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; + import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.ObjectUtils; +import org.folio.consortia.domain.dto.PublicationRequest; import org.folio.consortia.domain.dto.SharingRoleCapabilityDeleteResponse; import org.folio.consortia.domain.dto.SharingRoleCapabilityRequest; import org.folio.consortia.domain.dto.SharingRoleCapabilityResponse; +import org.folio.consortia.domain.dto.SharingRoleRequest; import org.folio.consortia.domain.dto.SourceValues; import org.folio.consortia.domain.entity.SharingRoleEntity; import org.folio.consortia.exception.ResourceNotFoundException; @@ -22,11 +31,6 @@ import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; - @Service @Log4j2 public class SharingRoleCapabilityService extends BaseSharingService findTenantsForConfig(SharingRoleCapabilityRequest request) { - return sharingRoleRepository.findTenantsByRoleIdAndIsCapabilitiesSharedTrue(request.getRoleId()); + return sharingRoleRepository.findTenantsByRoleNameAndIsCapabilitiesSharedTrue(request.getRoleName()); } @Override @@ -97,40 +116,58 @@ protected void saveSharingConfig(List sharingRoleEntityList) } @Override - protected void deleteSharingConfig(UUID roleId) { - var sharingRoleEntityList = sharingRoleRepository.findByRoleId(roleId); + protected void deleteSharingConfig(SharingRoleCapabilityRequest request) { + var sharingRoleEntityList = sharingRoleRepository.findByRoleName(request.getRoleName()); sharingRoleEntityList.forEach(sharingRoleEntity -> sharingRoleEntity.setIsCapabilitiesShared(false)); sharingRoleRepository.saveAll(sharingRoleEntityList); } + @Override + protected PublicationRequest buildPublicationRequestForTenant(SharingRoleCapabilityRequest request, + String tenantId, HttpMethod method) { + var payload = objectMapper.convertValue(getPayload(request), ObjectNode.class); + String url = request.getUrl(); + var tenantRoleId = sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), tenantId); + payload.put(ROLE_ID, tenantRoleId.toString()); + if (method.equals(HttpMethod.PUT) || method.equals(HttpMethod.DELETE)) { + url = url.replace("capabilities", tenantRoleId + "/capabilities"); + } + log.info("buildPublicationRequestForTenant:: roleId '{}' and url '{}' was set to tenant '{}'", tenantRoleId, url, tenantId); + return new PublicationRequest() + .method(method.toString()) + .url(url) + .payload(payload) + .tenants(Set.of(tenantId)); + } + @Override protected SharingRoleEntity createSharingConfigEntityFromRequest(SharingRoleCapabilityRequest request, String tenantId) { - return sharingRoleRepository.findByRoleIdAndTenantId(request.getRoleId(), tenantId); + return getSharingRoleEntity(request.getRoleName(), tenantId); } - @Override - protected SharingRoleCapabilityResponse createSharingConfigResponse(UUID createRoleCapabilitiesPCId, - UUID updateRoleCapabilitiesPCId) { - return new SharingRoleCapabilityResponse() - .createRoleCapabilitiesPCId(createRoleCapabilitiesPCId) - .updateRoleCapabilitiesPCId(updateRoleCapabilitiesPCId); + private SharingRoleEntity getSharingRoleEntity(String roleName, String tenantId) { + return sharingRoleRepository.findByRoleNameAndTenantId(roleName, tenantId) + .orElseThrow(() -> new ResourceNotFoundException("sharing role, tenantId", roleName + ", " + tenantId)); } @Override - protected SharingRoleCapabilityDeleteResponse createSharingConfigResponse(UUID publishRequestId) { - return new SharingRoleCapabilityDeleteResponse() - .pcId(publishRequestId); + protected SharingRoleCapabilityResponse createSharingConfigResponse(List createPCIds, + List updatePCIds) { + return new SharingRoleCapabilityResponse() + .createPCIds(createPCIds) + .updatePCIds(updatePCIds); } @Override - protected ObjectNode updatePayload(SharingRoleCapabilityRequest request, String sourceValue) { - var payload = objectMapper.convertValue(getPayload(request), ObjectNode.class); - return payload.set(TYPE, new TextNode(sourceValue)); + protected SharingRoleCapabilityDeleteResponse createSharingConfigDeleteResponse(List publishRequestId) { + return new SharingRoleCapabilityDeleteResponse() + .pcIds(publishRequestId); } @Override - protected String getSourceValue(SourceValues sourceValue) { - return sourceValue.getRoleValue(); + protected ObjectNode updateSourcePayload(Object payload, String sourceValue) { + var node = objectMapper.convertValue(payload, ObjectNode.class); + return node.set(TYPE, new TextNode(sourceValue)); } } diff --git a/src/main/java/org/folio/consortia/service/impl/SharingRoleCapabilitySetService.java b/src/main/java/org/folio/consortia/service/impl/SharingRoleCapabilitySetService.java index 690735d2..86e80477 100644 --- a/src/main/java/org/folio/consortia/service/impl/SharingRoleCapabilitySetService.java +++ b/src/main/java/org/folio/consortia/service/impl/SharingRoleCapabilitySetService.java @@ -1,13 +1,21 @@ package org.folio.consortia.service.impl; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; + import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.ObjectUtils; +import org.folio.consortia.domain.dto.PublicationRequest; import org.folio.consortia.domain.dto.SharingRoleCapabilitySetDeleteResponse; import org.folio.consortia.domain.dto.SharingRoleCapabilitySetRequest; import org.folio.consortia.domain.dto.SharingRoleCapabilitySetResponse; +import org.folio.consortia.domain.dto.SharingRoleRequest; import org.folio.consortia.domain.dto.SourceValues; import org.folio.consortia.domain.entity.SharingRoleEntity; import org.folio.consortia.exception.ResourceNotFoundException; @@ -22,11 +30,6 @@ import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; - @Service @Log4j2 public class SharingRoleCapabilitySetService extends BaseSharingService findTenantsForConfig(SharingRoleCapabilitySetRequest request) { - return sharingRoleRepository.findTenantsByRoleIdAndIsCapabilitySetsSharedTrue(request.getRoleId()); + return sharingRoleRepository.findTenantsByRoleNameAndIsCapabilitySetsSharedTrue(request.getRoleName()); } @Override @@ -97,40 +115,58 @@ protected void saveSharingConfig(List sharingRoleEntityList) } @Override - protected void deleteSharingConfig(UUID roleId) { - var sharingRoleEntityList = sharingRoleRepository.findByRoleId(roleId); + protected void deleteSharingConfig(SharingRoleCapabilitySetRequest request) { + var sharingRoleEntityList = sharingRoleRepository.findByRoleName(request.getRoleName()); sharingRoleEntityList.forEach(sharingRoleEntity -> sharingRoleEntity.setIsCapabilitySetsShared(false)); sharingRoleRepository.saveAll(sharingRoleEntityList); } + @Override + protected PublicationRequest buildPublicationRequestForTenant(SharingRoleCapabilitySetRequest request, String tenantId, + HttpMethod method) { + var payload = objectMapper.convertValue(getPayload(request), ObjectNode.class); + String url = request.getUrl(); + var tenantRoleId = sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), tenantId); + payload.put(ROLE_ID, tenantRoleId.toString()); + if (method.equals(HttpMethod.PUT) || method.equals(HttpMethod.DELETE)) { + url = url.replace("capability-sets", tenantRoleId + "/capability-sets"); + } + log.info("buildPublicationRequestForTenant:: roleId '{}' and url '{}' was set to tenant '{}'", tenantRoleId, url, tenantId); + return new PublicationRequest() + .method(method.toString()) + .url(url) + .payload(payload) + .tenants(Set.of(tenantId)); + } + @Override protected SharingRoleEntity createSharingConfigEntityFromRequest(SharingRoleCapabilitySetRequest request, String tenantId) { - return sharingRoleRepository.findByRoleIdAndTenantId(request.getRoleId(), tenantId); + return getSharingRoleEntity(request.getRoleName(), tenantId); } - @Override - protected SharingRoleCapabilitySetResponse createSharingConfigResponse(UUID createRoleCapabilitySetsPCId, - UUID updateRoleCapabilitySetsPCId) { - return new SharingRoleCapabilitySetResponse() - .createRoleCapabilitySetsPCId(createRoleCapabilitySetsPCId) - .updateRoleCapabilitySetsPCId(updateRoleCapabilitySetsPCId); + private SharingRoleEntity getSharingRoleEntity(String roleName, String tenantId) { + return sharingRoleRepository.findByRoleNameAndTenantId(roleName, tenantId) + .orElseThrow(() -> new ResourceNotFoundException("sharing role, tenantId", roleName + ", " + tenantId)); } @Override - protected SharingRoleCapabilitySetDeleteResponse createSharingConfigResponse(UUID publishRequestId) { - return new SharingRoleCapabilitySetDeleteResponse() - .pcId(publishRequestId); + protected SharingRoleCapabilitySetResponse createSharingConfigResponse(List createPCIds, + List updateIds) { + return new SharingRoleCapabilitySetResponse() + .createPCIds(createPCIds) + .updatePCIds(updateIds); } @Override - protected ObjectNode updatePayload(SharingRoleCapabilitySetRequest request, String sourceValue) { - var payload = objectMapper.convertValue(getPayload(request), ObjectNode.class); - return payload.set(TYPE, new TextNode(sourceValue)); + protected SharingRoleCapabilitySetDeleteResponse createSharingConfigDeleteResponse(List publishRequestIds) { + return new SharingRoleCapabilitySetDeleteResponse() + .pcIds(publishRequestIds); } @Override - protected String getSourceValue(SourceValues sourceValue) { - return sourceValue.getRoleValue(); + protected ObjectNode updateSourcePayload(Object payload, String sourceValue) { + var node = objectMapper.convertValue(payload, ObjectNode.class); + return node.set(TYPE, new TextNode(sourceValue)); } } diff --git a/src/main/java/org/folio/consortia/service/impl/SharingRoleService.java b/src/main/java/org/folio/consortia/service/impl/SharingRoleService.java index f69d2abe..0b00e715 100644 --- a/src/main/java/org/folio/consortia/service/impl/SharingRoleService.java +++ b/src/main/java/org/folio/consortia/service/impl/SharingRoleService.java @@ -1,10 +1,21 @@ package org.folio.consortia.service.impl; +import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.UUID; + import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; + import lombok.extern.log4j.Log4j2; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; +import org.folio.consortia.client.RoleCapabilitiesClient; +import org.folio.consortia.client.RoleCapabilitySetsClient; +import org.folio.consortia.client.RolesClient; +import org.folio.consortia.domain.dto.PublicationRequest; import org.folio.consortia.domain.dto.SharingRoleDeleteResponse; import org.folio.consortia.domain.dto.SharingRoleRequest; import org.folio.consortia.domain.dto.SharingRoleResponse; @@ -22,23 +33,28 @@ import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.UUID; - @Service @Log4j2 public class SharingRoleService extends BaseSharingService { + private static final String ID = "id"; + private static final String NAME = "name"; + + private final RolesClient rolesClient; + private final RoleCapabilitySetsClient roleCapabilitySetsClient; + private final RoleCapabilitiesClient roleCapabilitiesClient; private final SharingRoleRepository sharingRoleRepository; public SharingRoleService(TenantService tenantService, ConsortiumService consortiumService, SystemUserScopedExecutionService systemUserScopedExecutionService, PublicationService publicationService, FolioExecutionContext folioExecutionContext, - ObjectMapper parentObjectMapper, TaskExecutor asyncTaskExecutor, SharingRoleRepository sharingRoleRepository) { + ObjectMapper parentObjectMapper, TaskExecutor asyncTaskExecutor, RolesClient rolesClient, RoleCapabilitySetsClient roleCapabilitySetsClient, RoleCapabilitiesClient roleCapabilitiesClient, + SharingRoleRepository sharingRoleRepository) { super(tenantService, consortiumService, systemUserScopedExecutionService, publicationService, folioExecutionContext, parentObjectMapper, asyncTaskExecutor); + this.rolesClient = rolesClient; + this.roleCapabilitySetsClient = roleCapabilitySetsClient; + this.roleCapabilitiesClient = roleCapabilitiesClient; this.sharingRoleRepository = sharingRoleRepository; } @@ -54,16 +70,21 @@ protected Object getPayload(SharingRoleRequest request) { @Override protected String getPayloadId(ObjectNode payload) { - return payload.get("id").asText(); + return payload.get(ID).asText(); } @Override - protected String getUrl(SharingRoleRequest request, HttpMethod httpMethod) { - String url = request.getUrl(); - if (httpMethod.equals(HttpMethod.PUT) || httpMethod.equals(HttpMethod.DELETE)) { - url += "/" + getConfigId(request); - } - return url; + protected String getSourceValue(SourceValues sourceValue) { + return sourceValue.getRoleValue(); + } + + /** + * RoleId is generated by keycloak, so payloads are different for each tenant, + * that is why requests must not be compacted + */ + @Override + protected boolean shouldCompactRequests() { + return false; } @Override @@ -81,7 +102,105 @@ protected void validateSharingConfigRequestOrThrow(UUID roleId, SharingRoleReque @Override protected Set findTenantsForConfig(SharingRoleRequest request) { - return sharingRoleRepository.findTenantsByRoleId(request.getRoleId()); + return sharingRoleRepository.findTenantsByRoleName(request.getRoleName()); + } + + @Override + protected void syncConfigWithTenants(SharingRoleRequest request) { + String centralTenantId = folioExecutionContext.getTenantId(); + syncSharingRoleWithTenant(request, centralTenantId); + updateRoleNamesIfNeed(request, centralTenantId); + } + + protected void syncSharingRoleWithTenant(SharingRoleRequest request, String centralTenantId) { + String roleName = request.getRoleName(); + log.debug("syncConfig:: Trying to syncing sharing role table with roles table for role '{}' and tenant '{}'", + request.getRoleName(), centralTenantId); + + if (sharingRoleRepository.existsByRoleIdAndTenantId(request.getRoleId(), centralTenantId)) { + log.info("syncConfig:: Role '{}' with central tenant '{}' already sync, Syncing with other tenants", + request.getRoleName(), centralTenantId); + + findTenantsForConfig(request).stream() + .filter(tenantId -> !tenantId.equals(centralTenantId)) + .forEach(memberTenantId -> syncSharingRoleWithTenant(request.getRoleName(), memberTenantId)); + return; + } + + log.info("syncConfig:: Role '{}' not found, trying to sync with only central tenant '{}'" + + " because role haven't shared with other tenants yet", request.getRoleId(), centralTenantId); + syncSharingRoleWithTenant(roleName, centralTenantId); + } + + private void syncSharingRoleWithTenant(String roleName, String tenantId) { + systemUserScopedExecutionService.executeSystemUserScoped(tenantId, () -> { + try { + String cqlQuery = String.format("name==%s", roleName); + var roles = rolesClient.getRolesByQuery(cqlQuery); + var roleList = roles.getRoles(); + if (CollectionUtils.isEmpty(roleList)) { + log.info("syncSharingRoleWithTenant:: Role '{}' not found in tenant '{}' and sharing role table, No need to sync", + roleName, tenantId); + return null; + } + + var roleIdForTenant = roleList.get(0).getId(); + log.info("syncSharingRoleWithTenant:: Role '{}' is found in tenant '{}', Syncing table", roleIdForTenant, tenantId); + var sharingRoleEntity = getOrCreateSharingConfigEntity(roleIdForTenant, roleName, tenantId); + sharingRoleEntity.setRoleId(roleIdForTenant); + + var capabilities = roleCapabilitiesClient.getRoleCapabilitiesByRoleId(roleIdForTenant); + if (CollectionUtils.isNotEmpty(capabilities.getCapabilities())) { + log.info("syncSharingRoleWithTenant:: capabilities found for role '{}' in tenant '{}'", roleIdForTenant, tenantId); + sharingRoleEntity.setIsCapabilitiesShared(true); + } + + var capabilitySets = roleCapabilitySetsClient.getRoleCapabilitySetsRoleId(roleIdForTenant); + if (CollectionUtils.isNotEmpty(capabilitySets.getCapabilitySets())) { + log.info("syncSharingRoleWithTenant:: capabilitySets found for role '{}' found in tenant '{}'", roleIdForTenant, tenantId); + sharingRoleEntity.setIsCapabilitySetsShared(true); + } + + sharingRoleRepository.save(sharingRoleEntity); + } catch (Exception e) { + log.error("syncSharingRoleWithTenant:: Error while fetching roles", e); + throw new IllegalStateException("Error while fetching roles", e); + } + return null; + }); + } + + private SharingRoleEntity getOrCreateSharingConfigEntity(UUID roleId, String roleName, String tenantId) { + var entity = sharingRoleRepository.findByRoleNameAndTenantId(roleName, tenantId); + return entity.orElseGet(() -> createSharingConfigEntity(roleId, roleName, tenantId)); + } + + private void updateRoleNamesIfNeed(SharingRoleRequest request, String centralTenantId) { + checkEqualsOfRoleNameWithPayload(request); + var existingSharingRole = sharingRoleRepository.findByRoleIdAndTenantId(request.getRoleId(), centralTenantId); + existingSharingRole.ifPresent(role -> { + if (ObjectUtils.notEqual(existingSharingRole.get().getRoleName(), request.getRoleName())) { + updateSharingRoleNameForAllTenants(existingSharingRole.get(), request.getRoleName()); + } + }); + } + + private void checkEqualsOfRoleNameWithPayload(SharingRoleRequest request) { + String roleName = request.getRoleName(); + var payloadNode = objectMapper.convertValue(request.getPayload(), ObjectNode.class); + String payloadRoleName = payloadNode.get(NAME).asText(); + if (ObjectUtils.notEqual(roleName, payloadRoleName)) { + throw new IllegalArgumentException("Mismatch name in payload with roleName"); + } + } + + private void updateSharingRoleNameForAllTenants(SharingRoleEntity sharingRole, String newRoleName) { + String oldRolName = sharingRole.getRoleName(); + log.info("updateSharingRoleNameForAllTenants:: shared role name '{}' is different request, updating to new roleName '{}'", + oldRolName, newRoleName); + var sharingRoles = sharingRoleRepository.findByRoleName(oldRolName); + sharingRoles.forEach(role -> role.setRoleName(newRoleName)); + saveSharingConfig(sharingRoles); } @Override @@ -90,15 +209,38 @@ protected void saveSharingConfig(List sharingRoleEntityList) } @Override - protected void deleteSharingConfig(UUID roleId) { - sharingRoleRepository.deleteByRoleId(roleId); + protected void deleteSharingConfig(SharingRoleRequest request) { + sharingRoleRepository.deleteByRoleName(request.getRoleName()); + } + + @Override + protected PublicationRequest buildPublicationRequestForTenant(SharingRoleRequest request, String tenantId, + HttpMethod method) { + var payload = objectMapper.convertValue(getPayload(request), ObjectNode.class); + String url = request.getUrl(); + if (method.equals(HttpMethod.PUT) || method.equals(HttpMethod.DELETE)) { + var tenantRoleId = sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), tenantId); + url += "/" + tenantRoleId; + payload.put(ID, tenantRoleId.toString()); + log.info("buildPublicationRequestForTenant:: roleId '{}' was set to tenant '{}'", tenantRoleId, tenantId); + } + return new PublicationRequest() + .method(method.toString()) + .url(url) + .payload(payload) + .tenants(Set.of(tenantId)); } @Override protected SharingRoleEntity createSharingConfigEntityFromRequest(SharingRoleRequest request, String tenantId) { + return createSharingConfigEntity(request.getRoleId(), request.getRoleName(), tenantId); + } + + private SharingRoleEntity createSharingConfigEntity(UUID roleId, String roleName, String tenantId) { return SharingRoleEntity.builder() .id(UUID.randomUUID()) - .roleId(request.getRoleId()) + .roleId(roleId) + .roleName(roleName) .tenantId(tenantId) .isCapabilitiesShared(false) .isCapabilitySetsShared(false) @@ -106,26 +248,21 @@ protected SharingRoleEntity createSharingConfigEntityFromRequest(SharingRoleRequ } @Override - protected SharingRoleResponse createSharingConfigResponse(UUID createRolesPcId, UUID updateRolesPcId) { + protected SharingRoleResponse createSharingConfigResponse(List createPcIds, List updatePcIds) { return new SharingRoleResponse() - .createRolesPCId(createRolesPcId) - .updateRolesPCId(updateRolesPcId); + .createPCIds(createPcIds) + .updatePCIds(updatePcIds); } @Override - protected SharingRoleDeleteResponse createSharingConfigResponse(UUID publishRequestId) { + protected SharingRoleDeleteResponse createSharingConfigDeleteResponse(List publishRequestIds) { return new SharingRoleDeleteResponse() - .pcId(publishRequestId); + .pcIds(publishRequestIds); } @Override - protected ObjectNode updatePayload(SharingRoleRequest request, String sourceValue) { - var payload = objectMapper.convertValue(getPayload(request), ObjectNode.class); - return payload.set(TYPE, new TextNode(sourceValue)); - } - - @Override - protected String getSourceValue(SourceValues sourceValue) { - return sourceValue.getRoleValue(); + protected ObjectNode updateSourcePayload(Object payload, String sourceValue) { + var payloadNode = objectMapper.convertValue(payload, ObjectNode.class); + return payloadNode.set(TYPE, new TextNode(sourceValue)); } } diff --git a/src/main/java/org/folio/consortia/service/impl/SharingSettingService.java b/src/main/java/org/folio/consortia/service/impl/SharingSettingService.java index 1ee046f3..edbd0b0c 100644 --- a/src/main/java/org/folio/consortia/service/impl/SharingSettingService.java +++ b/src/main/java/org/folio/consortia/service/impl/SharingSettingService.java @@ -4,7 +4,9 @@ import com.fasterxml.jackson.databind.node.ObjectNode; import com.fasterxml.jackson.databind.node.TextNode; import lombok.extern.log4j.Log4j2; +import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang3.ObjectUtils; +import org.folio.consortia.domain.dto.PublicationRequest; import org.folio.consortia.domain.dto.SharingSettingDeleteResponse; import org.folio.consortia.domain.dto.SharingSettingRequest; import org.folio.consortia.domain.dto.SharingSettingResponse; @@ -57,15 +59,6 @@ protected String getPayloadId(ObjectNode payload) { return payload.get("id").asText(); } - @Override - protected String getUrl(SharingSettingRequest request, HttpMethod httpMethod) { - String url = request.getUrl(); - if (httpMethod.equals(HttpMethod.PUT) || httpMethod.equals(HttpMethod.DELETE)) { - url += "/" + getConfigId(request); - } - return url; - } - @Override protected void validateSharingConfigRequestOrThrow(UUID settingId, SharingSettingRequest request) { if (ObjectUtils.notEqual(getConfigId(request), settingId)) { @@ -79,6 +72,14 @@ protected void validateSharingConfigRequestOrThrow(UUID settingId, SharingSettin } } + /** + * Sharing settings are one share-to-all tenants action only, so don't need to sync with tenant + */ + @Override + protected void syncConfigWithTenants(SharingSettingRequest request) { + log.info("syncConfigWithTenant:: No need to sync with tenant for Sharing Setting"); + } + @Override protected Set findTenantsForConfig(SharingSettingRequest request) { return sharingSettingRepository.findTenantsBySettingId(request.getSettingId()); @@ -90,8 +91,34 @@ protected void saveSharingConfig(List sharingSettingEntity } @Override - protected void deleteSharingConfig(UUID settingId) { - sharingSettingRepository.deleteBySettingId(settingId); + protected void deleteSharingConfig(SharingSettingRequest request) { + sharingSettingRepository.deleteBySettingId(request.getSettingId()); + } + + @Override + protected PublicationRequest buildPublicationRequestForTenant(SharingSettingRequest request, String tenantId, HttpMethod method) { + String urlForRequest = getUrl(request, method); + return new PublicationRequest() + .method(method.toString()) + .url(urlForRequest) + .payload(getPayload(request)) + .tenants(Set.of(tenantId)); + } + + private String getUrl(SharingSettingRequest request, HttpMethod httpMethod) { + String url = request.getUrl(); + if (httpMethod.equals(HttpMethod.PUT) || httpMethod.equals(HttpMethod.DELETE)) { + url += "/" + getConfigId(request); + } + return url; + } + + /** + * Setting has unique id, so payload should be same for all tenant + */ + @Override + protected boolean shouldCompactRequests() { + return true; } @Override @@ -104,26 +131,35 @@ protected SharingSettingEntity createSharingConfigEntityFromRequest(SharingSetti } @Override - protected SharingSettingResponse createSharingConfigResponse(UUID createSettingsPcId, UUID updateSettingsPcId) { - return new SharingSettingResponse() - .createSettingsPCId(createSettingsPcId) - .updateSettingsPCId(updateSettingsPcId); + protected SharingSettingResponse createSharingConfigResponse(List createSettingsPcId, + List updateSettingsPcId) { + var response = new SharingSettingResponse(); + if (CollectionUtils.isNotEmpty(createSettingsPcId)) { + response.setCreateSettingsPCId(createSettingsPcId.get(0)); + } + if (CollectionUtils.isNotEmpty(updateSettingsPcId)) { + response.setUpdateSettingsPCId(updateSettingsPcId.get(0)); + } + return response; } @Override - protected SharingSettingDeleteResponse createSharingConfigResponse(UUID publishRequestId) { - return new SharingSettingDeleteResponse() - .pcId(publishRequestId); + protected SharingSettingDeleteResponse createSharingConfigDeleteResponse(List publishRequestIds) { + var deleteResponse = new SharingSettingDeleteResponse(); + if (CollectionUtils.isNotEmpty(publishRequestIds)) { + deleteResponse.setPcId(publishRequestIds.get(0)); + } + return deleteResponse; } @Override - protected ObjectNode updatePayload(SharingSettingRequest request, String sourceValue) { - var payload = objectMapper.convertValue(getPayload(request), ObjectNode.class); - return payload.set(SOURCE, new TextNode(sourceValue)); + protected String getSourceValue(SourceValues sourceValue) { + return sourceValue.getSettingValue(); } @Override - protected String getSourceValue(SourceValues sourceValue) { - return sourceValue.getSettingValue(); + protected ObjectNode updateSourcePayload(Object payload, String sourceValue) { + var node = objectMapper.convertValue(payload, ObjectNode.class); + return node.set(SOURCE, new TextNode(sourceValue)); } } diff --git a/src/main/resources/db/changelog/changes/create-sharing-role-table.xml b/src/main/resources/db/changelog/changes/create-sharing-role-table.xml index d6adfb22..f0c504bc 100644 --- a/src/main/resources/db/changelog/changes/create-sharing-role-table.xml +++ b/src/main/resources/db/changelog/changes/create-sharing-role-table.xml @@ -34,4 +34,14 @@ + + + + + + + + + + diff --git a/src/main/resources/swagger.api/consortia.yaml b/src/main/resources/swagger.api/consortia.yaml index 82af4785..ae11096c 100644 --- a/src/main/resources/swagger.api/consortia.yaml +++ b/src/main/resources/swagger.api/consortia.yaml @@ -131,3 +131,7 @@ components: $ref: schemas/capability/user/userCapabilitySetsRequest.json capability-sets: $ref: schemas/capability/capabilitySets.json + capabilities: + $ref: schemas/capability/capabilities.json + roles: + $ref: schemas/role/roles.json diff --git a/src/main/resources/swagger.api/examples/requests/sharing_policy_request_for_roles.json b/src/main/resources/swagger.api/examples/requests/sharing_policy_request_for_roles.json new file mode 100644 index 00000000..83278433 --- /dev/null +++ b/src/main/resources/swagger.api/examples/requests/sharing_policy_request_for_roles.json @@ -0,0 +1,9 @@ +{ + "policyId": "2844767a-8367-4926-9999-514c35840399", + "url": "/policy", + "payload": { + "id": "2844767a-8367-4926-9999-514c35840399", + "name": "Policy for role: 004d7a66-c51d-402a-9c9f-3bdcdbbcdbe7", + "source": "local" + } +} diff --git a/src/main/resources/swagger.api/examples/requests/sharing_role_capabilities_request.json b/src/main/resources/swagger.api/examples/requests/sharing_role_capabilities_request.json new file mode 100644 index 00000000..9ec0d8f6 --- /dev/null +++ b/src/main/resources/swagger.api/examples/requests/sharing_role_capabilities_request.json @@ -0,0 +1,13 @@ +{ + "roleId": "5844767a-8367-4926-9999-514c35840399", + "roleName": "don't panic", + "url": "/roles/capabilities", + "payload": { + "roleId": "5844767a-8367-4926-9999-514c35840399", + "capabilityNames": [ + "account_item.view", + "account_item.create" + ], + "type": "local" + } +} diff --git a/src/main/resources/swagger.api/examples/requests/sharing_role_capability_sets_request.json b/src/main/resources/swagger.api/examples/requests/sharing_role_capability_sets_request.json new file mode 100644 index 00000000..e2ef5a4f --- /dev/null +++ b/src/main/resources/swagger.api/examples/requests/sharing_role_capability_sets_request.json @@ -0,0 +1,13 @@ +{ + "roleId": "4844767a-8367-4926-9999-514c35840399", + "roleName": "test", + "url": "/roles/capability-sets", + "payload": { + "roleId": "4844767a-8367-4926-9999-514c35840399", + "capabilitySetNames": [ + "account_item.view", + "account_item.create" + ], + "type": "local" + } +} diff --git a/src/main/resources/swagger.api/examples/requests/sharing_role_request.json b/src/main/resources/swagger.api/examples/requests/sharing_role_request.json new file mode 100644 index 00000000..e58f6a94 --- /dev/null +++ b/src/main/resources/swagger.api/examples/requests/sharing_role_request.json @@ -0,0 +1,10 @@ +{ + "roleId": "3844767a-8367-4926-9999-514c35840399", + "roleName": "role name", + "url": "/roles", + "payload": { + "id": "3844767a-8367-4926-9999-514c35840399", + "name": "role name", + "type": "local" + } +} diff --git a/src/main/resources/swagger.api/examples/requests/sharing_setting_request_for_department.json b/src/main/resources/swagger.api/examples/requests/sharing_setting_request_for_department.json new file mode 100644 index 00000000..b2e16587 --- /dev/null +++ b/src/main/resources/swagger.api/examples/requests/sharing_setting_request_for_department.json @@ -0,0 +1,9 @@ +{ + "settingId": "1844767a-8367-4926-9999-514c35840399", + "url": "/organizations-storage/organizations", + "payload": { + "id": "1844767a-8367-4926-9999-514c35840399", + "name": "ORG-NAME", + "source": "local" + } +} diff --git a/src/main/resources/swagger.api/examples/error.sample b/src/main/resources/swagger.api/examples/responses/error.sample similarity index 100% rename from src/main/resources/swagger.api/examples/error.sample rename to src/main/resources/swagger.api/examples/responses/error.sample diff --git a/src/main/resources/swagger.api/examples/errors.sample b/src/main/resources/swagger.api/examples/responses/errors.sample similarity index 100% rename from src/main/resources/swagger.api/examples/errors.sample rename to src/main/resources/swagger.api/examples/responses/errors.sample diff --git a/src/main/resources/swagger.api/examples/responses/sharing_policy_delete_response.json b/src/main/resources/swagger.api/examples/responses/sharing_policy_delete_response.json new file mode 100644 index 00000000..6113f1f9 --- /dev/null +++ b/src/main/resources/swagger.api/examples/responses/sharing_policy_delete_response.json @@ -0,0 +1,3 @@ +{ + "pcId": "c734a41e-16ba-4a02-beb0-2d45081e39b1" +} diff --git a/src/main/resources/swagger.api/examples/responses/sharing_policy_response.json b/src/main/resources/swagger.api/examples/responses/sharing_policy_response.json new file mode 100644 index 00000000..d194543d --- /dev/null +++ b/src/main/resources/swagger.api/examples/responses/sharing_policy_response.json @@ -0,0 +1,4 @@ +{ + "createPCId": "c734a41e-16ba-4a02-beb0-2d45081e39b1", + "updatePCId": "53e0f091-ffee-448c-a0f8-562d9ad6bf3f" +} diff --git a/src/main/resources/swagger.api/examples/responses/sharing_role_delete_response.json b/src/main/resources/swagger.api/examples/responses/sharing_role_delete_response.json new file mode 100644 index 00000000..72e0e9cf --- /dev/null +++ b/src/main/resources/swagger.api/examples/responses/sharing_role_delete_response.json @@ -0,0 +1,6 @@ +{ + "pcIds": [ + "44a7e57b-c535-4ad1-bdb4-099d48f3fd37", + "cf8fc598-fa4f-4a7d-9d1a-fdd3fac3cbd4" + ] +} diff --git a/src/main/resources/swagger.api/examples/responses/sharing_role_response.json b/src/main/resources/swagger.api/examples/responses/sharing_role_response.json new file mode 100644 index 00000000..e1644d48 --- /dev/null +++ b/src/main/resources/swagger.api/examples/responses/sharing_role_response.json @@ -0,0 +1,9 @@ +{ + "createPCIds": [ + "44a7e57b-c535-4ad1-bdb4-099d48f3fd37", + "cf8fc598-fa4f-4a7d-9d1a-fdd3fac3cbd4" + ], + "updatePCIds": [ + "f3b1b1b4-4b1b-4b1b-4b1b-4b1b4b1b4b1b" + ] +} diff --git a/src/main/resources/swagger.api/examples/responses/sharing_setting_delete_response.json b/src/main/resources/swagger.api/examples/responses/sharing_setting_delete_response.json new file mode 100644 index 00000000..6113f1f9 --- /dev/null +++ b/src/main/resources/swagger.api/examples/responses/sharing_setting_delete_response.json @@ -0,0 +1,3 @@ +{ + "pcId": "c734a41e-16ba-4a02-beb0-2d45081e39b1" +} diff --git a/src/main/resources/swagger.api/examples/responses/sharing_setting_response.json b/src/main/resources/swagger.api/examples/responses/sharing_setting_response.json new file mode 100644 index 00000000..67d6d6ec --- /dev/null +++ b/src/main/resources/swagger.api/examples/responses/sharing_setting_response.json @@ -0,0 +1,4 @@ +{ + "createSettingsPCId": "c734a41e-16ba-4a02-beb0-2d45081e39b1", + "updateSettingsPCId": "53e0f091-ffee-448c-a0f8-562d9ad6bf3f" +} diff --git a/src/main/resources/swagger.api/schemas/role/role.json b/src/main/resources/swagger.api/schemas/role/role.json new file mode 100644 index 00000000..d7bb6c89 --- /dev/null +++ b/src/main/resources/swagger.api/schemas/role/role.json @@ -0,0 +1,20 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Role schema", + "description": "Role", + "type": "object", + "properties": { + "id": { + "description": "Role identifier", + "type": "string", + "format": "uuid" + }, + "name": { + "description": "A human-readable name/label for this role", + "type": "string" + } + }, + "required": [ + "name" + ] +} diff --git a/src/main/resources/swagger.api/schemas/role/roles.json b/src/main/resources/swagger.api/schemas/role/roles.json new file mode 100644 index 00000000..feef896d --- /dev/null +++ b/src/main/resources/swagger.api/schemas/role/roles.json @@ -0,0 +1,24 @@ +{ + "$schema": "http://json-schema.org/draft-04/schema#", + "id": "roles.json", + "title": "Roles schema", + "description": "Roles", + "type": "object", + "properties": { + "roles": { + "description": "Role identifier", + "type": "array", + "items": { + "$ref": "role.json" + }, + "nullable" : false + }, + "totalRecords": { + "description": "The total number of roles matching the provided criteria", + "type": "integer" + } + }, + "required": [ + "roles" + ] +} diff --git a/src/main/resources/swagger.api/schemas/sharingPolicy.yaml b/src/main/resources/swagger.api/schemas/sharingPolicy.yaml index 7a7abbe1..f05254ad 100644 --- a/src/main/resources/swagger.api/schemas/sharingPolicy.yaml +++ b/src/main/resources/swagger.api/schemas/sharingPolicy.yaml @@ -21,16 +21,16 @@ SharingPolicyResponse: description: "A JSON schema for the Sharing policies object response for post request" type: object properties: - createPoliciesPCId: + createPCId: type: string format: uuid - updatePoliciesPCId: + updatePCId: type: string format: uuid additionalProperties: false required: - - createPoliciesPCId - - updatePoliciesPCId + - createPCId + - updatePCId SharingPolicyDeleteResponse: description: "A JSON schema for the Sharing policies object response for delete request" diff --git a/src/main/resources/swagger.api/schemas/sharingRole.yaml b/src/main/resources/swagger.api/schemas/sharingRole.yaml index 2240c34d..0f2bbcc3 100644 --- a/src/main/resources/swagger.api/schemas/sharingRole.yaml +++ b/src/main/resources/swagger.api/schemas/sharingRole.yaml @@ -6,6 +6,9 @@ SharingRoleRequest: description: id of sharing role record type: string format: uuid + roleName: + description: name of sharing role + type: string url: description: URL for publishing requests for consortia tenants type: string @@ -15,30 +18,37 @@ SharingRoleRequest: additionalProperties: false required: - roleId + - roleName - url SharingRoleResponse: description: "A JSON schema for the Sharing roles object response for post request" type: object properties: - createRolesPCId: - type: string - format: uuid - updateRolesPCId: - type: string - format: uuid + createPCIds: + type: array + items: + type: string + format: uuid + updatePCIds: + type: array + items: + type: string + format: uuid additionalProperties: false required: - - createRolesPCId - - updateRolesPCId + - createPCIds + - updatePCIds SharingRoleDeleteResponse: description: "A JSON schema for the Sharing roles object response for delete request" type: object properties: - pcId: - type: string - format: uuid + pcIds: + type: array + items: + type: string + format: uuid additionalProperties: false required: - pcId diff --git a/src/main/resources/swagger.api/schemas/sharingRoleCapability.yaml b/src/main/resources/swagger.api/schemas/sharingRoleCapability.yaml index 1d114af9..b416ec87 100644 --- a/src/main/resources/swagger.api/schemas/sharingRoleCapability.yaml +++ b/src/main/resources/swagger.api/schemas/sharingRoleCapability.yaml @@ -6,6 +6,9 @@ SharingRoleCapabilityRequest: description: id of sharing role record type: string format: uuid + roleName: + description: name of sharing role + type: string url: description: URL for publishing requests for consortia tenants type: string @@ -15,30 +18,37 @@ SharingRoleCapabilityRequest: additionalProperties: false required: - roleId + - roleName - url SharingRoleCapabilityResponse: description: "A JSON schema for the Sharing Role Capabilities object response for post request" type: object properties: - createRoleCapabilitiesPCId: - type: string - format: uuid - updateRoleCapabilitiesPCId: - type: string - format: uuid + createPCIds: + type: array + items: + type: string + format: uuid + updatePCIds: + type: array + items: + type: string + format: uuid additionalProperties: false required: - - createRoleCapabilitiesPCId - - updateRoleCapabilitiesPCId + - createPCIds + - updatePCIds SharingRoleCapabilityDeleteResponse: description: "A JSON schema for the Sharing Role Capability object response for delete request" type: object properties: - pcId: - type: string - format: uuid + pcIds: + type: array + items: + type: string + format: uuid additionalProperties: false required: - pcId diff --git a/src/main/resources/swagger.api/schemas/sharingRoleCapabilitySet.yaml b/src/main/resources/swagger.api/schemas/sharingRoleCapabilitySet.yaml index 533ff7cd..7e924237 100644 --- a/src/main/resources/swagger.api/schemas/sharingRoleCapabilitySet.yaml +++ b/src/main/resources/swagger.api/schemas/sharingRoleCapabilitySet.yaml @@ -6,6 +6,9 @@ SharingRoleCapabilitySetRequest: description: id of sharing role record type: string format: uuid + roleName: + description: name of sharing role + type: string url: description: URL for publishing requests for consortia tenants type: string @@ -15,30 +18,37 @@ SharingRoleCapabilitySetRequest: additionalProperties: false required: - roleId + - roleName - url SharingRoleCapabilitySetResponse: description: "A JSON schema for the Sharing Role Capability Sets object response for post request" type: object properties: - createRoleCapabilitySetsPCId: - type: string - format: uuid - updateRoleCapabilitySetsPCId: - type: string - format: uuid + createPCIds: + type: array + items: + type: string + format: uuid + updatePCIds: + type: array + items: + type: string + format: uuid additionalProperties: false required: - - createRoleCapabilitySetsPCId - - updateRoleCapabilitySetsPCId + - createPCIds + - updatePCIds SharingRoleCapabilitySetDeleteResponse: description: "A JSON schema for the Sharing Role Capability Sets object response for delete request" type: object properties: - pcId: - type: string - format: uuid + pcIds: + type: array + items: + type: string + format: uuid additionalProperties: false required: - pcId diff --git a/src/main/resources/swagger.api/sharing_policies.yaml b/src/main/resources/swagger.api/sharing_policies.yaml index 1ae1ea47..89d6ff34 100644 --- a/src/main/resources/swagger.api/sharing_policies.yaml +++ b/src/main/resources/swagger.api/sharing_policies.yaml @@ -58,6 +58,8 @@ components: application/json: schema: $ref: "schemas/sharingPolicy.yaml#/SharingPolicyRequest" + example: + $ref: "examples/requests/sharing_policy_request_for_roles.json" responses: SharingPolicyResponse: description: Returns a sharing policy object response for post operation @@ -65,12 +67,16 @@ components: application/json: schema: $ref: "schemas/sharingPolicy.yaml#/SharingPolicyResponse" + example: + $ref: "examples/responses/sharing_policy_response.json" SharingPolicyDeleteResponse: description: Returns a sharing policy response for delete operation content: application/json: schema: $ref: "schemas/sharingPolicy.yaml#/SharingPolicyDeleteResponse" + example: + $ref: "examples/responses/sharing_policy_delete_response.json" NoContent: description: No content Conflict: diff --git a/src/main/resources/swagger.api/sharing_roles.yaml b/src/main/resources/swagger.api/sharing_roles.yaml index 88f7ae26..ced75f29 100644 --- a/src/main/resources/swagger.api/sharing_roles.yaml +++ b/src/main/resources/swagger.api/sharing_roles.yaml @@ -162,6 +162,8 @@ components: application/json: schema: $ref: "schemas/sharingRole.yaml#/SharingRoleRequest" + example: + $ref: "examples/requests/sharing_role_request.json" SharingRoleCapabilitySetBody: description: Sharing role capability sets object required: true @@ -169,6 +171,8 @@ components: application/json: schema: $ref: "schemas/sharingRoleCapabilitySet.yaml#/SharingRoleCapabilitySetRequest" + example: + $ref: "examples/requests/sharing_role_capability_sets_request.json" SharingRoleCapabilityBody: description: Sharing role capabilities object required: true @@ -176,6 +180,8 @@ components: application/json: schema: $ref: "schemas/sharingRoleCapability.yaml#/SharingRoleCapabilityRequest" + example: + $ref: "examples/requests/sharing_role_capabilities_request.json" responses: SharingRoleResponse: description: Returns a sharing role object response for post operation @@ -183,36 +189,48 @@ components: application/json: schema: $ref: "schemas/sharingRole.yaml#/SharingRoleResponse" + example: + $ref: "examples/responses/sharing_role_response.json" SharingRoleCapabilitySetResponse: description: Returns a sharing role capability set object response for post operation content: application/json: schema: $ref: "schemas/sharingRoleCapabilitySet.yaml#/SharingRoleCapabilitySetResponse" + example: + $ref: "examples/responses/sharing_role_response.json" SharingRoleCapabilityResponse: description: Returns a sharing role capability object response for post operation content: application/json: schema: $ref: "schemas/sharingRoleCapability.yaml#/SharingRoleCapabilityResponse" + example: + $ref: "examples/responses/sharing_role_response.json" SharingRoleDeleteResponse: description: Returns a sharing role response for delete operation content: application/json: schema: $ref: "schemas/sharingRole.yaml#/SharingRoleDeleteResponse" + example: + $ref: "examples/responses/sharing_role_delete_response.json" SharingRoleCapabilitySetDeleteResponse: description: Returns a sharing role capability set response for delete operation content: application/json: schema: $ref: "schemas/sharingRoleCapabilitySet.yaml#/SharingRoleCapabilitySetDeleteResponse" + example: + $ref: "examples/responses/sharing_role_delete_response.json" SharingRoleCapabilityDeleteResponse: description: Returns a sharing role capability response for delete operation content: application/json: schema: $ref: "schemas/sharingRoleCapability.yaml#/SharingRoleCapabilityDeleteResponse" + example: + $ref: "examples/responses/sharing_role_delete_response.json" NoContent: description: No content Conflict: diff --git a/src/main/resources/swagger.api/sharing_settings.yaml b/src/main/resources/swagger.api/sharing_settings.yaml index e5dd825e..8cd24c4f 100644 --- a/src/main/resources/swagger.api/sharing_settings.yaml +++ b/src/main/resources/swagger.api/sharing_settings.yaml @@ -58,6 +58,8 @@ components: application/json: schema: $ref: "schemas/sharingSetting.yaml#/SharingSettingRequest" + example: + $ref: "examples/requests/sharing_setting_request_for_department.json" responses: SharingSettingResponse: description: Returns a sharing setting object response for post operation @@ -65,12 +67,16 @@ components: application/json: schema: $ref: "schemas/sharingSetting.yaml#/SharingSettingResponse" + example: + $ref: "examples/responses/sharing_setting_response.json" SharingSettingDeleteResponse: description: Returns a sharing setting response for delete operation content: application/json: schema: $ref: "schemas/sharingSetting.yaml#/SharingSettingDeleteResponse" + example: + $ref: "examples/responses/sharing_setting_delete_response.json" NoContent: description: No content Conflict: diff --git a/src/test/java/org/folio/consortia/controller/SharingPolicyControllerTest.java b/src/test/java/org/folio/consortia/controller/SharingPolicyControllerTest.java index c8863d7c..53292ec0 100644 --- a/src/test/java/org/folio/consortia/controller/SharingPolicyControllerTest.java +++ b/src/test/java/org/folio/consortia/controller/SharingPolicyControllerTest.java @@ -1,16 +1,7 @@ package org.folio.consortia.controller; -import org.folio.consortia.base.BaseIT; -import org.folio.consortia.domain.dto.SharingPolicyDeleteResponse; -import org.folio.consortia.domain.dto.SharingPolicyResponse; -import org.folio.consortia.service.impl.SharingPolicyService; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.http.MediaType; - -import java.util.UUID; - +import static org.folio.consortia.support.EntityUtils.SHARING_POLICY_REQUEST_SAMPLE_FOR_ROLES; +import static org.folio.consortia.utils.InputOutputTestUtils.getMockDataAsString; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; @@ -18,43 +9,55 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.util.UUID; + +import org.folio.consortia.base.BaseIT; +import org.folio.consortia.domain.dto.SharingPolicyDeleteResponse; +import org.folio.consortia.domain.dto.SharingPolicyResponse; +import org.folio.consortia.service.impl.SharingPolicyService; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.http.MediaType; + class SharingPolicyControllerTest extends BaseIT { + private static final String BASE_URL = "/consortia/7698e46-c3e3-11ed-afa1-0242ac120002/sharing/policies"; + @MockBean SharingPolicyService sharingPolicyService; - @ParameterizedTest - @ValueSource(strings = {"{\"policyId\":\"1844767a-8367-4926-9999-514c35840399\",\"url\":\"/organizations-storage/organizations\",\"payload\":{\"name\":\"ORG-NAME\",\"source\":\"local\"}}" }) - void shouldStartSharingPolicy(String body) throws Exception { + @Test + void shouldStartSharingPolicy() throws Exception { var headers = defaultHeaders(); + var body = getMockDataAsString(SHARING_POLICY_REQUEST_SAMPLE_FOR_ROLES); UUID createPoliciesPcId = UUID.randomUUID(); UUID updatePoliciesPcId = UUID.randomUUID(); SharingPolicyResponse sharingPolicyResponse = new SharingPolicyResponse() - .createPoliciesPCId(createPoliciesPcId) - .updatePoliciesPCId(updatePoliciesPcId); + .createPCId(createPoliciesPcId) + .updatePCId(updatePoliciesPcId); when(sharingPolicyService.start(any(), any())).thenReturn(sharingPolicyResponse); this.mockMvc.perform( - post("/consortia/7698e46-c3e3-11ed-afa1-0242ac120002/sharing/policies") + post(BASE_URL) .headers(headers) .content(body) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isCreated()) - .andExpect(jsonPath("$.createPoliciesPCId").value(String.valueOf(createPoliciesPcId))) - .andExpect(jsonPath("$.updatePoliciesPCId").value(String.valueOf(updatePoliciesPcId))); + .andExpect(jsonPath("$.createPCId").value(String.valueOf(createPoliciesPcId))) + .andExpect(jsonPath("$.updatePCId").value(String.valueOf(updatePoliciesPcId))); } - @ParameterizedTest - @ValueSource(strings = {"{\"policyId\":\"1844767a-8367-4926-9999-514c35840399\",\"url\":\"/organizations-storage/organizations\"}" }) - void shouldDeleteSharingPolicy(String body) throws Exception { + @Test + void shouldDeleteSharingPolicy() throws Exception { var headers = defaultHeaders(); + var body = getMockDataAsString(SHARING_POLICY_REQUEST_SAMPLE_FOR_ROLES); UUID pcId = UUID.randomUUID(); SharingPolicyDeleteResponse sharingPolicyDeleteResponse = new SharingPolicyDeleteResponse().pcId(pcId); when(sharingPolicyService.delete(any(), any(), any())).thenReturn(sharingPolicyDeleteResponse); this.mockMvc.perform( - delete("/consortia/7698e46-c3e3-11ed-afa1-0242ac120002/sharing/policies/1844767a-8367-4926-9999-514c35840399") + delete(BASE_URL + "/1844767a-8367-4926-9999-514c35840399") .headers(headers) .content(body) .contentType(MediaType.APPLICATION_JSON)) diff --git a/src/test/java/org/folio/consortia/controller/SharingRoleCapabilityControllerTest.java b/src/test/java/org/folio/consortia/controller/SharingRoleCapabilityControllerTest.java index c4049e6d..23ce2079 100644 --- a/src/test/java/org/folio/consortia/controller/SharingRoleCapabilityControllerTest.java +++ b/src/test/java/org/folio/consortia/controller/SharingRoleCapabilityControllerTest.java @@ -8,10 +8,12 @@ import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; +import java.util.List; import java.util.UUID; import static org.folio.consortia.support.EntityUtils.SHARING_ROLE_CAPABILITIES_REQUEST_SAMPLE; import static org.folio.consortia.utils.InputOutputTestUtils.getMockDataAsString; +import static org.hamcrest.Matchers.hasItems; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; @@ -20,6 +22,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; class SharingRoleCapabilityControllerTest extends BaseIT { + private static final String BASE_URL = "/consortia/7698e46-c3e3-11ed-afa1-0242ac120002/sharing/roles"; @MockBean SharingRoleCapabilityService sharingRoleCapabilityService; @@ -28,37 +31,40 @@ class SharingRoleCapabilityControllerTest extends BaseIT { void shouldStartSharingRoleCapabilities() throws Exception { var headers = defaultHeaders(); var request = getMockDataAsString(SHARING_ROLE_CAPABILITIES_REQUEST_SAMPLE); - var createPcId = UUID.randomUUID(); - var updatePcId = UUID.randomUUID(); + var createPcIds = List.of(UUID.randomUUID(), UUID.randomUUID()); + var updatePcIds = List.of(UUID.randomUUID(), UUID.randomUUID()); + var response = new SharingRoleCapabilityResponse() - .createRoleCapabilitiesPCId(createPcId) - .updateRoleCapabilitiesPCId(updatePcId); + .createPCIds(createPcIds) + .updatePCIds(updatePcIds); when(sharingRoleCapabilityService.start(any(), any())).thenReturn(response); this.mockMvc.perform( - post("/consortia/7698e46-c3e3-11ed-afa1-0242ac120002/sharing/roles/capabilities") + post(BASE_URL + "/capabilities") .headers(headers) .content(request) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isCreated()) - .andExpect(jsonPath("$.createRoleCapabilitiesPCId").value(String.valueOf(createPcId))) - .andExpect(jsonPath("$.updateRoleCapabilitiesPCId").value(String.valueOf(updatePcId))); + .andExpect(jsonPath("$.createPCIds").isArray()) + .andExpect(jsonPath("$.createPCIds", hasItems(createPcIds.get(0).toString(), createPcIds.get(1).toString()))) + .andExpect(jsonPath("$.updatePCIds").isArray()) + .andExpect(jsonPath("$.updatePCIds", hasItems(updatePcIds.get(0).toString(), updatePcIds.get(1).toString()))); } @Test void shouldDeleteSharingRoleCapabilities() throws Exception { var headers = defaultHeaders(); var request = getMockDataAsString(SHARING_ROLE_CAPABILITIES_REQUEST_SAMPLE); - var pcId = UUID.randomUUID(); + var pcIds = List.of(UUID.randomUUID(), UUID.randomUUID()); + var response = new SharingRoleCapabilityDeleteResponse() - .pcId(pcId); + .pcIds(pcIds); when(sharingRoleCapabilityService.delete(any(), any(), any())).thenReturn(response); this.mockMvc.perform( - delete("/consortia/7698e46-c3e3-11ed-afa1-0242ac120002/" + - "sharing/roles/2844767a-8367-4926-9999-514c35840399/capabilities") + delete(BASE_URL + "/2844767a-8367-4926-9999-514c35840399/capabilities") .headers(headers) .content(request) .contentType(MediaType.APPLICATION_JSON)) diff --git a/src/test/java/org/folio/consortia/controller/SharingRoleCapabilitySetControllerTest.java b/src/test/java/org/folio/consortia/controller/SharingRoleCapabilitySetControllerTest.java index 89f952fb..dc1a988d 100644 --- a/src/test/java/org/folio/consortia/controller/SharingRoleCapabilitySetControllerTest.java +++ b/src/test/java/org/folio/consortia/controller/SharingRoleCapabilitySetControllerTest.java @@ -2,6 +2,7 @@ import static org.folio.consortia.support.EntityUtils.SHARING_ROLE_CAPABILITY_SETS_REQUEST_SAMPLE; import static org.folio.consortia.utils.InputOutputTestUtils.getMockDataAsString; +import static org.hamcrest.Matchers.hasItems; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; @@ -9,6 +10,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.util.List; import java.util.UUID; import org.folio.consortia.base.BaseIT; import org.folio.consortia.domain.dto.SharingRoleCapabilitySetDeleteResponse; @@ -19,6 +21,7 @@ import org.springframework.http.MediaType; class SharingRoleCapabilitySetControllerTest extends BaseIT { + private static final String BASE_URL = "/consortia/7698e46-c3e3-11ed-afa1-0242ac120002/sharing/roles"; @MockBean SharingRoleCapabilitySetService sharingRoleCapabilitySetService; @@ -27,40 +30,43 @@ class SharingRoleCapabilitySetControllerTest extends BaseIT { void shouldStartSharingRole() throws Exception { var headers = defaultHeaders(); String request = getMockDataAsString(SHARING_ROLE_CAPABILITY_SETS_REQUEST_SAMPLE); - UUID createRoleCapabilitySetsPCId = UUID.randomUUID(); - UUID updateRoleCapabilitySetsPCId = UUID.randomUUID(); + var createPcIds = List.of(UUID.randomUUID(), UUID.randomUUID()); + var updatePcIds = List.of(UUID.randomUUID(), UUID.randomUUID()); var response = new SharingRoleCapabilitySetResponse() - .createRoleCapabilitySetsPCId(createRoleCapabilitySetsPCId) - .updateRoleCapabilitySetsPCId(updateRoleCapabilitySetsPCId); + .createPCIds(createPcIds) + .updatePCIds(updatePcIds); when(sharingRoleCapabilitySetService.start(any(), any())).thenReturn(response); this.mockMvc.perform( - post("/consortia/7698e46-c3e3-11ed-afa1-0242ac120002/sharing/roles/capability-sets") + post(BASE_URL + "/capability-sets") .headers(headers) .content(request) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isCreated()) - .andExpect(jsonPath("$.createRoleCapabilitySetsPCId").value(String.valueOf(createRoleCapabilitySetsPCId))) - .andExpect(jsonPath("$.updateRoleCapabilitySetsPCId").value(String.valueOf(updateRoleCapabilitySetsPCId))); + .andExpect(jsonPath("$.createPCIds").isArray()) + .andExpect(jsonPath("$.createPCIds", hasItems(createPcIds.get(0).toString(), createPcIds.get(1).toString()))) + .andExpect(jsonPath("$.updatePCIds").isArray()) + .andExpect(jsonPath("$.updatePCIds", hasItems(updatePcIds.get(0).toString(), updatePcIds.get(1).toString()))); } @Test void shouldDeleteSharingRole() throws Exception { var headers = defaultHeaders(); String request = getMockDataAsString(SHARING_ROLE_CAPABILITY_SETS_REQUEST_SAMPLE); - UUID pcId = UUID.randomUUID(); + var pcIds = List.of(UUID.randomUUID(), UUID.randomUUID()); var response = new SharingRoleCapabilitySetDeleteResponse() - .pcId(pcId); + .pcIds(pcIds); when(sharingRoleCapabilitySetService.delete(any(), any(), any())).thenReturn(response); this.mockMvc.perform( - delete("/consortia/7698e46-c3e3-11ed-afa1-0242ac120002/" + - "sharing/roles/2844767a-8367-4926-9999-514c35840399/capability-sets") + delete(BASE_URL + "/2844767a-8367-4926-9999-514c35840399/capability-sets") .headers(headers) .content(request) .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().is2xxSuccessful()); + .andExpect(status().is2xxSuccessful()) + .andExpect(jsonPath("$.pcIds").isArray()) + .andExpect(jsonPath("$.pcIds", hasItems(pcIds.get(0).toString(), pcIds.get(1).toString()))); } } diff --git a/src/test/java/org/folio/consortia/controller/SharingRoleControllerTest.java b/src/test/java/org/folio/consortia/controller/SharingRoleControllerTest.java index 94b74a9b..f2f5e710 100644 --- a/src/test/java/org/folio/consortia/controller/SharingRoleControllerTest.java +++ b/src/test/java/org/folio/consortia/controller/SharingRoleControllerTest.java @@ -1,5 +1,9 @@ package org.folio.consortia.controller; +import static org.folio.consortia.support.EntityUtils.SHARING_ROLE_REQUEST_SAMPLE; +import static org.folio.consortia.support.EntityUtils.SHARING_ROLE_REQUEST_SAMPLE_WITHOUT_PAYLOAD; +import static org.folio.consortia.utils.InputOutputTestUtils.getMockDataAsString; +import static org.hamcrest.Matchers.hasItems; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete; @@ -7,57 +11,64 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.util.List; import java.util.UUID; import org.folio.consortia.base.BaseIT; import org.folio.consortia.domain.dto.SharingRoleDeleteResponse; import org.folio.consortia.domain.dto.SharingRoleResponse; import org.folio.consortia.service.impl.SharingRoleService; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; +import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.http.MediaType; class SharingRoleControllerTest extends BaseIT { + private static final String BASE_URL = "/consortia/7698e46-c3e3-11ed-afa1-0242ac120002/sharing/roles"; + @MockBean SharingRoleService sharingRoleService; - @ParameterizedTest - @ValueSource(strings = {"{\"roleId\":\"2844767a-8367-4926-9999-514c35840399\",\"url\":\"/role\",\"payload\":{\"name\":\"ROLE-NAME\",\"source\":\"local\"}}" }) - void shouldStartSharingRole(String body) throws Exception { + @Test + void shouldStartSharingRole() throws Exception { + var body = getMockDataAsString(SHARING_ROLE_REQUEST_SAMPLE); var headers = defaultHeaders(); - UUID createRolesPcId = UUID.randomUUID(); - UUID updateRolesPcId = UUID.randomUUID(); - SharingRoleResponse sharingRoleResponse = new SharingRoleResponse() - .createRolesPCId(createRolesPcId) - .updateRolesPCId(updateRolesPcId); + var createPcIds = List.of(UUID.randomUUID(), UUID.randomUUID()); + var updatePcIds = List.of(UUID.randomUUID(), UUID.randomUUID()); + var sharingRoleResponse = new SharingRoleResponse() + .createPCIds(createPcIds) + .updatePCIds(updatePcIds); when(sharingRoleService.start(any(), any())).thenReturn(sharingRoleResponse); this.mockMvc.perform( - post("/consortia/7698e46-c3e3-11ed-afa1-0242ac120002/sharing/roles") + post(BASE_URL) .headers(headers) .content(body) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isCreated()) - .andExpect(jsonPath("$.createRolesPCId").value(String.valueOf(createRolesPcId))) - .andExpect(jsonPath("$.updateRolesPCId").value(String.valueOf(updateRolesPcId))); + .andExpect(jsonPath("$.createPCIds").isArray()) + .andExpect(jsonPath("$.createPCIds", hasItems(createPcIds.get(0).toString(), createPcIds.get(1).toString()))) + .andExpect(jsonPath("$.updatePCIds").isArray()) + .andExpect(jsonPath("$.updatePCIds", hasItems(updatePcIds.get(0).toString(), updatePcIds.get(1).toString()))); + } - @ParameterizedTest - @ValueSource(strings = {"{\"roleId\":\"2844767a-8367-4926-9999-514c35840399\",\"url\":\"/role\"}" }) - void shouldDeleteSharingRole(String body) throws Exception { + @Test + void shouldDeleteSharingRole() throws Exception { + var body = getMockDataAsString(SHARING_ROLE_REQUEST_SAMPLE_WITHOUT_PAYLOAD); var headers = defaultHeaders(); - UUID pcId = UUID.randomUUID(); - SharingRoleDeleteResponse sharingRoleDeleteResponse = new SharingRoleDeleteResponse().pcId(pcId); + var pcIds = List.of(UUID.randomUUID(), UUID.randomUUID()); + var sharingRoleDeleteResponse = new SharingRoleDeleteResponse().pcIds(pcIds); when(sharingRoleService.delete(any(), any(), any())).thenReturn(sharingRoleDeleteResponse); this.mockMvc.perform( - delete("/consortia/7698e46-c3e3-11ed-afa1-0242ac120002/sharing/roles/2844767a-8367-4926-9999-514c35840399") + delete(BASE_URL + "/3844767a-8367-4926-9999-514c35840399") .headers(headers) .content(body) .contentType(MediaType.APPLICATION_JSON)) - .andExpect(status().is2xxSuccessful()); + .andExpect(status().is2xxSuccessful()) + .andExpect(jsonPath("$.pcIds").isArray()) + .andExpect(jsonPath("$.pcIds", hasItems(pcIds.get(0).toString(), pcIds.get(1).toString()))); } } diff --git a/src/test/java/org/folio/consortia/service/BaseSharingConfigServiceTest.java b/src/test/java/org/folio/consortia/service/BaseSharingConfigServiceTest.java index 5510d1cd..cd614ea4 100644 --- a/src/test/java/org/folio/consortia/service/BaseSharingConfigServiceTest.java +++ b/src/test/java/org/folio/consortia/service/BaseSharingConfigServiceTest.java @@ -2,6 +2,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.ObjectNode; + +import feign.Request; import org.folio.consortia.domain.dto.PublicationRequest; import org.folio.consortia.domain.dto.PublicationResponse; import org.folio.consortia.repository.ConsortiumRepository; @@ -19,7 +21,9 @@ import org.springframework.core.task.TaskExecutor; import org.springframework.test.util.ReflectionTestUtils; +import java.nio.charset.StandardCharsets; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.UUID; @@ -28,6 +32,7 @@ import static org.folio.consortia.support.EntityUtils.CENTRAL_TENANT_ID; import static org.folio.consortia.support.EntityUtils.TENANT_ID_1; import static org.folio.consortia.support.EntityUtils.TENANT_ID_2; +import static org.folio.consortia.support.EntityUtils.createOkapiHeaders; import static org.folio.consortia.support.EntityUtils.createTenant; import static org.folio.consortia.support.EntityUtils.createTenantCollection; import static org.folio.consortia.support.TestConstants.CONSORTIUM_ID; @@ -69,6 +74,8 @@ void setUp() { when(systemUserScopedExecutionService.executeSystemUserScoped(eq(CENTRAL_TENANT_ID), any())) .then(this::callSecondArgument); when(tenantService.getAll(CONSORTIUM_ID)).thenReturn(tenantCollection); + Map> okapiHeaders = createOkapiHeaders(); + when(folioExecutionContext.getOkapiHeaders()).thenReturn(okapiHeaders); ReflectionTestUtils.setField(getServiceUnderTest(), "maxTries", 60); ReflectionTestUtils.setField(getServiceUnderTest(), "interval", 200); @@ -89,12 +96,22 @@ protected void setupCommonMocksForDelete(UUID pcId, PublicationRequest publicati } protected T callSecondArgument(InvocationOnMock invocation) throws Exception { - var headers = Map.>of(XOkapiHeaders.TENANT, List.of("mobius")); + var headers = Map.>of(XOkapiHeaders.TENANT, List.of(CENTRAL_TENANT_ID)); var context = new DefaultFolioExecutionContext(mock(FolioModuleMetadata.class), headers); try (var ignored = new FolioExecutionContextSetter(context)) { return invocation.>getArgument(1).call(); } } + protected Request buildFeignRequest() { + return Request + .create(Request.HttpMethod.GET, + "/roles", + Collections.emptyMap(), + null, + StandardCharsets.UTF_8, + null); + } + protected abstract Object getServiceUnderTest(); } diff --git a/src/test/java/org/folio/consortia/service/SharingPolicyServiceTest.java b/src/test/java/org/folio/consortia/service/SharingPolicyServiceTest.java index 649b6b7f..be3b7365 100644 --- a/src/test/java/org/folio/consortia/service/SharingPolicyServiceTest.java +++ b/src/test/java/org/folio/consortia/service/SharingPolicyServiceTest.java @@ -1,6 +1,9 @@ package org.folio.consortia.service; import com.fasterxml.jackson.databind.node.ObjectNode; + +import feign.FeignException; +import org.folio.consortia.client.PoliciesClient; import org.folio.consortia.domain.dto.PublicationStatus; import org.folio.consortia.domain.dto.SharingPolicyRequest; import org.folio.consortia.domain.entity.SharingPolicyEntity; @@ -35,6 +38,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -46,35 +50,40 @@ class SharingPolicyServiceTest extends BaseSharingConfigServiceTest{ SharingPolicyService sharingPolicyService; @Mock SharingPolicyRepository sharingPolicyRepository; + @Mock + PoliciesClient policiesClient; @Test void shouldStartSharingPolicy() { + var request = getMockDataObject(SHARING_POLICY_REQUEST_SAMPLE_FOR_ROLES, SharingPolicyRequest.class); var createPcId = UUID.randomUUID(); var updatePcId = UUID.randomUUID(); var tenantSharedPolicy = Set.of(TENANT_ID_1); - var request = getMockDataObject(SHARING_POLICY_REQUEST_SAMPLE_FOR_ROLES, SharingPolicyRequest.class); var payload = createPayloadForPolicy(); // "tenant1" exists in tenant policy association so that tenant1 is in PUT request publication, // "tenant2" is in POST method publication - var expectedPubRequestPost = createPublicationRequest(CONSORTIUM.getPolicyValue(), payload, HttpMethod.POST) - .tenants(Set.of(TENANT_ID_2)) - .url(request.getUrl()); var expectedPubRequestPut = createPublicationRequest(CONSORTIUM.getPolicyValue(), payload, HttpMethod.PUT) .tenants(Set.of(TENANT_ID_1)) .url(request.getUrl() + "/" + request.getPolicyId()); + var expectedPubRequestPost = createPublicationRequest(CONSORTIUM.getPolicyValue(), payload, HttpMethod.POST) + .tenants(Set.of(TENANT_ID_2)) + .url(request.getUrl()); var expectedSharingPolicyEntity = createSharingPolicyEntity(request.getPolicyId(), TENANT_ID_2); setupCommonMocksForStart(createPcId, updatePcId, expectedPubRequestPost, expectedPubRequestPut, payload); + doThrow(new FeignException.NotFound("Policy not found", buildFeignRequest(), null, null)) + .when(policiesClient).getPolicyById(any()); when(sharingPolicyRepository.findTenantsByPolicyId(request.getPolicyId())).thenReturn(tenantSharedPolicy); when(sharingPolicyRepository.save(expectedSharingPolicyEntity)).thenReturn(new SharingPolicyEntity()); var actualResponse = sharingPolicyService.start(CONSORTIUM_ID, request); - assertThat(actualResponse.getCreatePoliciesPCId()).isEqualTo(createPcId); - assertThat(actualResponse.getUpdatePoliciesPCId()).isEqualTo(updatePcId); + assertThat(actualResponse.getCreatePCId()).isEqualTo(createPcId); + assertThat(actualResponse.getUpdatePCId()).isEqualTo(updatePcId); verify(publicationService, times(2)).publishRequest(any(), any()); + verify(policiesClient).getPolicyById(request.getPolicyId()); } @Test @@ -99,6 +108,7 @@ void shouldDeleteSharingPolicy() { assertThat(actualResponse.getPcId()).isEqualTo(pcId); verify(publicationService, times(1)).publishRequest(any(), any()); + verify(policiesClient).getPolicyById(request.getPolicyId()); } @Test diff --git a/src/test/java/org/folio/consortia/service/SharingRoleCapabilityServiceTest.java b/src/test/java/org/folio/consortia/service/SharingRoleCapabilityServiceTest.java index f1c16c57..960fb144 100644 --- a/src/test/java/org/folio/consortia/service/SharingRoleCapabilityServiceTest.java +++ b/src/test/java/org/folio/consortia/service/SharingRoleCapabilityServiceTest.java @@ -1,13 +1,14 @@ package org.folio.consortia.service; import com.fasterxml.jackson.databind.node.ObjectNode; + import org.folio.consortia.domain.dto.PublicationStatus; import org.folio.consortia.domain.dto.SharingRoleCapabilityRequest; -import org.folio.consortia.domain.entity.SharingRoleEntity; import org.folio.consortia.exception.ResourceNotFoundException; import org.folio.consortia.repository.SharingRoleRepository; import org.folio.consortia.service.impl.SharingRoleCapabilityService; -import org.folio.consortia.service.impl.SharingRoleCapabilitySetService; +import org.folio.consortia.service.impl.SharingRoleService; +import org.folio.consortia.support.EntityUtils; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; @@ -16,11 +17,14 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.UUID; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.folio.consortia.domain.dto.SourceValues.CONSORTIUM; +import static org.folio.consortia.domain.dto.SourceValues.USER; import static org.folio.consortia.support.EntityUtils.SHARING_ROLE_CAPABILITIES_REQUEST_SAMPLE; import static org.folio.consortia.support.EntityUtils.SHARING_ROLE_CAPABILITIES_WITHOUT_PAYLOAD_REQUEST_SAMPLE; import static org.folio.consortia.support.EntityUtils.SHARING_ROLE_CAPABILITY_SETS_REQUEST_SAMPLE; @@ -31,7 +35,6 @@ import static org.folio.consortia.support.EntityUtils.createPublicationRequest; import static org.folio.consortia.support.EntityUtils.createPublicationResultCollection; import static org.folio.consortia.support.EntityUtils.createSharingRoleEntity; -import static org.folio.consortia.support.EntityUtils.createSharingRoleResponseForDelete; import static org.folio.consortia.support.TestConstants.CENTRAL_TENANT_ID; import static org.folio.consortia.support.TestConstants.CONSORTIUM_ID; import static org.folio.consortia.utils.InputOutputTestUtils.getMockDataObject; @@ -49,37 +52,57 @@ class SharingRoleCapabilityServiceTest extends BaseSharingConfigServiceTest { SharingRoleCapabilityService sharingRoleCapabilityService; @Mock SharingRoleRepository sharingRoleRepository; + @Mock + SharingRoleService sharingRoleService; @Test void shouldStartSharingRoleCapabilities() { + var request = getMockDataObject(SHARING_ROLE_CAPABILITIES_REQUEST_SAMPLE, SharingRoleCapabilityRequest.class); + var roleIdForTenant1 = request.getRoleId(); + var roleIdForTenant2 = UUID.randomUUID(); var createPcId = UUID.randomUUID(); var updatePcId = UUID.randomUUID(); var tenantSharedRoleAndCapabilities = Set.of(TENANT_ID_1); - var request = getMockDataObject(SHARING_ROLE_CAPABILITIES_REQUEST_SAMPLE, SharingRoleCapabilityRequest.class); var sharingRoleEntity = createSharingRoleEntity(request.getRoleId(), TENANT_ID_2); - var payload = createPayloadForRoleCapabilities(); - var expectedSharingRoleEntity = createSharingRoleEntity(request.getRoleId(), TENANT_ID_2); - expectedSharingRoleEntity.setIsCapabilitiesShared(true); + var payloadForTenant1 = createPayloadForRoleCapabilities(roleIdForTenant1); + var payloadForTenant2 = createPayloadForRoleCapabilities(roleIdForTenant2); + + var expectedPayloadTenant1 = createPayloadForRoleCapabilities(roleIdForTenant1); + var expectedPayloadTenant2 = createPayloadForRoleCapabilities(roleIdForTenant2); // "tenant1" exists in tenant role association so that tenant1 is in PUT request publication, // "tenant2" is in POST method publication - var expectedPubRequestPost = createPublicationRequest(CONSORTIUM.getRoleValue(), payload, HttpMethod.POST) + var expectedPubRequestPut = createPublicationRequest(CONSORTIUM.getRoleValue(), expectedPayloadTenant1, HttpMethod.PUT) + .tenants(Set.of(TENANT_ID_1)) + .url("/roles/" + roleIdForTenant1 + "/capabilities"); + var expectedPubRequestPost = createPublicationRequest(CONSORTIUM.getRoleValue(), expectedPayloadTenant2, HttpMethod.POST) .tenants(Set.of(TENANT_ID_2)) .url(request.getUrl()); - var expectedPubRequestPut = createPublicationRequest(CONSORTIUM.getRoleValue(), payload, HttpMethod.PUT) - .tenants(Set.of(TENANT_ID_1)) - .url("/roles/" + request.getRoleId() + "/capabilities"); + var expectedSharingRoleEntity = createSharingRoleEntity(roleIdForTenant2, TENANT_ID_2); + expectedSharingRoleEntity.setIsCapabilitiesShared(true); - setupCommonMocksForStart(createPcId, updatePcId, expectedPubRequestPost, expectedPubRequestPut, payload); - when(sharingRoleRepository.findTenantsByRoleIdAndIsCapabilitiesSharedTrue(request.getRoleId())) + setupCommonMocksForStart(createPcId, updatePcId, expectedPubRequestPost, expectedPubRequestPut, payloadForTenant1); + when(objectMapper.convertValue(request.getPayload(), ObjectNode.class)) + .thenReturn(payloadForTenant1) + .thenReturn(payloadForTenant1) + .thenReturn(payloadForTenant2); + when(objectMapper.convertValue(payloadForTenant1, ObjectNode.class)) + .thenReturn(payloadForTenant1); + when(objectMapper.convertValue(payloadForTenant2, ObjectNode.class)) + .thenReturn(payloadForTenant2); + when(sharingRoleRepository.existsByRoleIdAndTenantId(any(), any())).thenReturn(false); + when(sharingRoleRepository.findTenantsByRoleNameAndIsCapabilitiesSharedTrue(request.getRoleName())) .thenReturn(tenantSharedRoleAndCapabilities); - when(sharingRoleRepository.findByRoleIdAndTenantId(request.getRoleId(), TENANT_ID_2)).thenReturn(sharingRoleEntity); - when(sharingRoleRepository.save(expectedSharingRoleEntity)).thenReturn(new SharingRoleEntity()); + when(sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_1)).thenReturn(roleIdForTenant1); + when(sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_2)).thenReturn(roleIdForTenant2); + when(sharingRoleRepository.findByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_2)) + .thenReturn(Optional.of(sharingRoleEntity)); + when(sharingRoleRepository.saveAll(List.of(expectedSharingRoleEntity))).thenReturn(List.of(expectedSharingRoleEntity)); var actualResponse = sharingRoleCapabilityService.start(CONSORTIUM_ID, request); - assertThat(actualResponse.getCreateRoleCapabilitiesPCId()).isEqualTo(createPcId); - assertThat(actualResponse.getUpdateRoleCapabilitiesPCId()).isEqualTo(updatePcId); + assertThat(actualResponse.getCreatePCIds()).isEqualTo(List.of(createPcId)); + assertThat(actualResponse.getUpdatePCIds()).isEqualTo(List.of(updatePcId)); verify(publicationService, times(2)).publishRequest(any(), any()); } @@ -90,57 +113,78 @@ void shouldDeleteSharingRoleCapabilities() { var roleId = UUID.fromString("5844767a-8367-4926-9999-514c35840399"); var tenantSharedRoleAndCapabilities = Set.of(TENANT_ID_1); var request = getMockDataObject(SHARING_ROLE_CAPABILITIES_REQUEST_SAMPLE, SharingRoleCapabilityRequest.class); + var payload = createPayloadForRoleCapabilities(roleId); // "tenant1" exists in the tenant role association so that tenant1 is in DELETE request publication, var expectedPubRequestDelete = createPublicationRequest(HttpMethod.DELETE) .tenants(Set.of(TENANT_ID_1)) .url("/roles/" + request.getRoleId() + "/capabilities") - .payload(request.getPayload()); + .payload(payload); setupCommonMocksForDelete(pcId, expectedPubRequestDelete); + when(objectMapper.convertValue(any(), eq(ObjectNode.class))).thenReturn(payload); + when(sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_1)).thenReturn(roleId); when(sharingRoleRepository.existsByRoleId(roleId)).thenReturn(true); - when(sharingRoleRepository.findTenantsByRoleIdAndIsCapabilitiesSharedTrue(request.getRoleId())) + when(sharingRoleRepository.findTenantsByRoleNameAndIsCapabilitiesSharedTrue(request.getRoleName())) .thenReturn(tenantSharedRoleAndCapabilities); - var expectedResponse = createSharingRoleResponseForDelete(pcId); var actualResponse = sharingRoleCapabilityService.delete(CONSORTIUM_ID, roleId, request); - assertThat(actualResponse.getPcId()).isEqualTo(expectedResponse.getPcId()); + assertThat(actualResponse.getPcIds()).isEqualTo(List.of(pcId)); + verify(publicationService, times(1)).publishRequest(any(), any()); } @Test void shouldUpdateFailedTenantRoleCapabilities() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - var publicationId = UUID.randomUUID(); - var pcId = UUID.randomUUID(); var request = getMockDataObject(SHARING_ROLE_CAPABILITIES_REQUEST_SAMPLE, SharingRoleCapabilityRequest.class); - var publicationResultCollection = createPublicationResultCollection(CENTRAL_TENANT_ID, TENANT_ID_2); - var publicationDetails = createPublicationDetails(PublicationStatus.ERROR); - var expectedPayload = createPayloadForRoleCapabilities(); + var publicationId = UUID.randomUUID(); + var pcId1 = UUID.randomUUID(); + var pcId2 = UUID.randomUUID(); + var pubResultCollection = createPublicationResultCollection(CENTRAL_TENANT_ID, TENANT_ID_2); + var pubDetails = createPublicationDetails(PublicationStatus.ERROR); + var roleIdForTenant1 = request.getRoleId(); + var roleIdForTenant2 = UUID.randomUUID(); + var payloadForTenant1 = createPayloadForRoleCapabilities(roleIdForTenant1); + var payloadForTenant2 = createPayloadForRoleCapabilities(roleIdForTenant2); + var expectedPayloadTenant1 = createPayloadForRoleCapabilities(roleIdForTenant1); + var expectedPayloadTenant2 = createPayloadForRoleCapabilities(roleIdForTenant2); // expected data for publish request - var expectedPublicationRequest = createPublicationRequest(CONSORTIUM.getRoleValue(), expectedPayload, HttpMethod.PUT) - .url("/roles/" + request.getRoleId() + "/capabilities") - .tenants(Set.of(CENTRAL_TENANT_ID, TENANT_ID_2)); - - setupCommonMocksForDelete(pcId, expectedPublicationRequest); + var expectedPublicationRequest1 = createPublicationRequest(USER.getRoleValue(), expectedPayloadTenant1, HttpMethod.PUT) + .url("/roles/" + roleIdForTenant1 + "/capabilities") + .tenants(Set.of(CENTRAL_TENANT_ID)); + var expectedPublicationRequest2 = createPublicationRequest(USER.getRoleValue(), expectedPayloadTenant2, HttpMethod.PUT) + .url("/roles/" + roleIdForTenant2 + "/capabilities") + .tenants(Set.of(TENANT_ID_2)); + + setupCommonMocksForDelete(pcId1, expectedPublicationRequest1); + setupCommonMocksForDelete(pcId2, expectedPublicationRequest2); when(publicationService.checkPublicationDetailsExists(CONSORTIUM_ID, publicationId)) .thenReturn(false) .thenReturn(false) .thenReturn(true); - when(publicationService.getPublicationDetails(CONSORTIUM_ID, publicationId)).thenReturn(publicationDetails); - when(publicationService.getPublicationResults(CONSORTIUM_ID, publicationId)).thenReturn(publicationResultCollection); - when(objectMapper.convertValue(any(), eq(ObjectNode.class))).thenReturn(expectedPayload); + when(objectMapper.convertValue(request.getPayload(), ObjectNode.class)) + .thenReturn(payloadForTenant1) + .thenReturn(payloadForTenant2); + when(objectMapper.convertValue(payloadForTenant1, ObjectNode.class)).thenReturn(payloadForTenant1); + when(objectMapper.convertValue(payloadForTenant2, ObjectNode.class)).thenReturn(payloadForTenant2); + + when(sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), EntityUtils.CENTRAL_TENANT_ID)).thenReturn(roleIdForTenant1); + when(sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_2)).thenReturn(roleIdForTenant2); + when(publicationService.getPublicationDetails(CONSORTIUM_ID, publicationId)).thenReturn(pubDetails); + when(publicationService.getPublicationResults(CONSORTIUM_ID, publicationId)).thenReturn(pubResultCollection); // Use reflection to access the protected method in BaseSharingService - Method method = SharingRoleCapabilitySetService.class.getSuperclass() + Method method = SharingRoleCapabilityService.class.getSuperclass() .getDeclaredMethod("updateConfigsForFailedTenantsWithRetry", UUID.class, UUID.class, Object.class); method.setAccessible(true); method.invoke(sharingRoleCapabilityService, CONSORTIUM_ID, publicationId, request); verify(publicationService).getPublicationDetails(CONSORTIUM_ID, publicationId); verify(publicationService, times(3)).checkPublicationDetailsExists(CONSORTIUM_ID, publicationId); - verify(publicationService).publishRequest(CONSORTIUM_ID, expectedPublicationRequest); + verify(publicationService).publishRequest(CONSORTIUM_ID, expectedPublicationRequest1); + verify(publicationService).publishRequest(CONSORTIUM_ID, expectedPublicationRequest2); } // Negative cases @@ -148,7 +192,7 @@ void shouldUpdateFailedTenantRoleCapabilities() throws NoSuchMethodException, In void shouldThrowErrorForNotEqualRoleIdWithPayloadId() { var request = getMockDataObject(SHARING_ROLE_CAPABILITIES_REQUEST_SAMPLE, SharingRoleCapabilityRequest.class); request.setRoleId(UUID.randomUUID()); - var expectedPayload = createPayloadForRoleCapabilities(); + var expectedPayload = createPayloadForRoleCapabilities(UUID.randomUUID()); when(objectMapper.convertValue(any(), eq(ObjectNode.class))).thenReturn(expectedPayload); diff --git a/src/test/java/org/folio/consortia/service/SharingRoleCapabilitySetServiceTest.java b/src/test/java/org/folio/consortia/service/SharingRoleCapabilitySetServiceTest.java index 12707ca0..c3e31c8d 100644 --- a/src/test/java/org/folio/consortia/service/SharingRoleCapabilitySetServiceTest.java +++ b/src/test/java/org/folio/consortia/service/SharingRoleCapabilitySetServiceTest.java @@ -1,11 +1,14 @@ package org.folio.consortia.service; import com.fasterxml.jackson.databind.node.ObjectNode; + import org.folio.consortia.domain.dto.PublicationStatus; import org.folio.consortia.domain.dto.SharingRoleCapabilitySetRequest; import org.folio.consortia.exception.ResourceNotFoundException; import org.folio.consortia.repository.SharingRoleRepository; import org.folio.consortia.service.impl.SharingRoleCapabilitySetService; +import org.folio.consortia.service.impl.SharingRoleService; +import org.folio.consortia.support.EntityUtils; import org.junit.jupiter.api.Test; import org.mockito.InjectMocks; import org.mockito.Mock; @@ -14,11 +17,14 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.UUID; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.folio.consortia.domain.dto.SourceValues.CONSORTIUM; +import static org.folio.consortia.domain.dto.SourceValues.USER; import static org.folio.consortia.support.EntityUtils.SHARING_ROLE_CAPABILITY_SETS_REQUEST_SAMPLE; import static org.folio.consortia.support.EntityUtils.SHARING_ROLE_CAPABILITY_SETS_WITHOUT_PAYLOAD_REQUEST_SAMPLE; import static org.folio.consortia.support.EntityUtils.TENANT_ID_1; @@ -45,37 +51,56 @@ class SharingRoleCapabilitySetServiceTest extends BaseSharingConfigServiceTest{ SharingRoleCapabilitySetService sharingRoleCapabilitySetService; @Mock SharingRoleRepository sharingRoleRepository; + @Mock + SharingRoleService sharingRoleService; @Test void shouldStartSharingRoleCapabilitySets() { + var request = getMockDataObject(SHARING_ROLE_CAPABILITY_SETS_REQUEST_SAMPLE, SharingRoleCapabilitySetRequest.class); + var roleIdForTenant1 = request.getRoleId(); + var roleIdForTenant2 = UUID.randomUUID(); var createPcId = UUID.randomUUID(); var updatePcId = UUID.randomUUID(); var tenantSharedRoleAndCapabilitySets = Set.of(TENANT_ID_1); - var request = getMockDataObject(SHARING_ROLE_CAPABILITY_SETS_REQUEST_SAMPLE, SharingRoleCapabilitySetRequest.class); var sharingRoleEntity = createSharingRoleEntity(request.getRoleId(), TENANT_ID_2); - var payload = createPayloadForRoleCapabilitySets(); - var expectedSharingRoleEntity = createSharingRoleEntity(request.getRoleId(), TENANT_ID_2); - expectedSharingRoleEntity.setIsCapabilitySetsShared(true); + var payloadForTenant1 = createPayloadForRoleCapabilitySets(roleIdForTenant1); + var payloadForTenant2 = createPayloadForRoleCapabilitySets(roleIdForTenant2); + + var expectedPayloadTenant1 = createPayloadForRoleCapabilitySets(roleIdForTenant1); + var expectedPayloadTenant2 = createPayloadForRoleCapabilitySets(roleIdForTenant2); // "tenant1" exists in tenant role association so that tenant1 is in PUT request publication, // "tenant2" is in POST method publication - var expectedPubRequestPost = createPublicationRequest(CONSORTIUM.getRoleValue(), payload, HttpMethod.POST) + var expectedPubRequestPut = createPublicationRequest(CONSORTIUM.getRoleValue(), expectedPayloadTenant1, HttpMethod.PUT) + .tenants(Set.of(TENANT_ID_1)) + .url("/roles/" + roleIdForTenant1 + "/capability-sets"); + var expectedPubRequestPost = createPublicationRequest(CONSORTIUM.getRoleValue(), expectedPayloadTenant2, HttpMethod.POST) .tenants(Set.of(TENANT_ID_2)) .url(request.getUrl()); - var expectedPubRequestPut = createPublicationRequest(CONSORTIUM.getRoleValue(), payload, HttpMethod.PUT) - .tenants(Set.of(TENANT_ID_1)) - .url("/roles/" + request.getRoleId() + "/capability-sets"); + var expectedSharingRoleEntity = createSharingRoleEntity(roleIdForTenant2, TENANT_ID_2); + expectedSharingRoleEntity.setIsCapabilitySetsShared(true); - setupCommonMocksForStart(createPcId, updatePcId, expectedPubRequestPost, expectedPubRequestPut, payload); - when(sharingRoleRepository.findTenantsByRoleIdAndIsCapabilitySetsSharedTrue(request.getRoleId())) + setupCommonMocksForStart(createPcId, updatePcId, expectedPubRequestPost, expectedPubRequestPut, payloadForTenant1); + when(objectMapper.convertValue(request.getPayload(), ObjectNode.class)) + .thenReturn(payloadForTenant1) + .thenReturn(payloadForTenant1) + .thenReturn(payloadForTenant2); + when(objectMapper.convertValue(payloadForTenant1, ObjectNode.class)) + .thenReturn(payloadForTenant1); + when(objectMapper.convertValue(payloadForTenant2, ObjectNode.class)) + .thenReturn(payloadForTenant2); + when(sharingRoleRepository.findTenantsByRoleNameAndIsCapabilitySetsSharedTrue(request.getRoleName())) .thenReturn(tenantSharedRoleAndCapabilitySets); - when(sharingRoleRepository.findByRoleIdAndTenantId(request.getRoleId(), TENANT_ID_2)).thenReturn(sharingRoleEntity); - when(sharingRoleRepository.save(expectedSharingRoleEntity)).thenReturn(expectedSharingRoleEntity); + when(sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_1)).thenReturn(roleIdForTenant1); + when(sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_2)).thenReturn(roleIdForTenant2); + when(sharingRoleRepository.findByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_2)) + .thenReturn(Optional.of(sharingRoleEntity)); + when(sharingRoleRepository.saveAll(List.of(expectedSharingRoleEntity))).thenReturn(List.of(expectedSharingRoleEntity)); var actualResponse = sharingRoleCapabilitySetService.start(CONSORTIUM_ID, request); - assertThat(actualResponse.getCreateRoleCapabilitySetsPCId()).isEqualTo(createPcId); - assertThat(actualResponse.getUpdateRoleCapabilitySetsPCId()).isEqualTo(updatePcId); + assertThat(actualResponse.getCreatePCIds()).isEqualTo(List.of(createPcId)); + assertThat(actualResponse.getUpdatePCIds()).isEqualTo(List.of(updatePcId)); verify(publicationService, times(2)).publishRequest(any(), any()); } @@ -86,49 +111,66 @@ void shouldDeleteSharingRoleCapabilitySets() { var roleId = UUID.fromString("4844767a-8367-4926-9999-514c35840399"); var tenantSharedRoleAndCapabilitySets = Set.of(TENANT_ID_1); var request = getMockDataObject(SHARING_ROLE_CAPABILITY_SETS_REQUEST_SAMPLE, SharingRoleCapabilitySetRequest.class); + var payload = createPayloadForRoleCapabilitySets(roleId); - // "tenant1" exists in the tenant role association so that tenant1 is in DELETE request publication, var expectedPubRequestDelete = createPublicationRequest(HttpMethod.DELETE) .tenants(Set.of(TENANT_ID_1)) .url("/roles/" + request.getRoleId() + "/capability-sets") - .payload(request.getPayload()); + .payload(payload); setupCommonMocksForDelete(pcId, expectedPubRequestDelete); + when(objectMapper.convertValue(any(), eq(ObjectNode.class))).thenReturn(payload); + when(sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_1)).thenReturn(roleId); when(sharingRoleRepository.existsByRoleId(roleId)).thenReturn(true); - when(sharingRoleRepository.findTenantsByRoleIdAndIsCapabilitySetsSharedTrue(request.getRoleId())) + when(sharingRoleRepository.findTenantsByRoleNameAndIsCapabilitySetsSharedTrue(request.getRoleName())) .thenReturn(tenantSharedRoleAndCapabilitySets); var actualResponse = sharingRoleCapabilitySetService.delete(CONSORTIUM_ID, roleId, request); - assertThat(actualResponse.getPcId()).isEqualTo(pcId); + assertThat(actualResponse.getPcIds()).isEqualTo(List.of(pcId)); verify(publicationService, times(1)).publishRequest(any(), any()); } @Test void shouldUpdateFailedTenantRoleCapabilitySets() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - var publicationId = UUID.randomUUID(); - var pcId = UUID.randomUUID(); var request = getMockDataObject(SHARING_ROLE_CAPABILITY_SETS_REQUEST_SAMPLE, SharingRoleCapabilitySetRequest.class); + var publicationId = UUID.randomUUID(); + var pcId1 = UUID.randomUUID(); + var pcId2 = UUID.randomUUID(); var pubResultCollection = createPublicationResultCollection(CENTRAL_TENANT_ID, TENANT_ID_2); var pubDetails = createPublicationDetails(PublicationStatus.ERROR); - var payload = createPayloadForRoleCapabilitySets(); - - // expected data for publish request - var expectedPubRequest = createPublicationRequest(CONSORTIUM.getRoleValue(), payload, HttpMethod.PUT) - .url("/roles/" + request.getRoleId() + "/capability-sets") - .tenants(Set.of(CENTRAL_TENANT_ID, TENANT_ID_2)); - - setupCommonMocksForDelete(pcId, expectedPubRequest); + var roleIdForTenant1 = request.getRoleId(); + var roleIdForTenant2 = UUID.randomUUID(); + var payloadForTenant1 = createPayloadForRoleCapabilitySets(roleIdForTenant1); + var payloadForTenant2 = createPayloadForRoleCapabilitySets(roleIdForTenant2); + var expectedPayloadTenant1 = createPayloadForRoleCapabilitySets(roleIdForTenant1); + var expectedPayloadTenant2 = createPayloadForRoleCapabilitySets(roleIdForTenant2); + + var expectedPublicationRequest1 = createPublicationRequest(USER.getRoleValue(), expectedPayloadTenant1, HttpMethod.PUT) + .url("/roles/" + roleIdForTenant1 + "/capability-sets") + .tenants(Set.of(CENTRAL_TENANT_ID)); + var expectedPublicationRequest2 = createPublicationRequest(USER.getRoleValue(), expectedPayloadTenant2, HttpMethod.PUT) + .url("/roles/" + roleIdForTenant2 + "/capability-sets") + .tenants(Set.of(TENANT_ID_2)); + + setupCommonMocksForDelete(pcId1, expectedPublicationRequest1); + setupCommonMocksForDelete(pcId2, expectedPublicationRequest2); when(publicationService.checkPublicationDetailsExists(CONSORTIUM_ID, publicationId)) .thenReturn(false) .thenReturn(false) .thenReturn(true); + when(objectMapper.convertValue(request.getPayload(), ObjectNode.class)) + .thenReturn(payloadForTenant1) + .thenReturn(payloadForTenant2); + when(objectMapper.convertValue(payloadForTenant1, ObjectNode.class)).thenReturn(payloadForTenant1); + when(objectMapper.convertValue(payloadForTenant2, ObjectNode.class)).thenReturn(payloadForTenant2); + + when(sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), EntityUtils.CENTRAL_TENANT_ID)).thenReturn(roleIdForTenant1); + when(sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_2)).thenReturn(roleIdForTenant2); when(publicationService.getPublicationDetails(CONSORTIUM_ID, publicationId)).thenReturn(pubDetails); when(publicationService.getPublicationResults(CONSORTIUM_ID, publicationId)).thenReturn(pubResultCollection); - when(objectMapper.convertValue(any(), eq(ObjectNode.class))).thenReturn(payload); - // Use reflection to access the protected method in BaseSharingService Method method = SharingRoleCapabilitySetService.class.getSuperclass() .getDeclaredMethod("updateConfigsForFailedTenantsWithRetry", UUID.class, UUID.class, Object.class); method.setAccessible(true); @@ -136,14 +178,15 @@ void shouldUpdateFailedTenantRoleCapabilitySets() throws NoSuchMethodException, verify(publicationService).getPublicationDetails(CONSORTIUM_ID, publicationId); verify(publicationService, times(3)).checkPublicationDetailsExists(CONSORTIUM_ID, publicationId); - verify(publicationService).publishRequest(CONSORTIUM_ID, expectedPubRequest); + verify(publicationService).publishRequest(CONSORTIUM_ID, expectedPublicationRequest1); + verify(publicationService).publishRequest(CONSORTIUM_ID, expectedPublicationRequest2); } @Test void shouldThrowErrorForNotEqualRoleIdWithPayloadId() { var request = getMockDataObject(SHARING_ROLE_CAPABILITY_SETS_REQUEST_SAMPLE, SharingRoleCapabilitySetRequest.class); request.setRoleId(UUID.randomUUID()); - var payload = createPayloadForRoleCapabilitySets(); + var payload = createPayloadForRoleCapabilitySets(UUID.randomUUID()); when(objectMapper.convertValue(any(), eq(ObjectNode.class))).thenReturn(payload); diff --git a/src/test/java/org/folio/consortia/service/SharingRoleServiceTest.java b/src/test/java/org/folio/consortia/service/SharingRoleServiceTest.java index f59d982e..c6f6602f 100644 --- a/src/test/java/org/folio/consortia/service/SharingRoleServiceTest.java +++ b/src/test/java/org/folio/consortia/service/SharingRoleServiceTest.java @@ -1,7 +1,17 @@ package org.folio.consortia.service; import com.fasterxml.jackson.databind.node.ObjectNode; + +import org.folio.consortia.client.RoleCapabilitiesClient; +import org.folio.consortia.client.RoleCapabilitySetsClient; +import org.folio.consortia.client.RolesClient; +import org.folio.consortia.domain.dto.Capabilities; +import org.folio.consortia.domain.dto.Capability; +import org.folio.consortia.domain.dto.CapabilitySet; +import org.folio.consortia.domain.dto.CapabilitySets; import org.folio.consortia.domain.dto.PublicationStatus; +import org.folio.consortia.domain.dto.Role; +import org.folio.consortia.domain.dto.Roles; import org.folio.consortia.domain.dto.SharingRoleRequest; import org.folio.consortia.exception.ResourceNotFoundException; import org.folio.consortia.repository.SharingRoleRepository; @@ -14,11 +24,14 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.util.List; +import java.util.Optional; import java.util.Set; import java.util.UUID; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.folio.consortia.domain.dto.SourceValues.CONSORTIUM; +import static org.folio.consortia.domain.dto.SourceValues.USER; import static org.folio.consortia.support.EntityUtils.CENTRAL_TENANT_ID; import static org.folio.consortia.support.EntityUtils.SHARING_ROLE_REQUEST_SAMPLE; import static org.folio.consortia.support.EntityUtils.SHARING_ROLE_REQUEST_SAMPLE_WITHOUT_PAYLOAD; @@ -45,35 +58,116 @@ class SharingRoleServiceTest extends BaseSharingConfigServiceTest { SharingRoleService sharingRoleService; @Mock SharingRoleRepository sharingRoleRepository; + @Mock + RolesClient rolesClient; + @Mock + RoleCapabilitiesClient roleCapabilitiesClient; + @Mock + RoleCapabilitySetsClient roleCapabilitySetsClient; @Test void shouldStartSharingRole() { + var request = getMockDataObject(SHARING_ROLE_REQUEST_SAMPLE, SharingRoleRequest.class); + var roleIdForTenant1 = request.getRoleId(); + var roleIdForTenant2 = UUID.randomUUID(); var createPcId = UUID.randomUUID(); var updatePcId = UUID.randomUUID(); var tenantsSharedRole = Set.of(TENANT_ID_1); - var request = getMockDataObject(SHARING_ROLE_REQUEST_SAMPLE, SharingRoleRequest.class); - var payload = createPayloadForRole(); + + var payloadForTenant1 = createPayloadForRole(roleIdForTenant1.toString(), request.getRoleName()); + var payloadForTenant2 = createPayloadForRole(roleIdForTenant2.toString(), request.getRoleName()); // "tenant1" exists in tenant role association so that tenant1 is in PUT request publication, // "tenant2" is in POST method publication - var expectedPubRequestPOST = createPublicationRequest(CONSORTIUM.getRoleValue(), payload, HttpMethod.POST) + var expectedPuRequestPUT = createPublicationRequest(CONSORTIUM.getRoleValue(), payloadForTenant1, HttpMethod.PUT) + .tenants(Set.of(TENANT_ID_1)) + .url(request.getUrl() + "/" + roleIdForTenant1); + var expectedPubRequestPOST = createPublicationRequest(CONSORTIUM.getRoleValue(), payloadForTenant2, HttpMethod.POST) .tenants(Set.of(TENANT_ID_2)) .url(request.getUrl()); - var expectedPuRequestPUT = createPublicationRequest(CONSORTIUM.getRoleValue(), payload, HttpMethod.PUT) - .tenants(Set.of(TENANT_ID_1)) - .url(request.getUrl() + "/" + request.getRoleId()); - var expectedSharingRoleEntity = createSharingRoleEntity(request.getRoleId(), TENANT_ID_2); - - setupCommonMocksForStart(createPcId, updatePcId, expectedPubRequestPOST, expectedPuRequestPUT, payload); - when(sharingRoleRepository.findTenantsByRoleId(request.getRoleId())).thenReturn(tenantsSharedRole); + var expectedSharingRoleEntity = createSharingRoleEntity(roleIdForTenant2, TENANT_ID_2); + + setupCommonMocksForStart(createPcId, updatePcId, expectedPubRequestPOST, expectedPuRequestPUT, payloadForTenant1); + when(objectMapper.convertValue(any(), eq(ObjectNode.class))) + .thenReturn(payloadForTenant1) + .thenReturn(payloadForTenant2); + when(rolesClient.getRolesByQuery(any())).thenReturn(new Roles()); + when(sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_1)).thenReturn(roleIdForTenant1); + when(sharingRoleRepository.findTenantsByRoleName(request.getRoleName())).thenReturn(tenantsSharedRole); when(sharingRoleRepository.save(expectedSharingRoleEntity)).thenReturn(expectedSharingRoleEntity); var actualResponse = sharingRoleService.start(CONSORTIUM_ID, request); - assertThat(actualResponse.getCreateRolesPCId()).isEqualTo(createPcId); - assertThat(actualResponse.getUpdateRolesPCId()).isEqualTo(updatePcId); + assertThat(actualResponse.getCreatePCIds()).isEqualTo(List.of(createPcId)); + assertThat(actualResponse.getUpdatePCIds()).isEqualTo(List.of(updatePcId)); verify(publicationService, times(2)).publishRequest(any(), any()); + verify(rolesClient).getRolesByQuery(any()); + } + + @Test + void shouldSyncOnlySharingRole() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + var request = getMockDataObject(SHARING_ROLE_REQUEST_SAMPLE, SharingRoleRequest.class); + var roleIdForTenant1 = request.getRoleId(); + var role = new Role().id(roleIdForTenant1).name(request.getRoleName()); + var roles = new Roles().roles(List.of(role)); + var payloadForTenant1 = createPayloadForRole(roleIdForTenant1.toString(), request.getRoleName()); + var expectedSharingRoleEntity = createSharingRoleEntity(roleIdForTenant1, TENANT_ID_1); + + when(objectMapper.convertValue(any(), eq(ObjectNode.class))) + .thenReturn(payloadForTenant1); + when(rolesClient.getRolesByQuery(any())).thenReturn(roles); + when(roleCapabilitySetsClient.getRoleCapabilitySetsRoleId(any())).thenReturn(new CapabilitySets()); + when(roleCapabilitiesClient.getRoleCapabilitiesByRoleId(any())).thenReturn(new Capabilities()); + when(sharingRoleRepository.findByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_1)).thenReturn(Optional.empty()); + when(sharingRoleRepository.existsByRoleIdAndTenantId(roleIdForTenant1, TENANT_ID_1)).thenReturn(false); + // will check that desired sharing role is being saved + when(sharingRoleRepository.save(expectedSharingRoleEntity)).thenReturn(expectedSharingRoleEntity); + + // Use reflection to access the protected method in BaseSharingService + Method method = SharingRoleService.class.getSuperclass() + .getDeclaredMethod("syncConfigWithTenants", Object.class); + method.setAccessible(true); + method.invoke(sharingRoleService, request); + + verify(rolesClient).getRolesByQuery(any()); + verify(roleCapabilitiesClient).getRoleCapabilitiesByRoleId(any()); + verify(roleCapabilitySetsClient).getRoleCapabilitySetsRoleId(any()); + } + + @Test + void shouldSyncSharingRoleCapability() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { + var request = getMockDataObject(SHARING_ROLE_REQUEST_SAMPLE, SharingRoleRequest.class); + var roleIdForTenant1 = request.getRoleId(); + var role = new Role().id(roleIdForTenant1).name(request.getRoleName()); + var roles = new Roles().roles(List.of(role)); + var capability = new Capability().id(UUID.randomUUID()).name("capability"); + var capabilities = new Capabilities().capabilities(List.of(capability)); + var capabilitySet = new CapabilitySet().id(UUID.randomUUID()).name("capabilitySet"); + var capabilitySets = new CapabilitySets().capabilitySets(List.of(capabilitySet)); + + var payloadForTenant1 = createPayloadForRole(roleIdForTenant1.toString(), request.getRoleName()); + var expectedSharingRoleEntity = createSharingRoleEntity(roleIdForTenant1, TENANT_ID_1); + + when(objectMapper.convertValue(any(), eq(ObjectNode.class))) + .thenReturn(payloadForTenant1); + when(rolesClient.getRolesByQuery(any())).thenReturn(roles); + when(roleCapabilitySetsClient.getRoleCapabilitySetsRoleId(any())).thenReturn(capabilitySets); + when(roleCapabilitiesClient.getRoleCapabilitiesByRoleId(any())).thenReturn(capabilities); + when(sharingRoleRepository.findByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_1)).thenReturn(Optional.empty()); + when(sharingRoleRepository.existsByRoleIdAndTenantId(roleIdForTenant1, TENANT_ID_1)).thenReturn(false); + // will check that desired sharing role is being saved + when(sharingRoleRepository.save(expectedSharingRoleEntity)).thenReturn(expectedSharingRoleEntity); + + // Use reflection to access the protected method in BaseSharingService + Method method = SharingRoleService.class.getSuperclass() + .getDeclaredMethod("syncConfigWithTenants", Object.class); + method.setAccessible(true); + method.invoke(sharingRoleService, request); + + verify(rolesClient).getRolesByQuery(any()); + verify(roleCapabilitiesClient).getRoleCapabilitiesByRoleId(any()); + verify(roleCapabilitySetsClient).getRoleCapabilitySetsRoleId(any()); } @Test @@ -82,46 +176,68 @@ void shouldDeleteSharingRole() { var roleId = UUID.fromString("3844767a-8367-4926-9999-514c35840399"); var tenantsSharedRole = Set.of(TENANT_ID_1); var request = getMockDataObject(SHARING_ROLE_REQUEST_SAMPLE, SharingRoleRequest.class); + var payload = createPayloadForRole(roleId.toString(), request.getRoleName()); // "tenant1" exists in the tenant role association so that tenant1 is in DELETE request publication, var expectedPubRequestDELETE = createPublicationRequest(HttpMethod.DELETE) .tenants(Set.of(TENANT_ID_1)) .url(request.getUrl() + "/" + roleId) - .payload(request.getPayload()); + .payload(payload); setupCommonMocksForDelete(pcId, expectedPubRequestDELETE); + when(objectMapper.convertValue(any(), eq(ObjectNode.class))).thenReturn(payload); + when(rolesClient.getRolesByQuery(any())).thenReturn(new Roles()); + when(sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_1)).thenReturn(request.getRoleId()); when(sharingRoleRepository.existsByRoleId(roleId)).thenReturn(true); - when(sharingRoleRepository.findTenantsByRoleId(request.getRoleId())).thenReturn(tenantsSharedRole); + when(sharingRoleRepository.findTenantsByRoleName(request.getRoleName())).thenReturn(tenantsSharedRole); var actualResponse = sharingRoleService.delete(CONSORTIUM_ID, roleId, request); - assertThat(actualResponse.getPcId()).isEqualTo(pcId); + assertThat(actualResponse.getPcIds()).isEqualTo(List.of(pcId)); verify(publicationService, times(1)).publishRequest(any(), any()); + verify(rolesClient).getRolesByQuery(any()); } @Test void shouldUpdateFailedTenantRole() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException { - var publicationId = UUID.randomUUID(); - var pcId = UUID.randomUUID(); var request = getMockDataObject(SHARING_ROLE_REQUEST_SAMPLE, SharingRoleRequest.class); + var publicationId = UUID.randomUUID(); + var pcId1 = UUID.randomUUID(); + var pcId2 = UUID.randomUUID(); var pubResultCollection = createPublicationResultCollection(CENTRAL_TENANT_ID, TENANT_ID_2); var pubDetails = createPublicationDetails(PublicationStatus.ERROR); - var payload = createPayloadForRole(); + var roleIdForTenant1 = request.getRoleId(); + var roleIdForTenant2 = UUID.randomUUID(); + var payloadForTenant1 = createPayloadForRole(roleIdForTenant1.toString(), request.getRoleName()); + var payloadForTenant2 = createPayloadForRole(roleIdForTenant2.toString(), request.getRoleName()); + var expectedPayloadTenant1 = createPayloadForRole(roleIdForTenant1.toString(), request.getRoleName()); + var expectedPayloadTenant2 = createPayloadForRole(roleIdForTenant2.toString(), request.getRoleName()); // expected data for publish request - var expectedPubRequest = createPublicationRequest(CONSORTIUM.getRoleValue(), payload, HttpMethod.PUT) - .tenants(Set.of(CENTRAL_TENANT_ID, TENANT_ID_2)) - .url(request.getUrl() + "/" + request.getRoleId()); - - setupCommonMocksForDelete(pcId, expectedPubRequest); + var expectedPubRequest1 = createPublicationRequest(USER.getRoleValue(), expectedPayloadTenant1, HttpMethod.PUT) + .tenants(Set.of(CENTRAL_TENANT_ID)) + .url(request.getUrl() + "/" + roleIdForTenant1); + var expectedPubRequest2 = createPublicationRequest(USER.getRoleValue(), expectedPayloadTenant2, HttpMethod.PUT) + .url(request.getUrl() + "/" + roleIdForTenant2) + .tenants(Set.of(TENANT_ID_2)); + + setupCommonMocksForDelete(pcId1, expectedPubRequest1); + setupCommonMocksForDelete(pcId2, expectedPubRequest2); when(publicationService.checkPublicationDetailsExists(CONSORTIUM_ID, publicationId)) .thenReturn(false) .thenReturn(false) .thenReturn(true); + when(objectMapper.convertValue(request.getPayload(), ObjectNode.class)) + .thenReturn(payloadForTenant1) + .thenReturn(payloadForTenant2); + when(objectMapper.convertValue(payloadForTenant1, ObjectNode.class)).thenReturn(payloadForTenant1); + when(objectMapper.convertValue(payloadForTenant2, ObjectNode.class)).thenReturn(payloadForTenant2); + + when(sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), CENTRAL_TENANT_ID)).thenReturn(roleIdForTenant1); + when(sharingRoleRepository.findRoleIdByRoleNameAndTenantId(request.getRoleName(), TENANT_ID_2)).thenReturn(roleIdForTenant2); when(publicationService.getPublicationDetails(CONSORTIUM_ID, publicationId)).thenReturn(pubDetails); when(publicationService.getPublicationResults(CONSORTIUM_ID, publicationId)).thenReturn(pubResultCollection); - when(objectMapper.convertValue(any(), eq(ObjectNode.class))).thenReturn(payload); // Use reflection to access the protected method in BaseSharingService Method method = SharingRoleService.class.getSuperclass() @@ -132,7 +248,8 @@ void shouldUpdateFailedTenantRole() throws NoSuchMethodException, InvocationTarg verify(publicationService).getPublicationDetails(CONSORTIUM_ID, publicationId); verify(publicationService, times(3)) .checkPublicationDetailsExists(CONSORTIUM_ID, publicationId); - verify(publicationService).publishRequest(CONSORTIUM_ID, expectedPubRequest); + verify(publicationService).publishRequest(CONSORTIUM_ID, expectedPubRequest1); + verify(publicationService).publishRequest(CONSORTIUM_ID, expectedPubRequest2); } // Negative cases @@ -140,7 +257,7 @@ void shouldUpdateFailedTenantRole() throws NoSuchMethodException, InvocationTarg void shouldThrowErrorForNotEqualRoleIdWithPayloadId() { var request = getMockDataObject(SHARING_ROLE_REQUEST_SAMPLE, SharingRoleRequest.class); request.setRoleId(UUID.randomUUID()); - var payload = createPayloadForRole(); + var payload = createPayloadForRole(UUID.randomUUID().toString(), request.getRoleName()); when(objectMapper.convertValue(any(), eq(ObjectNode.class))).thenReturn(payload); diff --git a/src/test/java/org/folio/consortia/support/EntityUtils.java b/src/test/java/org/folio/consortia/support/EntityUtils.java index cda50b53..2866a4d6 100644 --- a/src/test/java/org/folio/consortia/support/EntityUtils.java +++ b/src/test/java/org/folio/consortia/support/EntityUtils.java @@ -12,7 +12,6 @@ import org.folio.consortia.domain.dto.PublicationResultCollection; import org.folio.consortia.domain.dto.PublicationStatus; import org.folio.consortia.domain.dto.SharingInstance; -import org.folio.consortia.domain.dto.SharingRoleDeleteResponse; import org.folio.consortia.domain.dto.Tenant; import org.folio.consortia.domain.dto.TenantCollection; import org.folio.consortia.domain.dto.TenantDetails.SetupStatusEnum; @@ -308,11 +307,6 @@ public static PublicationTenantRequestEntity createPublicationTenantRequestEntit return entity; } - public static SharingRoleDeleteResponse createSharingRoleResponseForDelete(UUID pcId) { - return new SharingRoleDeleteResponse().pcId(pcId); - } - - public static TenantCollection createTenantCollection(List tenants) { TenantCollection tenantCollection = new TenantCollection(); tenantCollection.setTenants(tenants); @@ -379,27 +373,27 @@ public static ObjectNode createPayloadForPolicy() { return mapper.convertValue(payload, ObjectNode.class); } - public static ObjectNode createPayloadForRole() { + public static ObjectNode createPayloadForRole(String roleId, String roleName) { Map payload = new HashMap<>(); - payload.put("id", "3844767a-8367-4926-9999-514c35840399"); - payload.put("name", "role names"); + payload.put("id", roleId); + payload.put("name", roleName); payload.put("type", "local"); ObjectMapper mapper = new ObjectMapper(); return mapper.convertValue(payload, ObjectNode.class); } - public static ObjectNode createPayloadForRoleCapabilitySets() { + public static ObjectNode createPayloadForRoleCapabilitySets(UUID roleId) { Map payload = new HashMap<>(); - payload.put("roleId", "4844767a-8367-4926-9999-514c35840399"); + payload.put("roleId", roleId); payload.put("capabilitySetNames", List.of("account_item.view", "account_item.create")); payload.put("type", "local"); ObjectMapper mapper = new ObjectMapper(); return mapper.convertValue(payload, ObjectNode.class); } - public static ObjectNode createPayloadForRoleCapabilities() { + public static ObjectNode createPayloadForRoleCapabilities(UUID roleId) { Map payload = new HashMap<>(); - payload.put("roleId", "5844767a-8367-4926-9999-514c35840399"); + payload.put("roleId", roleId); payload.put("capabilityNames", List.of("account_item.view", "account_item.create")); payload.put("type", "local"); ObjectMapper mapper = new ObjectMapper(); diff --git a/src/test/resources/mockdata/sharing_role_capabilities/sharing_role_capabilities_request.json b/src/test/resources/mockdata/sharing_role_capabilities/sharing_role_capabilities_request.json index a32eeb83..9ec0d8f6 100644 --- a/src/test/resources/mockdata/sharing_role_capabilities/sharing_role_capabilities_request.json +++ b/src/test/resources/mockdata/sharing_role_capabilities/sharing_role_capabilities_request.json @@ -1,5 +1,6 @@ { "roleId": "5844767a-8367-4926-9999-514c35840399", + "roleName": "don't panic", "url": "/roles/capabilities", "payload": { "roleId": "5844767a-8367-4926-9999-514c35840399", diff --git a/src/test/resources/mockdata/sharing_role_capabilities/sharing_role_capabilities_request_without_payload.json b/src/test/resources/mockdata/sharing_role_capabilities/sharing_role_capabilities_request_without_payload.json index be025d4b..acee7e76 100644 --- a/src/test/resources/mockdata/sharing_role_capabilities/sharing_role_capabilities_request_without_payload.json +++ b/src/test/resources/mockdata/sharing_role_capabilities/sharing_role_capabilities_request_without_payload.json @@ -1,4 +1,5 @@ { "roleId": "5844767a-8367-4926-9999-514c35840399", + "roleName": "don't panic", "url": "/roles" } diff --git a/src/test/resources/mockdata/sharing_role_capability_sets/sharing_role_capability_sets_request.json b/src/test/resources/mockdata/sharing_role_capability_sets/sharing_role_capability_sets_request.json index 44279872..e2ef5a4f 100644 --- a/src/test/resources/mockdata/sharing_role_capability_sets/sharing_role_capability_sets_request.json +++ b/src/test/resources/mockdata/sharing_role_capability_sets/sharing_role_capability_sets_request.json @@ -1,5 +1,6 @@ { "roleId": "4844767a-8367-4926-9999-514c35840399", + "roleName": "test", "url": "/roles/capability-sets", "payload": { "roleId": "4844767a-8367-4926-9999-514c35840399", diff --git a/src/test/resources/mockdata/sharing_role_capability_sets/sharing_role_capability_sets_request_without_payload.json b/src/test/resources/mockdata/sharing_role_capability_sets/sharing_role_capability_sets_request_without_payload.json index 70acf043..beaa581b 100644 --- a/src/test/resources/mockdata/sharing_role_capability_sets/sharing_role_capability_sets_request_without_payload.json +++ b/src/test/resources/mockdata/sharing_role_capability_sets/sharing_role_capability_sets_request_without_payload.json @@ -1,4 +1,5 @@ { "roleId": "4844767a-8367-4926-9999-514c35840399", + "roleName": "test", "url": "/roles" } diff --git a/src/test/resources/mockdata/sharing_roles/sharing_role_request.json b/src/test/resources/mockdata/sharing_roles/sharing_role_request.json index 55bef2cf..a703a381 100644 --- a/src/test/resources/mockdata/sharing_roles/sharing_role_request.json +++ b/src/test/resources/mockdata/sharing_roles/sharing_role_request.json @@ -1,9 +1,10 @@ { "roleId": "3844767a-8367-4926-9999-514c35840399", + "roleName": "don't panic", "url": "/roles", "payload": { "id": "3844767a-8367-4926-9999-514c35840399", - "name": "role names", + "name": "don't panic", "type": "local" } } diff --git a/src/test/resources/mockdata/sharing_roles/sharing_role_request_without_payload.json b/src/test/resources/mockdata/sharing_roles/sharing_role_request_without_payload.json index 284eb43d..0215d00e 100644 --- a/src/test/resources/mockdata/sharing_roles/sharing_role_request_without_payload.json +++ b/src/test/resources/mockdata/sharing_roles/sharing_role_request_without_payload.json @@ -1,4 +1,5 @@ { "roleId": "3844767a-8367-4926-9999-514c35840399", + "roleName": "don't panic", "url": "/roles" }