Skip to content

Commit

Permalink
Fix #956: Respect provider name in queries (#957)
Browse files Browse the repository at this point in the history
  • Loading branch information
jnpsk authored Dec 18, 2023
1 parent 1ddfe6d commit 3a54da3
Show file tree
Hide file tree
Showing 16 changed files with 249 additions and 93 deletions.
6 changes: 6 additions & 0 deletions enrollment-server-onboarding-common/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
Expand Up @@ -40,18 +40,20 @@ public interface DocumentResultRepository extends CrudRepository<DocumentResultE
*/
@Query("SELECT doc FROM DocumentResultEntity doc WHERE" +
" doc.documentVerification.status = com.wultra.app.enrollmentserver.model.enumeration.DocumentStatus.UPLOAD_IN_PROGRESS" +
" AND doc.documentVerification.providerName = :providerName " +
" AND doc.extractedData IS NULL " +
" ORDER BY doc.timestampCreated ASC")
Stream<DocumentResultEntity> streamAllInProgressDocumentSubmits();
Stream<DocumentResultEntity> streamAllInProgressDocumentSubmits(String providerName);

/**
* @return All not finished document submit verifications (upload is in progress and verification id exists)
*/
@Query("SELECT doc FROM DocumentResultEntity doc WHERE" +
" doc.documentVerification.status = com.wultra.app.enrollmentserver.model.enumeration.DocumentStatus.UPLOAD_IN_PROGRESS" +
" AND doc.documentVerification.providerName = :providerName " +
" AND doc.documentVerification.verificationId IS NOT NULL" +
" ORDER BY doc.timestampCreated ASC")
Stream<DocumentResultEntity> streamAllInProgressDocumentSubmitVerifications();
Stream<DocumentResultEntity> streamAllInProgressDocumentSubmitVerifications(String providerName);

