diff --git a/src/main/java/coop/libriciel/ipcore/configuration/RedisConfigurer.java b/src/main/java/coop/libriciel/ipcore/configuration/RedisConfigurer.java index 74e69047f171a2e67b271fc44474837e8d3801cd..2e4cd892a28176aa4379d65fe7cd11f05ae9d9c0 100644 --- a/src/main/java/coop/libriciel/ipcore/configuration/RedisConfigurer.java +++ b/src/main/java/coop/libriciel/ipcore/configuration/RedisConfigurer.java @@ -24,6 +24,7 @@ import coop.libriciel.ipcore.business.workflow.WorkflowBusinessService; import coop.libriciel.ipcore.services.auth.AuthServiceInterface; import coop.libriciel.ipcore.services.content.ContentServiceInterface; import coop.libriciel.ipcore.services.database.SubtypeRepository; +import coop.libriciel.ipcore.services.database.TenantRepository; import coop.libriciel.ipcore.services.externalsignature.ExternalSignatureInterface; import coop.libriciel.ipcore.services.ipng.IpngServiceInterface; import coop.libriciel.ipcore.services.mail.NotificationServiceInterface; @@ -84,6 +85,7 @@ public class RedisConfigurer { private final PlatformTransactionManager platformTransactionManager; private final SecureMailServiceInterface secureMailService; private final SignatureReportBusinessListenerService signatureReportBusinessListenerService; + private final TenantRepository tenantRepository; private final WebsocketService websocketService; private final WorkflowBusinessService workflowBusinessService; @@ -94,7 +96,7 @@ public class RedisConfigurer { ExternalSignatureInterface externalSignatureService, PlatformTransactionManager platformTransactionManager, SecureMailServiceInterface secureMailService, - SignatureReportBusinessListenerService signatureReportBusinessListenerService, + SignatureReportBusinessListenerService signatureReportBusinessListenerService, TenantRepository tenantRepository, WebsocketService websocketService, WorkflowBusinessService workflowBusinessService) { this.authService = authService; @@ -103,6 +105,7 @@ public class RedisConfigurer { this.platformTransactionManager = platformTransactionManager; this.secureMailService = secureMailService; this.signatureReportBusinessListenerService = signatureReportBusinessListenerService; + this.tenantRepository = tenantRepository; this.websocketService = websocketService; this.workflowBusinessService = workflowBusinessService; } @@ -145,6 +148,7 @@ public class RedisConfigurer { authService, contentService, notificationController, + tenantRepository, platformTransactionManager, subtypeRepository, websocketService, diff --git a/src/main/java/coop/libriciel/ipcore/services/redis/RedisMessageListenerService.java b/src/main/java/coop/libriciel/ipcore/services/redis/RedisMessageListenerService.java index e935de6ae38739c07c81d7a1ae9109489ada6d33..1648c83fee77d227c2a22cc568966a8d7c71e7e9 100644 --- a/src/main/java/coop/libriciel/ipcore/services/redis/RedisMessageListenerService.java +++ b/src/main/java/coop/libriciel/ipcore/services/redis/RedisMessageListenerService.java @@ -37,14 +37,13 @@ import coop.libriciel.ipcore.model.workflow.ipWorkflow.NotifiedIpWorkflowTask; import coop.libriciel.ipcore.services.auth.AuthServiceInterface; import coop.libriciel.ipcore.services.content.ContentServiceInterface; import coop.libriciel.ipcore.services.database.SubtypeRepository; +import coop.libriciel.ipcore.services.database.TenantRepository; import coop.libriciel.ipcore.services.mail.NotificationServiceInterface; import coop.libriciel.ipcore.services.websocket.WebsocketService; import coop.libriciel.ipcore.services.workflow.WorkflowServiceInterface; import coop.libriciel.ipcore.utils.*; import lombok.extern.log4j.Log4j2; import org.apache.commons.lang3.StringUtils; -import org.apache.commons.lang3.math.NumberUtils; -import org.jetbrains.annotations.NotNull; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.MessageListener; import org.springframework.stereotype.Service; @@ -54,11 +53,7 @@ import org.springframework.transaction.support.TransactionTemplate; import java.io.IOException; import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; -import java.util.stream.Stream; -import static coop.libriciel.ipcore.model.externalsignature.ExternalSignatureParams.*; import static coop.libriciel.ipcore.model.workflow.Action.*; import static coop.libriciel.ipcore.model.workflow.NotificationType.NEW_ON_DESK; import static coop.libriciel.ipcore.model.workflow.State.*; @@ -80,6 +75,7 @@ public class RedisMessageListenerService implements MessageListener { private final AuthServiceInterface authService; private final ContentServiceInterface contentService; private final NotificationServiceInterface notificationService; + private final TenantRepository tenantRepository; private final TransactionTemplate transactionTemplate; private final SubtypeRepository subtypeRepository; private final WebsocketService websocketService; @@ -90,6 +86,7 @@ public class RedisMessageListenerService implements MessageListener { public RedisMessageListenerService(AuthServiceInterface authService, ContentServiceInterface contentService, NotificationServiceInterface notificationService, + TenantRepository tenantRepository, PlatformTransactionManager platformTransactionManager, SubtypeRepository subtypeRepository, WebsocketService websocketService, @@ -98,6 +95,7 @@ public class RedisMessageListenerService implements MessageListener { this.authService = authService; this.contentService = contentService; this.notificationService = notificationService; + this.tenantRepository = tenantRepository; this.transactionTemplate = new TransactionTemplate(platformTransactionManager); this.subtypeRepository = subtypeRepository; this.websocketService = websocketService; @@ -130,11 +128,8 @@ public class RedisMessageListenerService implements MessageListener { log.debug("Message received folder:{}", folder); - Subtype subtype = subtypeRepository - .findById(folder.getSubtype().getId()) - .orElseThrow(() -> new LocalizedStatusException(NOT_FOUND, "message.unknown_subtype_id")); - - Tenant tenant = subtype.getTenant(); + String tenantId = task.getMetadata().get("tenantId"); + Tenant tenant = tenantRepository.findById(tenantId).get(); this.sendInternalNotification(tenant, task); @@ -146,108 +141,114 @@ public class RedisMessageListenerService implements MessageListener { // Tests for auto SEAL or EXTERNAL_SIGNATURE - boolean isExternalSignature = task.getAction() == EXTERNAL_SIGNATURE; - boolean canPerformExternalSignature = subtype.isExternalSignatureAutomatic(); - boolean doPerformAutoExternalSignature = isExternalSignature && canPerformExternalSignature; - - boolean isSeal = task.getAction() == SEAL; - boolean isNotValidated = task.getState() != VALIDATED; - boolean isSealAutomatic = subtype.isSealAutomatic(); - boolean doPerformAutoSeal = isSeal && isNotValidated && isSealAutomatic; - - if (doPerformAutoExternalSignature || doPerformAutoSeal) { + if (folder.getSubtype() != null) { + Subtype subtype = subtypeRepository + .findById(folder.getSubtype().getId()) + .orElseThrow(() -> new LocalizedStatusException(NOT_FOUND, "message.unknown_subtype_id")); - // Content id is absent from the Redis message, we have to fetch the folder again - folder = workflowService.getFolder(folder.getId(), tenant.getId(), true); - contentService.populateFolderWithAllDocumentTypes(folder); + boolean isExternalSignature = task.getAction() == EXTERNAL_SIGNATURE; + boolean canPerformExternalSignature = subtype.isExternalSignatureAutomatic(); + boolean doPerformAutoExternalSignature = isExternalSignature && canPerformExternalSignature; - Desk validatorDesk = task.getDesks().stream() - .findFirst() - .map(DeskRepresentation::getId) - .map(id -> authService.findDeskByIdNoException(tenant.getId(), id)) - .orElseThrow(() -> new LocalizedStatusException(NOT_FOUND, "message.unknown_desk_id")); + boolean isSeal = task.getAction() == SEAL; + boolean isNotValidated = task.getState() != VALIDATED; + boolean isSealAutomatic = subtype.isSealAutomatic(); + boolean doPerformAutoSeal = isSeal && isNotValidated && isSealAutomatic; - if (doPerformAutoSeal) { + if (doPerformAutoExternalSignature || doPerformAutoSeal) { - final Folder finalFolder = folder; - // The transaction prevent a LazyLoadingException (required since we are not in the context of a request session) - transactionTemplate.execute((TransactionCallback<Void>) transactionStatus -> { - workflowBusinessService.performRetryableAutoSeal(tenant, validatorDesk, finalFolder, task); - return null; - }); + // Content id is absent from the Redis message, we have to fetch the folder again + folder = workflowService.getFolder(folder.getId(), tenant.getId(), true); + contentService.populateFolderWithAllDocumentTypes(folder); - // We don't want to notify anyone here, - // since the action was already done. + Desk validatorDesk = task.getDesks().stream() + .findFirst() + .map(DeskRepresentation::getId) + .map(id -> authService.findDeskByIdNoException(tenant.getId(), id)) + .orElseThrow(() -> new LocalizedStatusException(NOT_FOUND, "message.unknown_desk_id")); - } else { // Auto external signature + if (doPerformAutoSeal) { - // Check appropriate metadata presence + final Folder finalFolder = folder; + // The transaction prevent a LazyLoadingException (required since we are not in the context of a request session) + transactionTemplate.execute((TransactionCallback<Void>) transactionStatus -> { + workflowBusinessService.performRetryableAutoSeal(tenant, validatorDesk, finalFolder, task); + return null; + }); - long externalSignatureCount = FolderUtils.countStepsWithAction(folder.getStepList(), EXTERNAL_SIGNATURE); - Map<Long, SignRequestMember> signRequestMemberMap = CryptoUtils.getExternalSignatureMetadataMap(folder.getMetadata()); + // We don't want to notify anyone here, + // since the action was already done. - boolean doesHaveDefaultIndex = signRequestMemberMap.containsKey(0L); - boolean doesHaveFirstIndex = signRequestMemberMap.containsKey(1L); - boolean leapsIndex = !CollectionUtils.isSequential(signRequestMemberMap.keySet()); - boolean incorrectIndexSequence = leapsIndex || !doesHaveFirstIndex; - if (incorrectIndexSequence && !doesHaveDefaultIndex){ - log.warn("External signature tag indexes have missing values. Cancelling..."); - return; - } + } else { // Auto external signature - if (signRequestMemberMap.size() == externalSignatureCount) { - log.debug("External signature configurations matches the total step count. Automatically set one per step."); + // Check appropriate metadata presence - Long currentExternalSignatureIndex = FolderUtils.getCurrentExternalSignatureIndex(folder.getStepList()); - SignRequestMember currentMemberConfiguration = Optional - .ofNullable(signRequestMemberMap.get(currentExternalSignatureIndex)) - .orElse(signRequestMemberMap.get(0L)); + long externalSignatureCount = FolderUtils.countStepsWithAction(folder.getStepList(), EXTERNAL_SIGNATURE); + Map<Long, SignRequestMember> signRequestMemberMap = CryptoUtils.getExternalSignatureMetadataMap(folder.getMetadata()); - if (currentMemberConfiguration == null) { - log.warn("No external signature found for the current step. Cancelling..."); + boolean doesHaveDefaultIndex = signRequestMemberMap.containsKey(0L); + boolean doesHaveFirstIndex = signRequestMemberMap.containsKey(1L); + boolean leapsIndex = !CollectionUtils.isSequential(signRequestMemberMap.keySet()); + boolean incorrectIndexSequence = leapsIndex || !doesHaveFirstIndex; + if (incorrectIndexSequence && !doesHaveDefaultIndex){ + log.warn("External signature tag indexes have missing values. Cancelling..."); return; } - if (!CryptoUtils.isConfigurationComplete(currentMemberConfiguration)) { - log.warn("Incomplete external signature configuration. Cancelling..."); - return; - } - - ExternalSignatureParams externalSignatureParams = new ExternalSignatureParams( - folder.getName(), - task.getId(), - singletonList(currentMemberConfiguration), - new HashMap<>(), - new ArrayList<>() - ); - workflowBusinessService.performRetryableAutoExternalSignature(tenant, validatorDesk, folder, task, externalSignatureParams); - - } else if (externalSignatureCount == 1) { - log.debug("External signature configurations mapped to a single step. Every conf to the single step."); - if (signRequestMemberMap.values().stream().anyMatch(conf -> !CryptoUtils.isConfigurationComplete(conf))) { - log.warn("One of the external signature configuration is incomplete. Cancelling..."); + if (signRequestMemberMap.size() == externalSignatureCount) { + log.debug("External signature configurations matches the total step count. Automatically set one per step."); + + Long currentExternalSignatureIndex = FolderUtils.getCurrentExternalSignatureIndex(folder.getStepList()); + SignRequestMember currentMemberConfiguration = Optional + .ofNullable(signRequestMemberMap.get(currentExternalSignatureIndex)) + .orElse(signRequestMemberMap.get(0L)); + + if (currentMemberConfiguration == null) { + log.warn("No external signature found for the current step. Cancelling..."); + return; + } + if (!CryptoUtils.isConfigurationComplete(currentMemberConfiguration)) { + log.warn("Incomplete external signature configuration. Cancelling..."); + return; + } + + ExternalSignatureParams externalSignatureParams = new ExternalSignatureParams( + folder.getName(), + task.getId(), + singletonList(currentMemberConfiguration), + new HashMap<>(), + new ArrayList<>() + ); + workflowBusinessService.performRetryableAutoExternalSignature(tenant, validatorDesk, folder, task, externalSignatureParams); + + } else if (externalSignatureCount == 1) { + log.debug("External signature configurations mapped to a single step. Every conf to the single step."); + + if (signRequestMemberMap.values().stream().anyMatch(conf -> !CryptoUtils.isConfigurationComplete(conf))) { + log.warn("One of the external signature configuration is incomplete. Cancelling..."); + return; + } + + ExternalSignatureParams externalSignatureParams = new ExternalSignatureParams( + folder.getName(), + task.getId(), + signRequestMemberMap.values(), + new HashMap<>(), + new ArrayList<>() + ); + workflowBusinessService.performRetryableAutoExternalSignature(tenant, validatorDesk, folder, task, externalSignatureParams); + + } else { + log.warn("External signature configuration mismatch: {} conf(s) for {} steps. Cancelling..."); return; } - ExternalSignatureParams externalSignatureParams = new ExternalSignatureParams( - folder.getName(), - task.getId(), - signRequestMemberMap.values(), - new HashMap<>(), - new ArrayList<>() - ); - workflowBusinessService.performRetryableAutoExternalSignature(tenant, validatorDesk, folder, task, externalSignatureParams); - - } else { - log.warn("External signature configuration mismatch: {} conf(s) for {} steps. Cancelling..."); - return; + // We don't want to notify anyone here, + // since the action was already done. } - // We don't want to notify anyone here, - // since the action was already done. + return; } - - return; } notify(tenant, folder, task);