/**
* @return All document results for the specified document verification and processing phase
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* PowerAuth Enrollment Server
* Copyright (C) 2023 Wultra s.r.o.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.wultra.app.onboardingserver.common;

import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class EnrollmentServerOnboardingCommonTestApplication {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* PowerAuth Enrollment Server
* Copyright (C) 2023 Wultra s.r.o.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.wultra.app.onboardingserver.common.database;


import com.wultra.app.onboardingserver.common.database.entity.DocumentResultEntity;
import com.wultra.app.onboardingserver.common.database.entity.DocumentVerificationEntity;
import jakarta.transaction.Transactional;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.jdbc.Sql;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Test for {@link DocumentResultRepository}.
*
* @author Jan Pesek, [email protected]
*/
@DataJpaTest
@ActiveProfiles("test")
@Transactional
class DocumentResultRepositoryTest {

@Autowired
private DocumentResultRepository tested;

@Test
@Sql
void testStreamAllInProgressDocumentSubmits() {
assertThat(tested.streamAllInProgressDocumentSubmits("mock"))
.extracting(DocumentResultEntity::getDocumentVerification)
.extracting(DocumentVerificationEntity::getProviderName)
.containsOnly("mock")
.hasSize(1);
}

@Test
@Sql
void testStreamAllInProgressDocumentSubmitVerifications() {
assertThat(tested.streamAllInProgressDocumentSubmitVerifications("mock"))
.extracting(DocumentResultEntity::getDocumentVerification)
.extracting(DocumentVerificationEntity::getProviderName)
.containsOnly("mock")
.hasSize(1);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
spring.datasource.url=jdbc:h2:mem:testdb;DB_CLOSE_ON_EXIT=FALSE
spring.datasource.username=sa
spring.datasource.password=password
spring.datasource.driver-class-name=org.h2.Driver
spring.jpa.hibernate.ddl-auto=create
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-- Documents that have been already submitted and data were extracted (multiple providers).
INSERT INTO es_identity_verification(id, activation_id, user_id, process_id, status, phase, timestamp_created, timestamp_last_updated) VALUES
('v3', 'a3', 'u3', 'p3', 'IN_PROGRESS', 'DOCUMENT_UPLOAD', now(), now()),
('v4', 'a4', 'u4', 'p4', 'IN_PROGRESS', 'DOCUMENT_UPLOAD', now(), now());

INSERT INTO es_document_verification(id, provider_name, activation_id, identity_verification_id, verification_id, type, status, filename, used_for_verification, timestamp_created, timestamp_last_updated) VALUES
('d3', 'foreign', 'a3', 'v3', 'verification1', 'ID_CARD', 'UPLOAD_IN_PROGRESS', 'f3', true, now(), now()),
('d4', 'mock', 'a4', 'v4', 'verification2', 'ID_CARD', 'UPLOAD_IN_PROGRESS', 'f4', true, now(), now());

INSERT INTO es_document_result(id, document_verification_id, phase, extracted_data, timestamp_created) VALUES
(3, 'd3', 'UPLOAD', '{extracted_data}', now()),
(4, 'd4', 'UPLOAD', '{extracted_data}', now());
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
-- Documents that have not been submitted yet (multiple providers).
INSERT INTO es_identity_verification(id, activation_id, user_id, process_id, status, phase, timestamp_created, timestamp_last_updated) VALUES
('v1', 'a1', 'u1', 'p1', 'IN_PROGRESS', 'DOCUMENT_UPLOAD', now(), now()),
('v2', 'a2', 'u2', 'p2', 'IN_PROGRESS', 'DOCUMENT_UPLOAD', now(), now());

INSERT INTO es_document_verification(id, provider_name, activation_id, identity_verification_id, type, status, filename, used_for_verification, timestamp_created, timestamp_last_updated) VALUES
('d1', 'foreign', 'a1', 'v1', 'ID_CARD', 'UPLOAD_IN_PROGRESS', 'f1', true, now(), now()),
('d2', 'mock', 'a2', 'v2', 'ID_CARD', 'UPLOAD_IN_PROGRESS', 'f2', true, now(), now());

INSERT INTO es_document_result(id, document_verification_id, phase, timestamp_created) VALUES
(1, 'd1', 'UPLOAD', now()),
(2, 'd2', 'UPLOAD', now());
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import com.wultra.app.onboardingserver.common.database.entity.DocumentVerificationEntity;
import com.wultra.app.enrollmentserver.model.enumeration.DocumentStatus;
import com.wultra.app.enrollmentserver.model.integration.OwnerId;
import com.wultra.app.onboardingserver.configuration.IdentityVerificationConfig;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -37,6 +39,7 @@
* @author Lukas Lukovsky, [email protected]
*/
@Service
@AllArgsConstructor
public class DocumentProcessingBatchService {

private static final Logger logger = LoggerFactory.getLogger(DocumentProcessingBatchService.class);
Expand All @@ -45,26 +48,15 @@ public class DocumentProcessingBatchService {

private final DocumentProcessingService documentProcessingService;

/**
* Service constructor.
* @param documentResultRepository Document verification result repository.
* @param documentProcessingService Document processing service.
*/
@Autowired
public DocumentProcessingBatchService(
DocumentResultRepository documentResultRepository,
DocumentProcessingService documentProcessingService) {
this.documentResultRepository = documentResultRepository;
this.documentProcessingService = documentProcessingService;
}
private final IdentityVerificationConfig identityVerificationConfig;

/**
* Checks in progress document submits on current provider status and data result
*/
@Transactional
public void checkInProgressDocumentSubmits() {
AtomicInteger countFinished = new AtomicInteger(0);
try (Stream<DocumentResultEntity> stream = documentResultRepository.streamAllInProgressDocumentSubmits()) {
try (Stream<DocumentResultEntity> stream = documentResultRepository.streamAllInProgressDocumentSubmits(identityVerificationConfig.getDocumentVerificationProvider())) {
stream.forEach(docResult -> {
DocumentVerificationEntity docVerification = docResult.getDocumentVerification();
final OwnerId ownerId = new OwnerId();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@
import com.wultra.app.onboardingserver.common.service.AuditService;
import com.wultra.app.onboardingserver.common.service.CommonOnboardingService;
import com.wultra.app.onboardingserver.api.errorhandling.DocumentVerificationException;
import com.wultra.app.onboardingserver.configuration.IdentityVerificationConfig;
import com.wultra.app.onboardingserver.impl.service.IdentityVerificationService;
import com.wultra.app.onboardingserver.api.provider.DocumentVerificationProvider;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -49,6 +51,7 @@
* @author Lukas Lukovsky, [email protected]
*/
@Service
@AllArgsConstructor
public class VerificationProcessingBatchService {

private static final Logger logger = LoggerFactory.getLogger(VerificationProcessingBatchService.class);
Expand All @@ -67,42 +70,15 @@ public class VerificationProcessingBatchService {

private final CommonOnboardingService commonOnboardingService;

/**
* Service constructor.
* @param documentResultRepository Document verification result repository.
* @param documentVerificationProvider Document verification provider.
* @param identityVerificationRepository Identity verification repository.
* @param identityVerificationService Identity verification service.
* @param verificationProcessingService Verification processing service.
* @param auditService Audit service.
* @param commonOnboardingService Onboarding process service (common).
*/
@Autowired
public VerificationProcessingBatchService(
final DocumentResultRepository documentResultRepository,
final DocumentVerificationProvider documentVerificationProvider,
final IdentityVerificationRepository identityVerificationRepository,
final IdentityVerificationService identityVerificationService,
final VerificationProcessingService verificationProcessingService,
final AuditService auditService,
final CommonOnboardingService commonOnboardingService) {

this.documentResultRepository = documentResultRepository;
this.identityVerificationRepository = identityVerificationRepository;
this.documentVerificationProvider = documentVerificationProvider;
this.identityVerificationService = identityVerificationService;
this.verificationProcessingService = verificationProcessingService;
this.auditService = auditService;
this.commonOnboardingService = commonOnboardingService;
}
private final IdentityVerificationConfig identityVerificationConfig;

/**
* Checks document submit verifications
*/
@Transactional
public void checkDocumentSubmitVerifications() {
AtomicInteger countFinished = new AtomicInteger(0);
try (Stream<DocumentResultEntity> stream = documentResultRepository.streamAllInProgressDocumentSubmitVerifications()) {
try (Stream<DocumentResultEntity> stream = documentResultRepository.streamAllInProgressDocumentSubmitVerifications(identityVerificationConfig.getDocumentVerificationProvider())) {
stream.forEach(docResult -> {
DocumentVerificationEntity docVerification = docResult.getDocumentVerification();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import com.wultra.app.enrollmentserver.model.integration.OwnerId;
import com.wultra.app.onboardingserver.common.database.entity.IdentityVerificationEntity;
import com.wultra.app.onboardingserver.common.errorhandling.IdentityVerificationException;
import com.wultra.app.onboardingserver.configuration.IdentityVerificationConfig;
import com.wultra.app.onboardingserver.impl.service.IdentityVerificationService;
import com.wultra.app.onboardingserver.statemachine.EnrollmentStateProvider;
import com.wultra.app.onboardingserver.statemachine.consts.EventHeaderName;
Expand All @@ -27,6 +28,7 @@
import com.wultra.app.onboardingserver.statemachine.enums.OnboardingState;
import com.wultra.app.onboardingserver.statemachine.interceptor.CustomStateMachineInterceptor;
import jakarta.annotation.Nullable;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.messaging.Message;
Expand All @@ -53,6 +55,7 @@
*/
@Service
@Slf4j
@AllArgsConstructor
@ConditionalOnProperty(value = "enrollment-server-onboarding.identity-verification.enabled", havingValue = "true")
public class StateMachineService {

Expand All @@ -66,27 +69,7 @@ public class StateMachineService {

private final TransactionTemplate transactionTemplate;

/**
* Constructor.
*
* @param enrollmentStateProvider Enrollment state provider.
* @param stateMachineFactory State machine factory.
* @param stateMachineInterceptor State machine interceptor.
* @param identityVerificationService Identity verification service.
*/
public StateMachineService(
final EnrollmentStateProvider enrollmentStateProvider,
final StateMachineFactory<OnboardingState, OnboardingEvent> stateMachineFactory,
final CustomStateMachineInterceptor stateMachineInterceptor,
final IdentityVerificationService identityVerificationService,
final TransactionTemplate transactionTemplate
) {
this.enrollmentStateProvider = enrollmentStateProvider;
this.stateMachineFactory = stateMachineFactory;
this.stateMachineInterceptor = stateMachineInterceptor;
this.identityVerificationService = identityVerificationService;
this.transactionTemplate = transactionTemplate;
}
private final IdentityVerificationConfig identityVerificationConfig;

@Transactional
public StateMachine<OnboardingState, OnboardingEvent> processStateMachineEvent(OwnerId ownerId, String processId, OnboardingEvent event)
Expand Down Expand Up @@ -144,23 +127,25 @@ public Message<OnboardingEvent> createMessage(OwnerId ownerId, String processId,
public void changeMachineStatesInBatch() {
final AtomicInteger countFinished = new AtomicInteger(0);
try (Stream<IdentityVerificationEntity> stream = identityVerificationService.streamAllIdentityVerificationsToChangeState().parallel()) {
stream.forEach(identityVerification -> {
final String processId = identityVerification.getProcessId();
final OwnerId ownerId = new OwnerId();
ownerId.setActivationId(identityVerification.getActivationId());
ownerId.setUserId(identityVerification.getUserId());
logger.debug("Changing state of machine for process ID: {}", processId);

transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
transactionTemplate.executeWithoutResult(status -> {
try {
processStateMachineEvent(ownerId, processId, OnboardingEvent.EVENT_NEXT_STATE);
countFinished.incrementAndGet();
} catch (IdentityVerificationException e) {
logger.warn("Unable to change state for process ID: {}", processId, e);
}
});
});
stream.filter(identityVerification -> identityVerification.getDocumentVerifications().stream()
.anyMatch(doc -> identityVerificationConfig.getDocumentVerificationProvider().equals(doc.getProviderName())))
.forEach(identityVerification -> {
final String processId = identityVerification.getProcessId();
final OwnerId ownerId = new OwnerId();
ownerId.setActivationId(identityVerification.getActivationId());
ownerId.setUserId(identityVerification.getUserId());
logger.debug("Changing state of machine for process ID: {}", processId);

transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
transactionTemplate.executeWithoutResult(status -> {
try {
processStateMachineEvent(ownerId, processId, OnboardingEvent.EVENT_NEXT_STATE);
countFinished.incrementAndGet();
} catch (IdentityVerificationException e) {
logger.warn("Unable to change state for process ID: {}", processId, e);
}
});
});
}
if (countFinished.get() > 0) {
logger.debug("Changed state of {} identity verifications", countFinished.get());
Expand Down
Loading

0 comments on commit 3a54da3

Please sign in to comment.