diff --git a/deploy/template.yaml b/deploy/template.yaml index c1a2fefc6d..ceae6419d3 100644 --- a/deploy/template.yaml +++ b/deploy/template.yaml @@ -827,7 +827,6 @@ Resources: ENVIRONMENT: !Sub "${Environment}" POWERTOOLS_SERVICE_NAME: !Sub initialise-ipv-session-${Environment} IPV_SESSIONS_TABLE_NAME: !Ref SessionsTable - USER_ISSUED_CREDENTIALS_TABLE_NAME: !Ref UserIssuedCredentialsV2Table SQS_AUDIT_EVENT_QUEUE_URL: !ImportValue AuditEventQueueUrl CLIENT_OAUTH_SESSIONS_TABLE_NAME: !Ref ClientOAuthSessionsTable VpcConfig: @@ -1243,7 +1242,6 @@ Resources: IPV_SESSIONS_TABLE_NAME: !Ref SessionsTable CRI_RESPONSE_TABLE_NAME: !Ref CRIResponseTable CLIENT_OAUTH_SESSIONS_TABLE_NAME: !Ref ClientOAuthSessionsTable - USER_ISSUED_CREDENTIALS_TABLE_NAME: !Ref UserIssuedCredentialsV2Table SESSION_CREDENTIALS_TABLE_NAME: !Ref SessionCredentialsTable VpcConfig: SubnetIds: @@ -1262,8 +1260,8 @@ Resources: - DynamoDBReadPolicy: TableName: !Ref CRIResponseTable - DynamoDBReadPolicy: - TableName: !Ref UserIssuedCredentialsV2Table - - DynamoDBReadPolicy: + TableName: !Ref SessionCredentialsTable + - DynamoDBWritePolicy: TableName: !Ref SessionCredentialsTable - SSMParameterReadPolicy: ParameterName: !Sub ${Environment}/core/* @@ -1271,6 +1269,8 @@ Resources: SecretArn: !Sub arn:aws:secretsmanager:eu-west-2:*:secret:/${Environment}/core/self/ciConfig-* - AWSSecretsManagerGetSecretValuePolicy: SecretArn: !Sub arn:aws:secretsmanager:eu-west-2:*:secret:/${Environment}/core/cimitApi/apiKey-* + - AWSSecretsManagerGetSecretValuePolicy: + SecretArn: !Sub arn:aws:secretsmanager:eu-west-2:*:secret:/${Environment}/core/evcs/apiKey-* - Statement: - Sid: EnforceStayinSpecificVpc Effect: Allow @@ -1743,7 +1743,6 @@ Resources: ENVIRONMENT: !Sub "${Environment}" POWERTOOLS_SERVICE_NAME: !Sub evaluate-gpg45-scores-${Environment} IPV_SESSIONS_TABLE_NAME: !Ref SessionsTable - USER_ISSUED_CREDENTIALS_TABLE_NAME: !Ref UserIssuedCredentialsV2Table CLIENT_OAUTH_SESSIONS_TABLE_NAME: !Ref ClientOAuthSessionsTable SESSION_CREDENTIALS_TABLE_NAME: !Ref SessionCredentialsTable SQS_AUDIT_EVENT_QUEUE_URL: !ImportValue AuditEventQueueUrl @@ -1925,7 +1924,6 @@ Resources: ENVIRONMENT: !Sub "${Environment}" POWERTOOLS_SERVICE_NAME: !Sub check-existing-identity-${Environment} IPV_SESSIONS_TABLE_NAME: !Ref SessionsTable - USER_ISSUED_CREDENTIALS_TABLE_NAME: !Ref UserIssuedCredentialsV2Table SESSION_CREDENTIALS_TABLE_NAME: !Ref SessionCredentialsTable CLIENT_OAUTH_SESSIONS_TABLE_NAME: !Ref ClientOAuthSessionsTable CRI_RESPONSE_TABLE_NAME: !Ref CRIResponseTable @@ -1961,8 +1959,6 @@ Resources: KeyId: !Ref DynamoDBKmsKey - DynamoDBCrudPolicy: TableName: !Ref SessionsTable - - DynamoDBCrudPolicy: - TableName: !Ref UserIssuedCredentialsV2Table - DynamoDBCrudPolicy: TableName: !Ref CRIResponseTable - DynamoDBReadPolicy: @@ -2018,7 +2014,6 @@ Resources: Environment: # checkov:skip=CKV_AWS_173: These environment variables do not require encryption. Variables: - USER_ISSUED_CREDENTIALS_TABLE_NAME: !Ref UserIssuedCredentialsV2Table CRI_RESPONSE_TABLE_NAME: !Ref CRIResponseTable ENVIRONMENT: !Sub "${Environment}" POWERTOOLS_SERVICE_NAME: !Sub process-async-cri-credential-${Environment} @@ -2045,8 +2040,6 @@ Resources: - Fn::ImportValue: !Sub ${VpcStackName}-VpcId - KMSDecryptPolicy: KeyId: !Ref DynamoDBKmsKey - - DynamoDBWritePolicy: - TableName: !Ref UserIssuedCredentialsV2Table - DynamoDBReadPolicy: TableName: !Ref CRIResponseTable - DynamoDBWritePolicy: @@ -2377,7 +2370,6 @@ Resources: ENVIRONMENT: !Sub "${Environment}" POWERTOOLS_SERVICE_NAME: !Sub store-identity-${Environment} SESSION_CREDENTIALS_TABLE_NAME: !Ref SessionCredentialsTable - USER_ISSUED_CREDENTIALS_TABLE_NAME: !Ref UserIssuedCredentialsV2Table IPV_SESSIONS_TABLE_NAME: !Ref SessionsTable CLIENT_OAUTH_SESSIONS_TABLE_NAME: !Ref ClientOAuthSessionsTable SQS_AUDIT_EVENT_QUEUE_URL: !ImportValue AuditEventQueueUrl @@ -2416,8 +2408,6 @@ Resources: SecretArn: !Sub arn:aws:secretsmanager:eu-west-2:*:secret:/${Environment}/core/evcs/apiKey-* - SQSSendMessagePolicy: QueueName: !ImportValue AuditEventQueueName - - DynamoDBCrudPolicy: - TableName: !Ref UserIssuedCredentialsV2Table - DynamoDBReadPolicy: TableName: !Ref SessionCredentialsTable - DynamoDBReadPolicy: @@ -2462,7 +2452,6 @@ Resources: IPV_SESSIONS_TABLE_NAME: !Ref SessionsTable SESSION_CREDENTIALS_TABLE_NAME: !Ref SessionCredentialsTable CLIENT_OAUTH_SESSIONS_TABLE_NAME: !Ref ClientOAuthSessionsTable - USER_ISSUED_CREDENTIALS_TABLE_NAME: !Ref UserIssuedCredentialsV2Table CRI_RESPONSE_TABLE_NAME: !Ref CRIResponseTable VpcConfig: SubnetIds: @@ -2505,8 +2494,6 @@ Resources: TableName: !Ref SessionsTable - DynamoDBReadPolicy: TableName: !Ref ClientOAuthSessionsTable - - DynamoDBCrudPolicy: - TableName: !Ref UserIssuedCredentialsV2Table - DynamoDBCrudPolicy: TableName: !Ref CRIResponseTable AutoPublishAlias: live diff --git a/lambdas/check-existing-identity/src/main/java/uk/gov/di/ipv/core/checkexistingidentity/CheckExistingIdentityHandler.java b/lambdas/check-existing-identity/src/main/java/uk/gov/di/ipv/core/checkexistingidentity/CheckExistingIdentityHandler.java index 2909d6e0a6..1fda820f81 100644 --- a/lambdas/check-existing-identity/src/main/java/uk/gov/di/ipv/core/checkexistingidentity/CheckExistingIdentityHandler.java +++ b/lambdas/check-existing-identity/src/main/java/uk/gov/di/ipv/core/checkexistingidentity/CheckExistingIdentityHandler.java @@ -13,7 +13,6 @@ import uk.gov.di.ipv.core.library.auditing.AuditEventTypes; import uk.gov.di.ipv.core.library.auditing.AuditEventUser; import uk.gov.di.ipv.core.library.auditing.extension.AuditExtensionGpg45ProfileMatched; -import uk.gov.di.ipv.core.library.auditing.extension.AuditExtensionsEvcsMigration; import uk.gov.di.ipv.core.library.auditing.restricted.AuditRestrictedDeviceInformation; import uk.gov.di.ipv.core.library.cimit.exception.CiRetrievalException; import uk.gov.di.ipv.core.library.config.ConfigurationVariable; @@ -22,7 +21,6 @@ import uk.gov.di.ipv.core.library.domain.JourneyRequest; import uk.gov.di.ipv.core.library.domain.JourneyResponse; import uk.gov.di.ipv.core.library.domain.VerifiableCredential; -import uk.gov.di.ipv.core.library.enums.EvcsVCState; import uk.gov.di.ipv.core.library.enums.Vot; import uk.gov.di.ipv.core.library.exception.EvcsServiceException; import uk.gov.di.ipv.core.library.exceptions.ConfigException; @@ -45,7 +43,6 @@ import uk.gov.di.ipv.core.library.service.ClientOAuthSessionDetailsService; import uk.gov.di.ipv.core.library.service.ConfigService; import uk.gov.di.ipv.core.library.service.CriResponseService; -import uk.gov.di.ipv.core.library.service.EvcsMigrationService; import uk.gov.di.ipv.core.library.service.EvcsService; import uk.gov.di.ipv.core.library.service.IpvSessionService; import uk.gov.di.ipv.core.library.service.UserIdentityService; @@ -60,12 +57,9 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; -import java.util.stream.Collectors; import static com.amazonaws.util.CollectionUtils.isNullOrEmpty; import static com.nimbusds.oauth2.sdk.http.HTTPResponse.SC_NOT_FOUND; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_READ_ENABLED; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_WRITE_ENABLED; import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.REPEAT_FRAUD_CHECK; import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.RESET_IDENTITY; import static uk.gov.di.ipv.core.library.domain.Cri.EXPERIAN_FRAUD; @@ -130,10 +124,8 @@ public class CheckExistingIdentityHandler private final ClientOAuthSessionDetailsService clientOAuthSessionDetailsService; private final CimitService cimitService; private final CimitUtilityService cimitUtilityService; - private final VerifiableCredentialService verifiableCredentialService; private final SessionCredentialsService sessionCredentialsService; private final EvcsService evcsService; - private final EvcsMigrationService evcsMigrationService; private final VotMatcher votMatcher; @SuppressWarnings({ @@ -152,7 +144,6 @@ public CheckExistingIdentityHandler( VerifiableCredentialService verifiableCredentialService, SessionCredentialsService sessionCredentialsService, EvcsService evcsService, - EvcsMigrationService evcsMigrationService, VotMatcher votMatcher) { this.configService = configService; this.userIdentityService = userIdentityService; @@ -162,10 +153,8 @@ public CheckExistingIdentityHandler( this.criResponseService = criResponseService; this.cimitService = cimitService; this.cimitUtilityService = cimitUtilityService; - this.verifiableCredentialService = verifiableCredentialService; this.sessionCredentialsService = sessionCredentialsService; this.evcsService = evcsService; - this.evcsMigrationService = evcsMigrationService; this.votMatcher = votMatcher; VcHelper.setConfigService(this.configService); } @@ -186,10 +175,8 @@ public CheckExistingIdentityHandler(ConfigService configService) { this.criResponseService = new CriResponseService(configService); this.cimitService = new CimitService(configService); this.cimitUtilityService = new CimitUtilityService(configService); - this.verifiableCredentialService = new VerifiableCredentialService(configService); this.sessionCredentialsService = new SessionCredentialsService(configService); this.evcsService = new EvcsService(configService); - this.evcsMigrationService = new EvcsMigrationService(configService); this.votMatcher = new VotMatcher( userIdentityService, new Gpg45ProfileEvaluator(), cimitUtilityService); @@ -197,9 +184,7 @@ public CheckExistingIdentityHandler(ConfigService configService) { } private record VerifiableCredentialBundle( - List credentials, - boolean hasEvcsIdentity, - boolean isPendingEvcsIdentity) { + List credentials, boolean isPendingIdentity) { private boolean isF2fIdentity() { return credentials.stream().anyMatch(vc -> vc.getCri().equals(F2F)); } @@ -257,19 +242,16 @@ private JourneyResponse getJourneyResponse( var userId = clientOAuthSessionItem.getUserId(); var govukSigninJourneyId = clientOAuthSessionItem.getGovukSigninJourneyId(); - AuditEventUser auditEventUser = + var auditEventUser = new AuditEventUser(userId, ipvSessionId, govukSigninJourneyId, ipAddress); - var evcsAccessToken = clientOAuthSessionItem.getEvcsAccessToken(); - var vcs = getVerifiableCredentials(userId, evcsAccessToken); - CriResponseItem f2fRequest = criResponseService.getFaceToFaceRequest(userId); - final boolean hasF2fVc = vcs.isF2fIdentity(); + var credentialBundle = + getCredentialBundle(userId, clientOAuthSessionItem.getEvcsAccessToken()); + var f2fRequest = criResponseService.getFaceToFaceRequest(userId); + final boolean hasF2fVc = credentialBundle.isF2fIdentity(); final boolean isF2FIncomplete = !Objects.isNull(f2fRequest) && !hasF2fVc; final boolean isF2FComplete = - !Objects.isNull(f2fRequest) - && hasF2fVc - && (!configService.enabled(EVCS_READ_ENABLED) - || vcs.isPendingEvcsIdentity()); + !Objects.isNull(f2fRequest) && hasF2fVc && credentialBundle.isPendingIdentity(); // If we want to prove or mitigate CIs for an identity we want to go for the lowest // strength that is acceptable to the caller. We can only prove/mitigate GPG45 @@ -288,8 +270,7 @@ private JourneyResponse getJourneyResponse( cimitService.getContraIndicators( clientOAuthSessionItem.getUserId(), govukSigninJourneyId, ipAddress); - Optional reproveIdentity = - Optional.ofNullable(clientOAuthSessionItem.getReproveIdentity()); + var reproveIdentity = Optional.ofNullable(clientOAuthSessionItem.getReproveIdentity()); if (reproveIdentity.orElse(false) || configService.enabled(RESET_IDENTITY)) { if (lowestGpg45ConfidenceRequested == Vot.P1) { @@ -316,7 +297,8 @@ private JourneyResponse getJourneyResponse( } // Check for credentials correlation failure - var areGpg45VcsCorrelated = userIdentityService.areVcsCorrelated(vcs.credentials); + var areGpg45VcsCorrelated = + userIdentityService.areVcsCorrelated(credentialBundle.credentials); var profileMatchResponse = checkForProfileMatch( @@ -324,7 +306,7 @@ private JourneyResponse getJourneyResponse( clientOAuthSessionItem, auditEventUser, deviceInformation, - vcs, + credentialBundle, areGpg45VcsCorrelated, contraIndicators); if (profileMatchResponse.isPresent()) { @@ -369,203 +351,31 @@ private JourneyResponse getJourneyResponse( } } - private VerifiableCredentialBundle getVerifiableCredentials( - String userId, String evcsAccessToken) + private VerifiableCredentialBundle getCredentialBundle(String userId, String evcsAccessToken) throws CredentialParseException, EvcsServiceException { + var vcs = + evcsService.getVerifiableCredentialsByState( + userId, evcsAccessToken, CURRENT, PENDING_RETURN); - var tacticalVcs = verifiableCredentialService.getVcs(userId); - - if (configService.enabled(EVCS_WRITE_ENABLED) || configService.enabled(EVCS_READ_ENABLED)) { - var bundle = getEvcsCredentialBundle(userId, evcsAccessToken, tacticalVcs); - if (bundle != null) { - return bundle; - } - } - - return new VerifiableCredentialBundle(tacticalVcs, false, false); - } - - private VerifiableCredentialBundle getEvcsCredentialBundle( - String userId, String evcsAccessToken, List tacticalVcs) - throws CredentialParseException, EvcsServiceException { - try { - var evcsVcs = - evcsService.getVerifiableCredentialsByState( - userId, evcsAccessToken, CURRENT, PENDING_RETURN); - - // Use pending return vcs to determine identity if available - var evcsIdentityVcs = evcsVcs.get(PENDING_RETURN); - var isPendingEvcs = true; - if (isNullOrEmpty(evcsIdentityVcs)) { - evcsIdentityVcs = evcsVcs.get(CURRENT); - isPendingEvcs = false; - } else { - // Ensure we keep any inherited ID VCs in the bundle - evcsIdentityVcs.addAll( - evcsVcs.getOrDefault(CURRENT, List.of()).stream() - .filter(vc -> HMRC_MIGRATION.equals(vc.getCri())) - .toList()); - } - - // Check for partially migrated pending identity - var hasPartiallyMigratedVcs = - hasPartiallyMigratedVcs(tacticalVcs, evcsIdentityVcs, isPendingEvcs); - logIdentityMismatches(tacticalVcs, evcsVcs, hasPartiallyMigratedVcs); - - if (!isNullOrEmpty(evcsIdentityVcs)) { - if (hasPartiallyMigratedVcs) { - // use tactical vcs but with evcs flags so that the store-identity lambda is - // called next and updates the evcs pending one - return new VerifiableCredentialBundle(tacticalVcs, true, true); - } else { - return new VerifiableCredentialBundle( - configService.enabled(EVCS_READ_ENABLED) - ? evcsIdentityVcs - : tacticalVcs, - true, - isPendingEvcs); - } - } - } catch (EvcsServiceException e) { - if (configService.enabled(EVCS_READ_ENABLED)) { - throw e; - } else { - LOGGER.error(LogHelper.buildErrorMessage("Failed to read EVCS VCs", e)); - } - } - return null; - } - - private boolean hasPartiallyMigratedVcs( - List tacticalVcs, - List evcsVcs, - boolean isPending) { - - if (!isPending) { - return false; + if (vcs.isEmpty()) { + return new VerifiableCredentialBundle(List.of(), false); } - // EVCS contains only a pending F2F VC - if (evcsVcs.size() == 1 && F2F.equals(evcsVcs.get(0).getCri())) { - return true; + // Use pending return vcs to determine identity if available + var evcsIdentityVcs = vcs.get(PENDING_RETURN); + var isPending = true; + if (isNullOrEmpty(evcsIdentityVcs)) { + evcsIdentityVcs = vcs.get(CURRENT); + isPending = false; + } else { + // Ensure we keep any inherited ID VCs in the bundle + evcsIdentityVcs.addAll( + vcs.getOrDefault(CURRENT, List.of()).stream() + .filter(vc -> HMRC_MIGRATION.equals(vc.getCri())) + .toList()); } - // Tactical contains the same as pending EVCS, with one extra F2F VC - if (tacticalVcs.size() == evcsVcs.size() + 1) { - - var extraF2fVcs = - tacticalVcs.stream() - .filter( - credential -> - F2F.equals(credential.getCri()) - && evcsVcs.stream() - .noneMatch( - evcsVC -> - evcsVC.getVcString() - .equals( - credential - .getVcString()))) - .toList(); - - return extraF2fVcs.size() == 1; - } - return false; - } - - @ExcludeFromGeneratedCoverageReport - private void logIdentityMismatches( - List tacticalVcs, - Map> evcsVcs, - boolean hasPartiallyMigratedVcs) { - - if (hasPartiallyMigratedVcs) { - LOGGER.info(LogHelper.buildLogMessage("found partially migrated vcs")); - return; - } - var migratedTacticalVcStrings = - tacticalVcs.stream() - .filter(vc -> vc.getMigrated() != null) - .map(VerifiableCredential::getVcString) - .collect(Collectors.toSet()); - - // if we have pending vcs just check those - var evcsToCheck = - Optional.ofNullable(evcsVcs.get(PENDING_RETURN)) - .or(() -> Optional.ofNullable(evcsVcs.get(CURRENT))) - .orElse(List.of()); - - var allTacticalVcStrings = - tacticalVcs.stream() - .map(VerifiableCredential::getVcString) - .collect(Collectors.toSet()); - - var evcsVcStrings = - evcsToCheck.stream() - .map(VerifiableCredential::getVcString) - .collect(Collectors.toSet()); - - var hasUnmigratedVcs = allTacticalVcStrings.size() > migratedTacticalVcStrings.size(); - - // check if we have unmigrated credentials alongside migrated ones - if (hasUnmigratedVcs && !migratedTacticalVcStrings.isEmpty()) { - LOGGER.warn( - LogHelper.buildLogMessage( - "Unmigrated tactical credentials found alongside migrated credentials") - .with( - "migratedCris", - getCriListString( - tacticalVcs.stream() - .filter(vc -> vc.getMigrated() != null) - .toList())) - .with( - "unmigratedCris", - getCriListString( - tacticalVcs.stream() - .filter(vc -> vc.getMigrated() == null) - .toList()))); - } - - // check all the tactical vcs are in the selected evcs vcs - if (!hasUnmigratedVcs && !evcsVcStrings.containsAll(migratedTacticalVcStrings)) { - LOGGER.warn( - LogHelper.buildLogMessage( - "Failed to find corresponding evcs credential for migrated tactical credential") - .with( - "migratedCris", - getCriListString( - tacticalVcs.stream() - .filter( - vc -> - evcsVcStrings.contains( - vc.getVcString())) - .toList())) - .with( - "unmigratedCris", - getCriListString( - tacticalVcs.stream() - .filter( - vc -> - !evcsVcStrings.contains( - vc.getVcString())) - .toList()))); - } - - // check all the evcs vcs are in the tactical store - if (!hasUnmigratedVcs && !migratedTacticalVcStrings.containsAll(evcsVcStrings)) { - LOGGER.warn( - LogHelper.buildLogMessage( - "Failed to find corresponding tactical credential for evcs credential") - .with("pendingEvcsCris", getCriListString(evcsVcs.get(PENDING_RETURN))) - .with("currentEvcsCris", getCriListString(evcsVcs.get(CURRENT))) - .with("tacticalCris", getCriListString(tacticalVcs))); - } - } - - private static String getCriListString(List vcs) { - if (vcs == null) { - return ""; - } - return vcs.stream().map(vc -> vc.getCri().getId()).collect(Collectors.joining(",")); + return new VerifiableCredentialBundle(evcsIdentityVcs, isPending); } private JourneyResponse buildF2FIncompleteResponse(CriResponseItem faceToFaceRequest) { @@ -596,18 +406,17 @@ private Optional checkForProfileMatch( ClientOAuthSessionItem clientOAuthSessionItem, AuditEventUser auditEventUser, String deviceInformation, - VerifiableCredentialBundle vcBundle, + VerifiableCredentialBundle credentialBundle, boolean areGpg45VcsCorrelated, List contraIndicators) - throws ParseException, VerifiableCredentialException, EvcsServiceException { - + throws ParseException, VerifiableCredentialException { // Check for attained vot from requested vots var maybeVotMatchingResult = votMatcher.matchFirstVot( clientOAuthSessionItem .getParsedVtr() .getRequestedVotsByStrengthDescending(), - vcBundle.credentials(), + credentialBundle.credentials(), contraIndicators, areGpg45VcsCorrelated); @@ -621,7 +430,7 @@ private Optional checkForProfileMatch( sendProfileMatchedAuditEvent( votMatchingResult.gpg45Profile(), votMatchingResult.gpg45Scores(), - VcHelper.filterVCBasedOnProfileType(vcBundle.credentials(), GPG45), + VcHelper.filterVCBasedOnProfileType(credentialBundle.credentials(), GPG45), auditEventUser, deviceInformation); } @@ -631,7 +440,7 @@ private Optional checkForProfileMatch( buildReuseResponse( votMatchingResult.vot(), ipvSessionItem, - vcBundle, + credentialBundle, auditEventUser, deviceInformation)); } @@ -698,19 +507,20 @@ private JourneyResponse buildNoMatchResponse( private JourneyResponse buildReuseResponse( Vot attainedVot, IpvSessionItem ipvSessionItem, - VerifiableCredentialBundle vcBundle, + VerifiableCredentialBundle credentialBundle, AuditEventUser auditEventUser, String deviceInformation) - throws VerifiableCredentialException, EvcsServiceException { + throws VerifiableCredentialException { // check the result of 6MFC and return the appropriate journey if (configService.enabled(REPEAT_FRAUD_CHECK) && attainedVot.getProfileType() == GPG45 - && allFraudVcsAreExpired(vcBundle.credentials)) { + && allFraudVcsAreExpired(credentialBundle.credentials)) { LOGGER.info(LogHelper.buildLogMessage("Expired fraud VC found")); sessionCredentialsService.persistCredentials( - allVcsExceptFraud(vcBundle.credentials), auditEventUser.getSessionId(), false); + allVcsExceptFraud(credentialBundle.credentials), + auditEventUser.getSessionId(), + false); - migrateCredentialsToEVCS(auditEventUser, deviceInformation, vcBundle); return JOURNEY_REPEAT_FRAUD_CHECK; } @@ -725,7 +535,7 @@ && allFraudVcsAreExpired(vcBundle.credentials)) { boolean isCurrentlyMigrating = ipvSessionItem.isInheritedIdentityReceivedThisSession(); sessionCredentialsService.persistCredentials( - filterVCBasedOnProfileType(vcBundle.credentials, OPERATIONAL_HMRC), + filterVCBasedOnProfileType(credentialBundle.credentials, OPERATIONAL_HMRC), auditEventUser.getSessionId(), isCurrentlyMigrating); @@ -735,36 +545,12 @@ && allFraudVcsAreExpired(vcBundle.credentials)) { } sessionCredentialsService.persistCredentials( - filterVCBasedOnProfileType(vcBundle.credentials, attainedVot.getProfileType()), + filterVCBasedOnProfileType( + credentialBundle.credentials, attainedVot.getProfileType()), auditEventUser.getSessionId(), false); - migrateCredentialsToEVCS(auditEventUser, deviceInformation, vcBundle); - - return vcBundle.isPendingEvcsIdentity() ? JOURNEY_REUSE_WITH_STORE : JOURNEY_REUSE; - } - - private void migrateCredentialsToEVCS( - AuditEventUser auditEventUser, - String deviceInformation, - VerifiableCredentialBundle vcBundle) - throws EvcsServiceException, VerifiableCredentialException { - if (configService.enabled(EVCS_WRITE_ENABLED) && !vcBundle.hasEvcsIdentity()) { - try { - evcsMigrationService.migrateExistingIdentity( - auditEventUser.getUserId(), vcBundle.credentials()); - sendVCsMigratedAuditEvent( - auditEventUser, vcBundle.credentials(), deviceInformation); - } catch (EvcsServiceException e) { - if (configService.enabled(EVCS_READ_ENABLED)) { - throw e; - } else { - LOGGER.error( - LogHelper.buildErrorMessage( - "Failed to store EVCS migrated identity", e)); - } - } - } + return credentialBundle.isPendingIdentity() ? JOURNEY_REUSE_WITH_STORE : JOURNEY_REUSE; } private List allVcsExceptFraud(List vcs) { @@ -789,24 +575,6 @@ private void sendAuditEvent( new AuditRestrictedDeviceInformation(deviceInformation))); } - private void sendVCsMigratedAuditEvent( - AuditEventUser auditEventUser, - List credentials, - String deviceInformation) { - auditService.sendAuditEvent( - AuditEvent.createWithDeviceInformation( - AuditEventTypes.IPV_VCS_MIGRATED, - configService.getParameter(ConfigurationVariable.COMPONENT_ID), - auditEventUser, - new AuditExtensionsEvcsMigration( - extractSignaturesFromCredentials(credentials)), - new AuditRestrictedDeviceInformation(deviceInformation))); - } - - private List extractSignaturesFromCredentials(List credentials) { - return credentials.stream().map(vc -> vc.getVcString().split("\\.")[2]).toList(); - } - private JourneyResponse buildErrorResponse(ErrorResponse errorResponse, Exception e) { LOGGER.error(LogHelper.buildErrorMessage(errorResponse.getMessage(), e)); return new JourneyErrorResponse( diff --git a/lambdas/check-existing-identity/src/test/java/uk/gov/di/ipv/core/checkexistingidentity/CheckExistingIdentityHandlerTest.java b/lambdas/check-existing-identity/src/test/java/uk/gov/di/ipv/core/checkexistingidentity/CheckExistingIdentityHandlerTest.java index e9c32e7fd8..0ae929326a 100644 --- a/lambdas/check-existing-identity/src/test/java/uk/gov/di/ipv/core/checkexistingidentity/CheckExistingIdentityHandlerTest.java +++ b/lambdas/check-existing-identity/src/test/java/uk/gov/di/ipv/core/checkexistingidentity/CheckExistingIdentityHandlerTest.java @@ -19,13 +19,13 @@ import org.junit.jupiter.api.extension.ExtendWith; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.EnumSource; import org.junit.jupiter.params.provider.MethodSource; import org.mockito.ArgumentCaptor; import org.mockito.Captor; import org.mockito.InOrder; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.Spy; import org.mockito.junit.jupiter.MockitoExtension; import uk.gov.di.ipv.core.library.auditing.AuditEvent; @@ -36,12 +36,12 @@ import uk.gov.di.ipv.core.library.domain.JourneyRequest; import uk.gov.di.ipv.core.library.domain.JourneyResponse; import uk.gov.di.ipv.core.library.domain.VerifiableCredential; -import uk.gov.di.ipv.core.library.enums.EvcsVCState; import uk.gov.di.ipv.core.library.enums.Vot; import uk.gov.di.ipv.core.library.exceptions.ConfigException; import uk.gov.di.ipv.core.library.exceptions.UnrecognisedCiException; import uk.gov.di.ipv.core.library.exceptions.VerifiableCredentialException; import uk.gov.di.ipv.core.library.gpg45.Gpg45Scores; +import uk.gov.di.ipv.core.library.gpg45.enums.Gpg45Profile; import uk.gov.di.ipv.core.library.helpers.SecureTokenHelper; import uk.gov.di.ipv.core.library.helpers.TestVc; import uk.gov.di.ipv.core.library.journeys.JourneyUris; @@ -54,7 +54,6 @@ import uk.gov.di.ipv.core.library.service.ClientOAuthSessionDetailsService; import uk.gov.di.ipv.core.library.service.ConfigService; import uk.gov.di.ipv.core.library.service.CriResponseService; -import uk.gov.di.ipv.core.library.service.EvcsMigrationService; import uk.gov.di.ipv.core.library.service.EvcsService; import uk.gov.di.ipv.core.library.service.IpvSessionService; import uk.gov.di.ipv.core.library.service.UserIdentityService; @@ -62,13 +61,11 @@ import uk.gov.di.ipv.core.library.service.VotMatchingResult; import uk.gov.di.ipv.core.library.testhelpers.unit.LogCollector; import uk.gov.di.ipv.core.library.verifiablecredential.service.SessionCredentialsService; -import uk.gov.di.ipv.core.library.verifiablecredential.service.VerifiableCredentialService; import uk.gov.di.model.ContraIndicator; import uk.gov.di.model.Mitigation; import java.time.Instant; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -92,8 +89,6 @@ import static org.mockito.Mockito.when; import static uk.gov.di.ipv.core.library.config.ConfigurationVariable.COMPONENT_ID; import static uk.gov.di.ipv.core.library.config.ConfigurationVariable.FRAUD_CHECK_EXPIRY_PERIOD_HOURS; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_READ_ENABLED; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_WRITE_ENABLED; import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.P1_JOURNEYS_ENABLED; import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.REPEAT_FRAUD_CHECK; import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.RESET_IDENTITY; @@ -115,9 +110,6 @@ import static uk.gov.di.ipv.core.library.fixtures.VcFixtures.M1B_DCMAW_VC; import static uk.gov.di.ipv.core.library.fixtures.VcFixtures.PASSPORT_NON_DCMAW_SUCCESSFUL_VC; import static uk.gov.di.ipv.core.library.fixtures.VcFixtures.vcDrivingPermit; -import static uk.gov.di.ipv.core.library.fixtures.VcFixtures.vcExperianFraudFailed; -import static uk.gov.di.ipv.core.library.fixtures.VcFixtures.vcF2fBrp; -import static uk.gov.di.ipv.core.library.fixtures.VcFixtures.vcF2fIdCard; import static uk.gov.di.ipv.core.library.fixtures.VcFixtures.vcF2fM1a; import static uk.gov.di.ipv.core.library.fixtures.VcFixtures.vcHmrcMigrationPCL200; import static uk.gov.di.ipv.core.library.fixtures.VcFixtures.vcVerificationM1a; @@ -192,10 +184,8 @@ class CheckExistingIdentityHandlerTest { @Mock private ClientOAuthSessionDetailsService clientOAuthSessionDetailsService; @Mock private CimitService cimitService; @Mock private CimitUtilityService cimitUtilityService; - @Mock private VerifiableCredentialService mockVerifiableCredentialService; @Mock private EvcsService mockEvcsService; @Mock private SessionCredentialsService mockSessionCredentialService; - @Mock private EvcsMigrationService mockEvcsMigrationService; @Mock private VotMatcher mockVotMatcher; @InjectMocks private CheckExistingIdentityHandler checkExistingIdentityHandler; @@ -269,8 +259,6 @@ void shouldReturnJourneyNewGpg45MediumIdentityForP2Vtr() throws Exception { void shouldReturnJourneyNewGpg45LowIdentityForP1Vtr() throws Exception { when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); clientOAuthSessionItem.setVtr(List.of(P2.name(), P1.name())); - when(configService.enabled(EVCS_WRITE_ENABLED)).thenReturn(false); - when(configService.enabled(EVCS_READ_ENABLED)).thenReturn(false); when(configService.enabled(P1_JOURNEYS_ENABLED)).thenReturn(true); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); @@ -298,136 +286,96 @@ public void reuseSetup() throws Exception { } @Test - void shouldUseEvcsServiceWhenEnabled() throws Exception { - var vc = vcHmrcMigrationPCL200(); - vc.setMigrated(Instant.now()); - when(mockVerifiableCredentialService.getVcs(any())).thenReturn(List.of(vc)); - when(configService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); - when(configService.enabled(EVCS_READ_ENABLED)).thenReturn(true); - + void shouldUseEvcsService() throws Exception { when(mockEvcsService.getVerifiableCredentialsByState( - any(), any(), any(EvcsVCState.class), any(EvcsVCState.class))) - .thenReturn(Map.of(EvcsVCState.CURRENT, List.of(gpg45Vc))); + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(CURRENT, List.of(gpg45Vc))); checkExistingIdentityHandler.handleRequest(event, context); - verify(clientOAuthSessionDetailsService, times(1)).getClientOAuthSession(any()); - verify(mockEvcsService, times(1)) + verify(clientOAuthSessionDetailsService).getClientOAuthSession(any()); + verify(mockEvcsService) .getVerifiableCredentialsByState( - TEST_USER_ID, - EVCS_TEST_TOKEN, - EvcsVCState.CURRENT, - EvcsVCState.PENDING_RETURN); + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN); } - @Test - void shouldUseVcServiceWhenEvcsServiceEnabledAndReturnsEmpty() throws Exception { - when(configService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); + @ParameterizedTest + @EnumSource(names = {"M1A", "M1B", "M2B"}) + void shouldReturnJourneyReuseResponseIfScoresSatisfyM1AGpg45Profile( + Gpg45Profile matchedProfile) throws Exception { + var hmrcMigrationVC = vcHmrcMigrationPCL200(); + when(userIdentityService.areVcsCorrelated(any())).thenReturn(true); when(mockEvcsService.getVerifiableCredentialsByState( - any(), any(), any(EvcsVCState.class), any(EvcsVCState.class))) - .thenReturn(new HashMap<>()); - - checkExistingIdentityHandler.handleRequest(event, context); - - verify(clientOAuthSessionDetailsService, times(1)).getClientOAuthSession(any()); - verify(mockEvcsService, times(1)) - .getVerifiableCredentialsByState( - TEST_USER_ID, - EVCS_TEST_TOKEN, - EvcsVCState.CURRENT, - EvcsVCState.PENDING_RETURN); - verify(mockVerifiableCredentialService, times(1)).getVcs(TEST_USER_ID); - } - - @Test - void shouldReturnJourneyReuseResponseIfScoresSatisfyM1AGpg45Profile_alsoStoreVcsInEvcs() - throws Exception { - Mockito.lenient().when(configService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); - VerifiableCredential hmrcMigrationVC = vcHmrcMigrationPCL200(); - - var vcs = List.of(gpg45Vc, hmrcMigrationVC); - when(mockVerifiableCredentialService.getVcs(any())).thenReturn(vcs); - when(mockVotMatcher.matchFirstVot(List.of(P2), vcs, List.of(), true)) + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(CURRENT, List.of(gpg45Vc, hmrcMigrationVC))); + when(mockVotMatcher.matchFirstVot( + List.of(P2), List.of(gpg45Vc, hmrcMigrationVC), List.of(), true)) .thenReturn( Optional.of( - new VotMatchingResult(P2, M1A, Gpg45Scores.builder().build()))); - when(userIdentityService.areVcsCorrelated(any())).thenReturn(true); + new VotMatchingResult( + P2, matchedProfile, Gpg45Scores.builder().build()))); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); assertEquals(JOURNEY_REUSE, journeyResponse); - verify(auditService, times(3)).sendAuditEvent(auditEventArgumentCaptor.capture()); + verify(auditService, times(2)).sendAuditEvent(auditEventArgumentCaptor.capture()); assertEquals( AuditEventTypes.IPV_GPG45_PROFILE_MATCHED, auditEventArgumentCaptor.getAllValues().get(0).getEventName()); assertEquals( AuditEventTypes.IPV_IDENTITY_REUSE_COMPLETE, auditEventArgumentCaptor.getAllValues().get(1).getEventName()); - assertEquals( - AuditEventTypes.IPV_VCS_MIGRATED, - auditEventArgumentCaptor.getAllValues().get(2).getEventName()); - verify(clientOAuthSessionDetailsService, times(1)).getClientOAuthSession(any()); - verify(mockVerifiableCredentialService, times(1)).getVcs(TEST_USER_ID); verify(mockSessionCredentialService) .persistCredentials(List.of(gpg45Vc), ipvSessionItem.getIpvSessionId(), false); - InOrder inOrder = inOrder(ipvSessionItem, ipvSessionService); + var inOrder = inOrder(ipvSessionItem, ipvSessionService); inOrder.verify(ipvSessionItem).setVot(P2); inOrder.verify(ipvSessionService).updateIpvSession(ipvSessionItem); inOrder.verify(ipvSessionItem, never()).setVot(any()); assertEquals(P2, ipvSessionItem.getVot()); - verify(mockEvcsMigrationService) - .migrateExistingIdentity(TEST_USER_ID, List.of(gpg45Vc, hmrcMigrationVC)); } @Test - void shouldReturnJourneyReuseUpdateResponseIfVcIsF2fAndHasPendingReturnInEvcs() - throws Exception { - when(configService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); - when(configService.enabled(EVCS_READ_ENABLED)).thenReturn(true); - var vcs = new ArrayList<>(List.of(gpg45Vc, vcF2fM1a())); - when(mockVerifiableCredentialService.getVcs(any())).thenReturn(vcs); + void shouldReturnJourneyReuseWithStoreResponseIfIsF2fPendingReturn() throws Exception { + var vcs = List.of(gpg45Vc, vcF2fM1a()); when(mockEvcsService.getVerifiableCredentialsByState( - any(), any(), any(EvcsVCState.class), any(EvcsVCState.class))) - .thenReturn(Map.of(PENDING_RETURN, vcs)); + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(PENDING_RETURN, new ArrayList<>(vcs))); - when(criResponseService.getFaceToFaceRequest(any())).thenReturn(new CriResponseItem()); + when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)) + .thenReturn(new CriResponseItem()); when(mockVotMatcher.matchFirstVot(List.of(P2), vcs, List.of(), true)) .thenReturn( Optional.of( new VotMatchingResult(P2, M1A, Gpg45Scores.builder().build()))); when(userIdentityService.areVcsCorrelated(any())).thenReturn(true); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); assertEquals(JOURNEY_REUSE_WITH_STORE, journeyResponse); - // pending vcs should not be migrated - verify(mockEvcsMigrationService, never()).migrateExistingIdentity(any(), any()); } @Test void shouldIncludeCurrentInheritedIdentityInVcBundleWhenPendingReturn() throws Exception { - when(configService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); - when(configService.enabled(EVCS_READ_ENABLED)).thenReturn(true); - var inheritedIdentityVc = vcHmrcMigrationPCL200(); var f2fVc = vcF2fM1a(); - var currentVcs = List.of(inheritedIdentityVc, vcExperianFraudFailed()); - var pendingReturnVcs = new ArrayList<>(List.of(gpg45Vc, f2fVc)); - var allVcs = Stream.concat(pendingReturnVcs.stream(), currentVcs.stream()).toList(); - when(mockVerifiableCredentialService.getVcs(any())).thenReturn(allVcs); when(mockEvcsService.getVerifiableCredentialsByState( - any(), any(), any(EvcsVCState.class), any(EvcsVCState.class))) - .thenReturn(Map.of(PENDING_RETURN, pendingReturnVcs, CURRENT, currentVcs)); + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn( + Map.of( + PENDING_RETURN, + new ArrayList<>(List.of(gpg45Vc, f2fVc)), + CURRENT, + List.of(inheritedIdentityVc))); checkExistingIdentityHandler.handleRequest(event, context); @@ -435,87 +383,22 @@ void shouldIncludeCurrentInheritedIdentityInVcBundleWhenPendingReturn() throws E .areVcsCorrelated(List.of(gpg45Vc, f2fVc, inheritedIdentityVc)); } - @Test - void shouldReturnJourneyReuseStoreResponseIfVcIsF2fAndHasPartiallyMigratedVcs() - throws Exception { - when(configService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); - when(configService.enabled(EVCS_READ_ENABLED)).thenReturn(true); - var f2fVc1 = vcF2fM1a(); - f2fVc1.setMigrated(Instant.now()); - var f2fVc2 = vcF2fBrp(); - f2fVc2.setMigrated(Instant.now()); - var f2fVc3 = vcF2fIdCard(); - when(mockVerifiableCredentialService.getVcs(any())) - .thenReturn(List.of(f2fVc1, f2fVc2, f2fVc3)); - when(mockEvcsService.getVerifiableCredentialsByState( - any(), any(), any(EvcsVCState.class), any(EvcsVCState.class))) - .thenReturn(Map.of(PENDING_RETURN, new ArrayList<>(List.of(f2fVc1, f2fVc2)))); - - when(criResponseService.getFaceToFaceRequest(any())).thenReturn(new CriResponseItem()); - when(mockVotMatcher.matchFirstVot( - List.of(P2), List.of(f2fVc1, f2fVc2, f2fVc3), List.of(), true)) - .thenReturn( - Optional.of( - new VotMatchingResult(P2, M1A, Gpg45Scores.builder().build()))); - when(userIdentityService.areVcsCorrelated(any())).thenReturn(true); - - JourneyResponse journeyResponse = - toResponseClass( - checkExistingIdentityHandler.handleRequest(event, context), - JourneyResponse.class); - - assertEquals(JOURNEY_REUSE_WITH_STORE, journeyResponse); - // pending vcs should not be migrated - verify(mockEvcsMigrationService, never()).migrateExistingIdentity(any(), any()); - } - - @Test - void shouldReturnJourneyReuseResponseIfScoresSatisfyM1BGpg45Profile() throws Exception { - when(mockVotMatcher.matchFirstVot(List.of(P2), List.of(), List.of(), true)) - .thenReturn( - Optional.of( - new VotMatchingResult(P2, M1B, Gpg45Scores.builder().build()))); - when(userIdentityService.areVcsCorrelated(any())).thenReturn(true); - - JourneyResponse journeyResponse = - toResponseClass( - checkExistingIdentityHandler.handleRequest(event, context), - JourneyResponse.class); - - assertEquals(JOURNEY_REUSE, journeyResponse); - - verify(auditService, times(2)).sendAuditEvent(auditEventArgumentCaptor.capture()); - assertEquals( - AuditEventTypes.IPV_IDENTITY_REUSE_COMPLETE, - auditEventArgumentCaptor.getValue().getEventName()); - verify(clientOAuthSessionDetailsService, times(1)).getClientOAuthSession(any()); - - verify(ipvSessionService, times(3)).updateIpvSession(ipvSessionItem); - - InOrder inOrder = inOrder(ipvSessionItem, ipvSessionService); - inOrder.verify(ipvSessionItem).setVot(P2); - inOrder.verify(ipvSessionService).updateIpvSession(ipvSessionItem); - inOrder.verify(ipvSessionItem, never()).setVot(any()); - assertEquals(P2, ipvSessionItem.getVot()); - assertEquals(P2, ipvSessionItem.getTargetVot()); - } - @Test // User returning after migration void shouldReturnJourneyOpProfileReuseResponseIfPCL200RequestedAndMetWhenNotInMigration() throws Exception { - when(mockVerifiableCredentialService.getVcs(any())) - .thenReturn(List.of(gpg45Vc, pcl200Vc)); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(CURRENT, List.of(gpg45Vc, pcl200Vc))); when(mockVotMatcher.matchFirstVot( List.of(P2, PCL250, PCL200), List.of(gpg45Vc, pcl200Vc), List.of(), false)) .thenReturn(Optional.of(new VotMatchingResult(PCL200, null, null))); - - clientOAuthSessionItem.setVtr(List.of(P2.name(), Vot.PCL250.name(), PCL200.name())); + clientOAuthSessionItem.setVtr(List.of(P2.name(), Vot.PCL250.name(), Vot.PCL200.name())); ipvSessionItem.setInheritedIdentityReceivedThisSession(false); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -525,8 +408,8 @@ void shouldReturnJourneyOpProfileReuseResponseIfPCL200RequestedAndMetWhenNotInMi verify(mockSessionCredentialService) .persistCredentials(List.of(pcl200Vc), ipvSessionItem.getIpvSessionId(), false); - InOrder inOrder = inOrder(ipvSessionItem, ipvSessionService); - inOrder.verify(ipvSessionItem).setVot(PCL200); + var inOrder = inOrder(ipvSessionItem, ipvSessionService); + inOrder.verify(ipvSessionItem).setVot(Vot.PCL200); inOrder.verify(ipvSessionService).updateIpvSession(ipvSessionItem); inOrder.verify(ipvSessionItem, never()).setVot(any()); assertEquals(PCL200, ipvSessionItem.getVot()); @@ -536,16 +419,16 @@ void shouldReturnJourneyOpProfileReuseResponseIfPCL200RequestedAndMetWhenNotInMi @Test // User returning after migration void shouldReturnJourneyOpProfileReuseResponseIfPCL250RequestedAndMetWhenNotInMigration() throws Exception { - when(mockVerifiableCredentialService.getVcs(any())) - .thenReturn(List.of(gpg45Vc, pcl250Vc)); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(CURRENT, List.of(gpg45Vc, pcl250Vc))); when(mockVotMatcher.matchFirstVot( List.of(P2, PCL250), List.of(gpg45Vc, pcl250Vc), List.of(), false)) .thenReturn(Optional.of(new VotMatchingResult(PCL250, null, null))); - clientOAuthSessionItem.setVtr(List.of(P2.name(), Vot.PCL250.name())); ipvSessionItem.setInheritedIdentityReceivedThisSession(false); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -555,7 +438,7 @@ void shouldReturnJourneyOpProfileReuseResponseIfPCL250RequestedAndMetWhenNotInMi verify(mockSessionCredentialService) .persistCredentials(List.of(pcl250Vc), ipvSessionItem.getIpvSessionId(), false); - InOrder inOrder = inOrder(ipvSessionItem, ipvSessionService); + var inOrder = inOrder(ipvSessionItem, ipvSessionService); inOrder.verify(ipvSessionItem).setVot(Vot.PCL250); inOrder.verify(ipvSessionService).updateIpvSession(ipvSessionItem); inOrder.verify(ipvSessionItem, never()).setVot(any()); @@ -566,7 +449,9 @@ void shouldReturnJourneyOpProfileReuseResponseIfPCL250RequestedAndMetWhenNotInMi @Test // User returning after migration void shouldReturnJourneyOpProfileReuseResponseIfOpProfileAndPendingF2F() throws Exception { when(criResponseService.getFaceToFaceRequest(any())).thenReturn(new CriResponseItem()); - when(mockVerifiableCredentialService.getVcs(any())).thenReturn(List.of(pcl250Vc)); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(CURRENT, List.of(pcl250Vc))); when(mockVotMatcher.matchFirstVot( List.of(P2, PCL250), List.of(pcl250Vc), List.of(), false)) .thenReturn(Optional.of(new VotMatchingResult(PCL250, null, null))); @@ -574,14 +459,14 @@ void shouldReturnJourneyOpProfileReuseResponseIfOpProfileAndPendingF2F() throws clientOAuthSessionItem.setVtr(List.of(P2.name(), Vot.PCL250.name())); ipvSessionItem.setInheritedIdentityReceivedThisSession(false); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); assertEquals(JOURNEY_OP_PROFILE_REUSE, journeyResponse); - InOrder inOrder = inOrder(ipvSessionItem, ipvSessionService); + var inOrder = inOrder(ipvSessionItem, ipvSessionService); inOrder.verify(ipvSessionItem).setVot(Vot.PCL250); inOrder.verify(ipvSessionService).updateIpvSession(ipvSessionItem); inOrder.verify(ipvSessionItem, never()).setVot(any()); @@ -591,19 +476,19 @@ void shouldReturnJourneyOpProfileReuseResponseIfOpProfileAndPendingF2F() throws @Test // User in process of migration void shouldReturnJourneyInMigrationReuseResponseIfPCL200RequestedAndMet() throws Exception { - when(mockVerifiableCredentialService.getVcs(any())) - .thenReturn(List.of(gpg45Vc, pcl200Vc)); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(CURRENT, List.of(gpg45Vc, pcl200Vc))); when(mockVotMatcher.matchFirstVot( List.of(P2, PCL250, PCL200), List.of(gpg45Vc, pcl200Vc), List.of(), false)) .thenReturn(Optional.of(new VotMatchingResult(PCL200, null, null))); - ipvSessionItem.setInheritedIdentityReceivedThisSession(true); clientOAuthSessionItem.setVtr(List.of(P2.name(), Vot.PCL250.name(), PCL200.name())); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -613,8 +498,8 @@ void shouldReturnJourneyInMigrationReuseResponseIfPCL200RequestedAndMet() throws verify(mockSessionCredentialService) .persistCredentials(List.of(pcl200Vc), ipvSessionItem.getIpvSessionId(), true); - InOrder inOrder = inOrder(ipvSessionItem, ipvSessionService); - inOrder.verify(ipvSessionItem).setVot(PCL200); + var inOrder = inOrder(ipvSessionItem, ipvSessionService); + inOrder.verify(ipvSessionItem).setVot(Vot.PCL200); inOrder.verify(ipvSessionService).updateIpvSession(ipvSessionItem); inOrder.verify(ipvSessionItem, never()).setVot(any()); assertEquals(PCL200, ipvSessionItem.getVot()); @@ -623,8 +508,9 @@ void shouldReturnJourneyInMigrationReuseResponseIfPCL200RequestedAndMet() throws @Test // User in process of migration void shouldReturnJourneyInMigrationReuseResponseIfPCL250RequestedAndMet() throws Exception { - when(mockVerifiableCredentialService.getVcs(any())) - .thenReturn(List.of(gpg45Vc, pcl250Vc)); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(CURRENT, List.of(gpg45Vc, pcl250Vc))); when(mockVotMatcher.matchFirstVot( List.of(P2, PCL250), List.of(gpg45Vc, pcl250Vc), List.of(), true)) .thenReturn(Optional.of(new VotMatchingResult(PCL250, null, null))); @@ -633,7 +519,7 @@ void shouldReturnJourneyInMigrationReuseResponseIfPCL250RequestedAndMet() throws clientOAuthSessionItem.setVtr(List.of(P2.name(), Vot.PCL250.name())); ipvSessionItem.setInheritedIdentityReceivedThisSession(true); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -643,7 +529,7 @@ void shouldReturnJourneyInMigrationReuseResponseIfPCL250RequestedAndMet() throws verify(mockSessionCredentialService) .persistCredentials(List.of(pcl250Vc), ipvSessionItem.getIpvSessionId(), true); - InOrder inOrder = inOrder(ipvSessionItem, ipvSessionService); + var inOrder = inOrder(ipvSessionItem, ipvSessionService); inOrder.verify(ipvSessionItem).setVot(Vot.PCL250); inOrder.verify(ipvSessionService).updateIpvSession(ipvSessionItem); inOrder.verify(ipvSessionItem, never()).setVot(any()); @@ -683,19 +569,20 @@ void shouldReturnErrorResponseIfVcCanNotBeStoredInSessionCredentialTable() } @Test - void shouldReturnNoMatchForF2FCompleteAndVCsDoNotCorrelate() throws Exception { + void shouldReturnF2FFailForF2FCompleteAndVCsDoNotCorrelate() throws Exception { when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - when(mockVerifiableCredentialService.getVcs(TEST_USER_ID)).thenReturn(List.of(vcF2fM1a())); - CriResponseItem criResponseItem = - createCriResponseStoreItem(CriResponseService.STATUS_PENDING); - when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)).thenReturn(criResponseItem); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(PENDING_RETURN, new ArrayList<>(List.of(vcF2fM1a())))); + when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)) + .thenReturn(createCriResponseStoreItem(CriResponseService.STATUS_PENDING)); when(userIdentityService.areVcsCorrelated(any())).thenReturn(false); clientOAuthSessionItem.setVtr(List.of(Vot.PCL250.name(), PCL200.name(), P2.name())); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -714,11 +601,13 @@ void shouldReturnNoMatchForF2FCompleteAndVCsDoNotCorrelate() throws Exception { } @Test - void shouldNoMatchStrongestVotAndAlsoVCsDoNotCorrelate() throws Exception { + void shouldReturnNoMatchResponseIfVCsDoNotCorrelate() throws Exception { when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - when(mockVerifiableCredentialService.getVcs(TEST_USER_ID)).thenReturn(List.of(vcF2fM1a())); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(CURRENT, List.of(vcF2fM1a()))); when(userIdentityService.areVcsCorrelated(any())).thenReturn(false); clientOAuthSessionItem.setVtr(List.of(Vot.PCL250.name(), PCL200.name(), P2.name())); @@ -744,16 +633,18 @@ void shouldReturnJourneyIpvGpg45MediumResponseIfNoProfileAttainsVot( when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)).thenReturn(null); - List credentials = new ArrayList<>(); + var credentials = new ArrayList(); if (vot.isPresent()) { credentials.add(createOperationalProfileVc(vot.get())); } - when(mockVerifiableCredentialService.getVcs(any())).thenReturn(credentials); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(CURRENT, credentials)); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); clientOAuthSessionItem.setVtr(vtr); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -764,16 +655,18 @@ void shouldReturnJourneyIpvGpg45MediumResponseIfNoProfileAttainsVot( } @Test - void shouldReturnJourneyIpvGpg45MediumResponseIfScoresDoNotSatisfyM1AGpg45Profile() + void shouldReturnJourneyIpvGpg45MediumResponseIfScoresDoNotSatisfyP2Gpg45Profile() throws Exception { when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); - when(mockVerifiableCredentialService.getVcs(TEST_USER_ID)).thenReturn(VCS_FROM_STORE); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(CURRENT, VCS_FROM_STORE)); when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)).thenReturn(null); when(userIdentityService.areVcsCorrelated(any())).thenReturn(true); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -795,7 +688,7 @@ void shouldNotSendAuditEventIfNewUser() throws Exception { when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -812,9 +705,9 @@ void shouldNotSendAuditEventIfNewUser() throws Exception { @Test void shouldReturn400IfSessionIdNotInHeader() throws Exception { - JourneyRequest eventWithoutHeaders = JourneyRequest.builder().build(); + var eventWithoutHeaders = JourneyRequest.builder().build(); - JourneyErrorResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(eventWithoutHeaders, context), JourneyErrorResponse.class); @@ -836,13 +729,12 @@ void shouldReturn400IfSessionIdNotInHeader() throws Exception { @Test void shouldReturnPendingResponseIfFaceToFaceVerificationIsPending() throws Exception { when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); - CriResponseItem criResponseItem = - createCriResponseStoreItem(CriResponseService.STATUS_PENDING); + var criResponseItem = createCriResponseStoreItem(CriResponseService.STATUS_PENDING); when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)).thenReturn(criResponseItem); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -858,15 +750,14 @@ void shouldReturnPendingResponseIfFaceToFaceVerificationIsPending() throws Excep void shouldReturnPendingResponseIfFaceToFaceVerificationIsPendingAndBreachingCi() throws Exception { when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); - CriResponseItem criResponseItem = - createCriResponseStoreItem(CriResponseService.STATUS_PENDING); + var criResponseItem = createCriResponseStoreItem(CriResponseService.STATUS_PENDING); when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)).thenReturn(criResponseItem); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); when(cimitUtilityService.getMitigationJourneyIfBreaching(any(), eq(TEST_VOT))) .thenReturn(Optional.of(JOURNEY_FAIL_WITH_CI)); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -881,12 +772,12 @@ void shouldReturnPendingResponseIfFaceToFaceVerificationIsPendingAndBreachingCi( @Test void shouldReturnFailResponseIfFaceToFaceVerificationIsError() throws Exception { when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); - CriResponseItem criResponseItem = createCriErrorResponseStoreItem(Instant.now()); + var criResponseItem = createCriErrorResponseStoreItem(Instant.now()); when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)).thenReturn(criResponseItem); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -901,13 +792,12 @@ void shouldReturnFailResponseIfFaceToFaceVerificationIsError() throws Exception @Test void shouldReturnFailResponseIfFaceToFaceVerificationIsAbandon() throws Exception { when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); - CriResponseItem criResponseItem = - createCriResponseStoreItem(CriResponseService.STATUS_ABANDON); + var criResponseItem = createCriResponseStoreItem(CriResponseService.STATUS_ABANDON); when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)).thenReturn(criResponseItem); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -922,15 +812,16 @@ void shouldReturnFailResponseIfFaceToFaceVerificationIsAbandon() throws Exceptio @Test void shouldReturnFailResponseForFaceToFaceVerificationIfNoMatchedProfile() throws Exception { when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); - when(mockVerifiableCredentialService.getVcs(TEST_USER_ID)).thenReturn(List.of(vcF2fM1a())); - CriResponseItem criResponseItem = - createCriResponseStoreItem(CriResponseService.STATUS_PENDING); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(PENDING_RETURN, new ArrayList<>(List.of(vcF2fM1a())))); + var criResponseItem = createCriResponseStoreItem(CriResponseService.STATUS_PENDING); when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)).thenReturn(criResponseItem); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); when(userIdentityService.areVcsCorrelated(any())).thenReturn(true); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -950,15 +841,16 @@ void shouldReturnFailResponseForFaceToFaceVerificationIfNoMatchedProfile() throw @Test void shouldReturnFailResponseForFaceToFaceIfVCsDoNotCorrelate() throws Exception { when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); - when(mockVerifiableCredentialService.getVcs(TEST_USER_ID)).thenReturn(List.of(vcF2fM1a())); - CriResponseItem criResponseItem = - createCriResponseStoreItem(CriResponseService.STATUS_PENDING); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(PENDING_RETURN, new ArrayList<>(List.of(vcF2fM1a())))); + var criResponseItem = createCriResponseStoreItem(CriResponseService.STATUS_PENDING); when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)).thenReturn(criResponseItem); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); when(userIdentityService.areVcsCorrelated(any())).thenReturn(false); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -977,12 +869,14 @@ void shouldReturnFailResponseForFaceToFaceIfVCsDoNotCorrelate() throws Exception @Test void shouldReturnJourneyIpvGpg45MediumIfDataDoesNotCorrelateAndNotF2F() throws Exception { when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); - when(mockVerifiableCredentialService.getVcs(TEST_USER_ID)).thenReturn(List.of(vcF2fM1a())); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(PENDING_RETURN, new ArrayList<>(List.of(vcF2fM1a())))); when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)).thenReturn(null); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -1007,7 +901,7 @@ void shouldReturnCiJourneyResponseIfPresent() throws Exception { when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - JourneyResponse response = + var response = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -1027,7 +921,7 @@ void shouldReturnFailWithCiJourneyResponseForCiBreach() throws Exception { when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - JourneyResponse response = + var response = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -1044,7 +938,7 @@ void shouldReturn500IfFailedToRetrieveCisFromStorageSystem() throws Exception { when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - JourneyErrorResponse response = + var response = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyErrorResponse.class); @@ -1063,7 +957,7 @@ void shouldReturn500IfFailedToGetCimitConfig() throws Exception { when(cimitUtilityService.getMitigationJourneyIfBreaching(any(), eq(TEST_VOT))) .thenThrow(new ConfigException("Failed to get cimit config")); - JourneyErrorResponse response = + var response = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyErrorResponse.class); @@ -1083,7 +977,7 @@ void shouldReturn500IfUnrecognisedCiReceived() throws Exception { when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - JourneyErrorResponse response = + var response = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyErrorResponse.class); @@ -1106,7 +1000,7 @@ void shouldReturn500IfUnrecognisedCiReceived() throws Exception { when(cimitUtilityService.getMitigationJourneyIfBreaching(any(), eq(TEST_VOT))) .thenReturn(Optional.of(JOURNEY_FAIL_WITH_CI)); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -1121,11 +1015,9 @@ void shouldReturnReproveP2JourneyStepResponseIfResetIdentityTrue() throws Except .thenReturn(clientOAuthSessionItem); when(cimitService.getContraIndicators(TEST_USER_ID, TEST_JOURNEY_ID, TEST_CLIENT_SOURCE_IP)) .thenReturn(List.of()); - when(configService.enabled(EVCS_WRITE_ENABLED)).thenReturn(false); - when(configService.enabled(EVCS_READ_ENABLED)).thenReturn(false); when(configService.enabled(RESET_IDENTITY)).thenReturn(true); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -1142,12 +1034,10 @@ void shouldReturnReproveP1JourneyStepResponseIfResetIdentityTrueAndP1InVtr() thr .thenReturn(clientOAuthSessionItem); when(cimitService.getContraIndicators(TEST_USER_ID, TEST_JOURNEY_ID, TEST_CLIENT_SOURCE_IP)) .thenReturn(List.of()); - when(configService.enabled(EVCS_WRITE_ENABLED)).thenReturn(false); - when(configService.enabled(EVCS_READ_ENABLED)).thenReturn(false); when(configService.enabled(RESET_IDENTITY)).thenReturn(true); when(configService.enabled(P1_JOURNEYS_ENABLED)).thenReturn(true); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -1177,7 +1067,7 @@ void shouldReturnSameMitigationJourneyWhenCiAlreadyMitigated() throws Exception when(cimitUtilityService.getMitigatedCiJourneyResponse(mitigatedCI)) .thenReturn(Optional.of(new JourneyResponse(journey))); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -1195,9 +1085,10 @@ void shouldReturnSameJourneyMitigationWhenCiAlreadyMitigatedF2F() throws Excepti when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - when(mockVerifiableCredentialService.getVcs(TEST_USER_ID)).thenReturn(List.of(vcF2fM1a())); - CriResponseItem criResponseItem = - createCriResponseStoreItem(CriResponseService.STATUS_PENDING); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(PENDING_RETURN, new ArrayList<>(List.of(vcF2fM1a())))); + var criResponseItem = createCriResponseStoreItem(CriResponseService.STATUS_PENDING); when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)).thenReturn(criResponseItem); when(cimitService.getContraIndicators(TEST_USER_ID, TEST_JOURNEY_ID, TEST_CLIENT_SOURCE_IP)) .thenReturn(testContraIndicators); @@ -1209,7 +1100,7 @@ void shouldReturnSameJourneyMitigationWhenCiAlreadyMitigatedF2F() throws Excepti when(cimitUtilityService.getMitigatedCiJourneyResponse(mitigatedCI)) .thenReturn(Optional.of(new JourneyResponse(JOURNEY_ENHANCED_VERIFICATION_PATH))); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -1229,9 +1120,10 @@ void shouldReturnSameJourneyMitigationWhenCiAlreadyMitigatedF2F() throws Excepti when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - when(mockVerifiableCredentialService.getVcs(TEST_USER_ID)).thenReturn(List.of(vcF2fM1a())); - CriResponseItem criResponseItem = - createCriResponseStoreItem(CriResponseService.STATUS_PENDING); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(PENDING_RETURN, new ArrayList<>(List.of(vcF2fM1a())))); + var criResponseItem = createCriResponseStoreItem(CriResponseService.STATUS_PENDING); when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)).thenReturn(criResponseItem); when(cimitService.getContraIndicators(TEST_USER_ID, TEST_JOURNEY_ID, TEST_CLIENT_SOURCE_IP)) .thenReturn(testContraIndicators); @@ -1243,7 +1135,7 @@ void shouldReturnSameJourneyMitigationWhenCiAlreadyMitigatedF2F() throws Excepti when(cimitUtilityService.getMitigatedCiJourneyResponse(mitigatedCI)) .thenReturn(Optional.empty()); - JourneyErrorResponse response = + var response = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyErrorResponse.class); @@ -1266,9 +1158,10 @@ void shouldReturnErrorResponseWhenCiMitigationJourneyStepPresentButNotSupported( when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - when(mockVerifiableCredentialService.getVcs(TEST_USER_ID)).thenReturn(List.of(vcF2fM1a())); - CriResponseItem criResponseItem = - createCriResponseStoreItem(CriResponseService.STATUS_PENDING); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(PENDING_RETURN, new ArrayList<>(List.of(vcF2fM1a())))); + var criResponseItem = createCriResponseStoreItem(CriResponseService.STATUS_PENDING); when(criResponseService.getFaceToFaceRequest(TEST_USER_ID)).thenReturn(criResponseItem); when(cimitService.getContraIndicators(TEST_USER_ID, TEST_JOURNEY_ID, TEST_CLIENT_SOURCE_IP)) .thenReturn(testContraIndicators); @@ -1280,7 +1173,7 @@ void shouldReturnErrorResponseWhenCiMitigationJourneyStepPresentButNotSupported( when(cimitUtilityService.getMitigatedCiJourneyResponse(mitigatedCI)) .thenReturn(Optional.of(new JourneyResponse(journey))); - JourneyErrorResponse response = + var response = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyErrorResponse.class); @@ -1301,7 +1194,9 @@ void shouldReturnJourneyRepeatFraudCheckResponseIfExpiredFraudAndFlagIsTrue() th EXPIRED_M1A_EXPERIAN_FRAUD_VC, vcVerificationM1a(), M1B_DCMAW_VC); - when(mockVerifiableCredentialService.getVcs(TEST_USER_ID)).thenReturn(vcs); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(CURRENT, vcs)); when(mockVotMatcher.matchFirstVot(List.of(P2), vcs, List.of(), true)) .thenReturn( @@ -1309,14 +1204,12 @@ void shouldReturnJourneyRepeatFraudCheckResponseIfExpiredFraudAndFlagIsTrue() th when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); when(userIdentityService.areVcsCorrelated(any())).thenReturn(true); - when(configService.enabled(EVCS_WRITE_ENABLED)).thenReturn(false); - when(configService.enabled(EVCS_READ_ENABLED)).thenReturn(false); when(configService.enabled(RESET_IDENTITY)).thenReturn(false); when(configService.enabled(REPEAT_FRAUD_CHECK)).thenReturn(true); when(configService.getParameter(COMPONENT_ID)).thenReturn("http://ipv/"); when(configService.getParameter(FRAUD_CHECK_EXPIRY_PERIOD_HOURS)).thenReturn("1"); - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -1328,61 +1221,16 @@ void shouldReturnJourneyRepeatFraudCheckResponseIfExpiredFraudAndFlagIsTrue() th .persistCredentials(expectedStoredVc, ipvSessionItem.getIpvSessionId(), false); verify(ipvSessionItem, never()).setVot(any()); - verify(mockEvcsMigrationService, times(0)).migrateExistingIdentity(any(), any()); assertEquals(P2, ipvSessionItem.getTargetVot()); } - @Test - void - shouldReturnJourneyRepeatFraudCheckResponseIfExpiredFraudAndFlagIsTrueAndAlsoStoreVcsInEvcs() - throws Exception { - when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); - var vcs = - List.of( - PASSPORT_NON_DCMAW_SUCCESSFUL_VC, - M1A_ADDRESS_VC, - EXPIRED_M1A_EXPERIAN_FRAUD_VC, - vcVerificationM1a(), - M1B_DCMAW_VC); - when(mockVerifiableCredentialService.getVcs(TEST_USER_ID)).thenReturn(vcs); - when(mockVotMatcher.matchFirstVot(List.of(P2), vcs, List.of(), true)) - .thenReturn( - Optional.of(new VotMatchingResult(P2, M1B, Gpg45Scores.builder().build()))); - when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) - .thenReturn(clientOAuthSessionItem); - when(userIdentityService.areVcsCorrelated(any())).thenReturn(true); - when(configService.enabled(RESET_IDENTITY)).thenReturn(false); - when(configService.enabled(REPEAT_FRAUD_CHECK)).thenReturn(true); - when(configService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); - when(configService.getParameter(COMPONENT_ID)).thenReturn("http://ipv/"); - when(configService.getParameter(FRAUD_CHECK_EXPIRY_PERIOD_HOURS)).thenReturn("1"); - - JourneyResponse journeyResponse = - toResponseClass( - checkExistingIdentityHandler.handleRequest(event, context), - JourneyResponse.class); - assertEquals(JOURNEY_REPEAT_FRAUD_CHECK, journeyResponse); - - verify(auditService, times(2)).sendAuditEvent(auditEventArgumentCaptor.capture()); - assertEquals( - AuditEventTypes.IPV_GPG45_PROFILE_MATCHED, - auditEventArgumentCaptor.getAllValues().get(0).getEventName()); - assertEquals( - AuditEventTypes.IPV_VCS_MIGRATED, - auditEventArgumentCaptor.getAllValues().get(1).getEventName()); - - var expectedStoredVc = - vcs.stream().filter(vc -> vc != EXPIRED_M1A_EXPERIAN_FRAUD_VC).toList(); - verify(mockSessionCredentialService) - .persistCredentials(expectedStoredVc, ipvSessionItem.getIpvSessionId(), false); - verify(mockEvcsMigrationService).migrateExistingIdentity(TEST_USER_ID, vcs); - } - @Test void shouldNotReturnJourneyRepeatFraudCheckResponseIfNotExpiredFraudAndFlagIsTrue() throws Exception { when(ipvSessionService.getIpvSessionWithRetry(TEST_SESSION_ID)).thenReturn(ipvSessionItem); - when(mockVerifiableCredentialService.getVcs(TEST_USER_ID)).thenReturn(VCS_FROM_STORE); + when(mockEvcsService.getVerifiableCredentialsByState( + TEST_USER_ID, EVCS_TEST_TOKEN, CURRENT, PENDING_RETURN)) + .thenReturn(Map.of(CURRENT, VCS_FROM_STORE)); when(mockVotMatcher.matchFirstVot(List.of(P2), VCS_FROM_STORE, List.of(), true)) .thenReturn( @@ -1391,15 +1239,13 @@ void shouldNotReturnJourneyRepeatFraudCheckResponseIfNotExpiredFraudAndFlagIsTru when(clientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); when(userIdentityService.areVcsCorrelated(any())).thenReturn(true); - when(configService.enabled(EVCS_WRITE_ENABLED)).thenReturn(false); - when(configService.enabled(EVCS_READ_ENABLED)).thenReturn(false); when(configService.enabled(RESET_IDENTITY)).thenReturn(false); when(configService.enabled(REPEAT_FRAUD_CHECK)).thenReturn(true); when(configService.getParameter(COMPONENT_ID)).thenReturn("http://ipv/"); when(configService.getParameter(FRAUD_CHECK_EXPIRY_PERIOD_HOURS)) .thenReturn("100000000"); // not the best way to test this - JourneyResponse journeyResponse = + var journeyResponse = toResponseClass( checkExistingIdentityHandler.handleRequest(event, context), JourneyResponse.class); @@ -1408,7 +1254,7 @@ void shouldNotReturnJourneyRepeatFraudCheckResponseIfNotExpiredFraudAndFlagIsTru verify(mockSessionCredentialService) .persistCredentials(VCS_FROM_STORE, ipvSessionItem.getIpvSessionId(), false); - InOrder inOrder = inOrder(ipvSessionItem, ipvSessionService); + var inOrder = inOrder(ipvSessionItem, ipvSessionService); inOrder.verify(ipvSessionItem).setVot(P2); inOrder.verify(ipvSessionService).updateIpvSession(ipvSessionItem); inOrder.verify(ipvSessionItem, never()).setVot(any()); diff --git a/lambdas/check-mobile-app-vc-receipt/build.gradle b/lambdas/check-mobile-app-vc-receipt/build.gradle index 0fc2397edc..1ce767e4e1 100644 --- a/lambdas/check-mobile-app-vc-receipt/build.gradle +++ b/lambdas/check-mobile-app-vc-receipt/build.gradle @@ -13,6 +13,7 @@ dependencies { project(":libs:cri-response-service"), project(":libs:verifiable-credentials"), project(":libs:cimit-service"), + project(":libs:evcs-service"), project(":libs:user-identity-service"), project(":lambdas:process-cri-callback") diff --git a/lambdas/check-mobile-app-vc-receipt/src/main/java/uk/gov/di/ipv/core/checkmobileappvcreceipt/CheckMobileAppVcReceiptHandler.java b/lambdas/check-mobile-app-vc-receipt/src/main/java/uk/gov/di/ipv/core/checkmobileappvcreceipt/CheckMobileAppVcReceiptHandler.java index 0faad3d5be..08aabbf3c5 100644 --- a/lambdas/check-mobile-app-vc-receipt/src/main/java/uk/gov/di/ipv/core/checkmobileappvcreceipt/CheckMobileAppVcReceiptHandler.java +++ b/lambdas/check-mobile-app-vc-receipt/src/main/java/uk/gov/di/ipv/core/checkmobileappvcreceipt/CheckMobileAppVcReceiptHandler.java @@ -14,10 +14,10 @@ import uk.gov.di.ipv.core.checkmobileappvcreceipt.exception.InvalidCheckMobileAppVcReceiptRequestException; import uk.gov.di.ipv.core.library.annotations.ExcludeFromGeneratedCoverageReport; import uk.gov.di.ipv.core.library.cimit.exception.CiRetrievalException; -import uk.gov.di.ipv.core.library.domain.Cri; import uk.gov.di.ipv.core.library.domain.ErrorResponse; import uk.gov.di.ipv.core.library.domain.JourneyErrorResponse; import uk.gov.di.ipv.core.library.domain.JourneyResponse; +import uk.gov.di.ipv.core.library.exception.EvcsServiceException; import uk.gov.di.ipv.core.library.exceptions.ConfigException; import uk.gov.di.ipv.core.library.exceptions.CredentialParseException; import uk.gov.di.ipv.core.library.exceptions.HttpResponseExceptionWithErrorBody; @@ -32,15 +32,17 @@ import uk.gov.di.ipv.core.library.service.ClientOAuthSessionDetailsService; import uk.gov.di.ipv.core.library.service.ConfigService; import uk.gov.di.ipv.core.library.service.CriResponseService; +import uk.gov.di.ipv.core.library.service.EvcsService; import uk.gov.di.ipv.core.library.service.IpvSessionService; import uk.gov.di.ipv.core.library.service.UserIdentityService; import uk.gov.di.ipv.core.library.service.exception.InvalidCriResponseException; import uk.gov.di.ipv.core.library.verifiablecredential.service.SessionCredentialsService; -import uk.gov.di.ipv.core.library.verifiablecredential.service.VerifiableCredentialService; import uk.gov.di.ipv.core.processcricallback.service.CriCheckingService; import java.util.List; +import static uk.gov.di.ipv.core.library.domain.Cri.DCMAW_ASYNC; +import static uk.gov.di.ipv.core.library.enums.EvcsVCState.PENDING_RETURN; import static uk.gov.di.ipv.core.library.journeys.JourneyUris.JOURNEY_ABANDON_PATH; import static uk.gov.di.ipv.core.library.journeys.JourneyUris.JOURNEY_ERROR_PATH; @@ -54,25 +56,25 @@ public class CheckMobileAppVcReceiptHandler private final IpvSessionService ipvSessionService; private final ClientOAuthSessionDetailsService clientOAuthSessionDetailsService; private final CriResponseService criResponseService; - private final VerifiableCredentialService verifiableCredentialService; private final CriCheckingService criCheckingService; private final SessionCredentialsService sessionCredentialsService; + private final EvcsService evcsService; public CheckMobileAppVcReceiptHandler( ConfigService configService, IpvSessionService ipvSessionService, ClientOAuthSessionDetailsService clientOAuthSessionDetailsService, CriResponseService criResponseService, - VerifiableCredentialService verifiableCredentialService, CriCheckingService criCheckingService, - SessionCredentialsService sessionCredentialsService) { + SessionCredentialsService sessionCredentialsService, + EvcsService evcsService) { this.configService = configService; this.ipvSessionService = ipvSessionService; this.clientOAuthSessionDetailsService = clientOAuthSessionDetailsService; this.criResponseService = criResponseService; - this.verifiableCredentialService = verifiableCredentialService; this.criCheckingService = criCheckingService; this.sessionCredentialsService = sessionCredentialsService; + this.evcsService = evcsService; } @ExcludeFromGeneratedCoverageReport @@ -81,18 +83,16 @@ public CheckMobileAppVcReceiptHandler() { ipvSessionService = new IpvSessionService(configService); clientOAuthSessionDetailsService = new ClientOAuthSessionDetailsService(configService); criResponseService = new CriResponseService(configService); - verifiableCredentialService = new VerifiableCredentialService(configService); - var cimitService = new CimitService(configService); - sessionCredentialsService = new SessionCredentialsService(configService); - criCheckingService = new CriCheckingService( configService, AuditService.create(configService), new UserIdentityService(configService), - cimitService, + new CimitService(configService), new CimitUtilityService(configService), ipvSessionService); + sessionCredentialsService = new SessionCredentialsService(configService); + evcsService = new EvcsService(configService); } @Override @@ -124,6 +124,8 @@ public APIGatewayProxyResponseEvent handleRequest( e, HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorResponse.FAILED_TO_PARSE_ISSUED_CREDENTIALS); + } catch (EvcsServiceException e) { + return buildErrorResponse(e, e.getResponseCode(), e.getErrorResponse()); } catch (ConfigException e) { return buildErrorResponse( e, HttpStatus.SC_INTERNAL_SERVER_ERROR, ErrorResponse.FAILED_TO_PARSE_CONFIG); @@ -147,7 +149,8 @@ private CheckMobileAppVcReceiptRequest parseRequest(APIGatewayProxyRequestEvent private JourneyResponse getJourneyResponse(CheckMobileAppVcReceiptRequest request) throws IpvSessionNotFoundException, HttpResponseExceptionWithErrorBody, InvalidCriResponseException, CredentialParseException, - VerifiableCredentialException, ConfigException, CiRetrievalException { + VerifiableCredentialException, ConfigException, CiRetrievalException, + EvcsServiceException { // Validate callback sessions validateSessionId(request); @@ -167,16 +170,11 @@ private JourneyResponse getJourneyResponse(CheckMobileAppVcReceiptRequest reques LogHelper.attachComponentId(configService); // Retrieve and validate cri response and vc - var criResponse = criResponseService.getCriResponseItem(userId, Cri.DCMAW_ASYNC); + var criResponse = criResponseService.getCriResponseItem(userId, DCMAW_ASYNC); if (criResponse == null) { throw new InvalidCriResponseException(ErrorResponse.CRI_RESPONSE_ITEM_NOT_FOUND); } - var vc = verifiableCredentialService.getVc(userId, Cri.DCMAW_ASYNC.getId()); - if (CriResponseService.STATUS_PENDING.equals(criResponse.getStatus()) && vc == null) { - return null; - } - if (CriResponseService.STATUS_ERROR.equals(criResponse.getStatus())) { return JOURNEY_ERROR; } @@ -185,14 +183,27 @@ private JourneyResponse getJourneyResponse(CheckMobileAppVcReceiptRequest reques return JOURNEY_ABANDON; } - var sessionVcs = - sessionCredentialsService.getCredentials(ipvSessionItem.getIpvSessionId(), userId); + var dcmawAsyncVc = + evcsService + .getVerifiableCredentials( + userId, clientOAuthSessionItem.getEvcsAccessToken(), PENDING_RETURN) + .stream() + .filter(vc -> DCMAW_ASYNC.equals(vc.getCri())) + .findFirst(); + + if (dcmawAsyncVc.isEmpty()) { + return null; + } + + sessionCredentialsService.persistCredentials( + List.of(dcmawAsyncVc.get()), ipvSessionItem.getIpvSessionId(), false); + return criCheckingService.checkVcResponse( - List.of(vc), + List.of(dcmawAsyncVc.get()), request.getIpAddress(), clientOAuthSessionItem, ipvSessionItem, - sessionVcs); + sessionCredentialsService.getCredentials(ipvSessionItem.getIpvSessionId(), userId)); } private void validateSessionId(CheckMobileAppVcReceiptRequest request) diff --git a/lambdas/check-mobile-app-vc-receipt/src/test/java/uk/gov/di/ipv/core/checkmobileappvcreceipt/CheckMobileAppVcReceiptHandlerTest.java b/lambdas/check-mobile-app-vc-receipt/src/test/java/uk/gov/di/ipv/core/checkmobileappvcreceipt/CheckMobileAppVcReceiptHandlerTest.java index 4c45834dd0..b3b82cbd9d 100644 --- a/lambdas/check-mobile-app-vc-receipt/src/test/java/uk/gov/di/ipv/core/checkmobileappvcreceipt/CheckMobileAppVcReceiptHandlerTest.java +++ b/lambdas/check-mobile-app-vc-receipt/src/test/java/uk/gov/di/ipv/core/checkmobileappvcreceipt/CheckMobileAppVcReceiptHandlerTest.java @@ -24,10 +24,10 @@ import uk.gov.di.ipv.core.library.service.ClientOAuthSessionDetailsService; import uk.gov.di.ipv.core.library.service.ConfigService; import uk.gov.di.ipv.core.library.service.CriResponseService; +import uk.gov.di.ipv.core.library.service.EvcsService; import uk.gov.di.ipv.core.library.service.IpvSessionService; import uk.gov.di.ipv.core.library.testhelpers.unit.LogCollector; import uk.gov.di.ipv.core.library.verifiablecredential.service.SessionCredentialsService; -import uk.gov.di.ipv.core.library.verifiablecredential.service.VerifiableCredentialService; import uk.gov.di.ipv.core.processcricallback.service.CriCheckingService; import java.util.List; @@ -38,8 +38,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static uk.gov.di.ipv.core.library.enums.EvcsVCState.PENDING_RETURN; import static uk.gov.di.ipv.core.library.journeys.JourneyUris.JOURNEY_ABANDON_PATH; import static uk.gov.di.ipv.core.library.journeys.JourneyUris.JOURNEY_ERROR_PATH; import static uk.gov.di.ipv.core.library.journeys.JourneyUris.JOURNEY_NEXT_PATH; @@ -50,6 +55,7 @@ class CheckMobileAppVcReceiptHandlerTest { private static final String TEST_IPV_SESSION_ID = "test_ipv_session_id"; private static final String TEST_CLIENT_OAUTH_SESSION_ID = "test_client_oauth_id"; private static final String TEST_USER_ID = "test_user_id"; + private static final String TEST_EVCS_ACCESS_TOKEN = "TEST_EVCS_ACCESS_TOKEN"; @Mock private Context mockContext; @Mock private SignedJWT mockSignedJwt; @Mock private ConfigService configService; @@ -57,8 +63,8 @@ class CheckMobileAppVcReceiptHandlerTest { @Mock private ClientOAuthSessionDetailsService clientOAuthSessionDetailsService; @Mock private CriResponseService criResponseService; @Mock private CriCheckingService criCheckingService; - @Mock private VerifiableCredentialService verifiableCredentialService; @Mock private SessionCredentialsService sessionCredentialsService; + @Mock private EvcsService evcsService; @InjectMocks private CheckMobileAppVcReceiptHandler checkMobileAppVcReceiptHandler; @Test @@ -148,10 +154,12 @@ void shouldReturn200WhenCriResponseStatusPendingButVcExists() throws Exception { "vc", Map.of("type", List.of("IdentityAssertionCredential"))))); var vc = VerifiableCredential.fromValidJwt(TEST_USER_ID, Cri.DCMAW_ASYNC, mockSignedJwt); - when(verifiableCredentialService.getVc(TEST_USER_ID, "dcmawAsync")).thenReturn(vc); when(sessionCredentialsService.getCredentials( ipvSessionItem.getIpvSessionId(), TEST_USER_ID)) .thenReturn(List.of()); + when(evcsService.getVerifiableCredentials( + TEST_USER_ID, TEST_EVCS_ACCESS_TOKEN, PENDING_RETURN)) + .thenReturn(List.of(vc)); when(criCheckingService.checkVcResponse( List.of(vc), null, clientOAuthSessionItem, ipvSessionItem, List.of())) .thenReturn(new JourneyResponse(JOURNEY_NEXT_PATH)); @@ -163,6 +171,8 @@ void shouldReturn200WhenCriResponseStatusPendingButVcExists() throws Exception { // Assert assertEquals(HttpStatus.SC_OK, response.getStatusCode()); assertEquals(new JourneyResponse(JOURNEY_NEXT_PATH), journeyResponse); + verify(sessionCredentialsService) + .persistCredentials(List.of(vc), TEST_IPV_SESSION_ID, false); } @Test @@ -208,7 +218,7 @@ void shouldReturnErrorJourneyResponseWhenCriResponseStatusError() throws Excepti } @Test - void shouldReturn404WhenCriResponseStatusPendingAndVcNotFound() throws Exception { + void shouldReturn404WhenVcNotFound() throws Exception { // Arrange var requestEvent = buildValidRequestEventWithState(); when(ipvSessionService.getIpvSession(TEST_IPV_SESSION_ID)) @@ -218,6 +228,9 @@ void shouldReturn404WhenCriResponseStatusPendingAndVcNotFound() throws Exception var criResponseItem = buildValidCriResponseItem(CriResponseService.STATUS_PENDING); when(criResponseService.getCriResponseItem(TEST_USER_ID, Cri.DCMAW_ASYNC)) .thenReturn(criResponseItem); + when(evcsService.getVerifiableCredentials( + TEST_USER_ID, TEST_EVCS_ACCESS_TOKEN, PENDING_RETURN)) + .thenReturn(List.of()); // Act var response = checkMobileAppVcReceiptHandler.handleRequest(requestEvent, mockContext); @@ -225,6 +238,7 @@ void shouldReturn404WhenCriResponseStatusPendingAndVcNotFound() throws Exception // Assert assertEquals(HttpStatus.SC_NOT_FOUND, response.getStatusCode()); assertNull(response.getBody()); + verify(sessionCredentialsService, never()).persistCredentials(any(), any(), anyBoolean()); } @Test @@ -266,7 +280,10 @@ private IpvSessionItem buildValidIpvSessionItem() { } private ClientOAuthSessionItem buildValidClientOAuthSessionItem() { - return ClientOAuthSessionItem.builder().userId(TEST_USER_ID).build(); + return ClientOAuthSessionItem.builder() + .userId(TEST_USER_ID) + .evcsAccessToken(TEST_EVCS_ACCESS_TOKEN) + .build(); } private CriResponseItem buildValidCriResponseItem(String status) { diff --git a/lambdas/initialise-ipv-session/src/main/java/uk/gov/di/ipv/core/initialiseipvsession/InitialiseIpvSessionHandler.java b/lambdas/initialise-ipv-session/src/main/java/uk/gov/di/ipv/core/initialiseipvsession/InitialiseIpvSessionHandler.java index e3de29e5df..e619c6c379 100644 --- a/lambdas/initialise-ipv-session/src/main/java/uk/gov/di/ipv/core/initialiseipvsession/InitialiseIpvSessionHandler.java +++ b/lambdas/initialise-ipv-session/src/main/java/uk/gov/di/ipv/core/initialiseipvsession/InitialiseIpvSessionHandler.java @@ -67,8 +67,6 @@ import static uk.gov.di.ipv.core.library.auditing.extension.AuditExtensionsIpvJourneyStart.REPROVE_IDENTITY_KEY; import static uk.gov.di.ipv.core.library.auditing.helpers.AuditExtensionsHelper.getExtensionsForAudit; import static uk.gov.di.ipv.core.library.auditing.helpers.AuditExtensionsHelper.getRestrictedAuditDataForInheritedIdentity; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_READ_ENABLED; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_WRITE_ENABLED; import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.MFA_RESET; import static uk.gov.di.ipv.core.library.domain.Cri.HMRC_MIGRATION; import static uk.gov.di.ipv.core.library.domain.ScopeConstants.REVERIFICATION; @@ -199,7 +197,9 @@ public APIGatewayProxyResponseEvent handleRequest( clientOAuthSessionId, claimsSet, sessionParams.get(CLIENT_ID_PARAM_KEY), - getEvcsAccessToken(claimsSet)); + validateEvcsAccessToken( + getJarUserInfo(claimsSet).map(JarUserInfo::evcsAccessToken), + claimsSet)); AuditEventUser auditEventUser = new AuditEventUser( @@ -342,10 +342,8 @@ private void validateAndStoreHMRCInheritedIdentity( validateHmrcInheritedIdentity(userId, inheritedIdentityJwtClaim); sendInheritedIdentityReceivedAuditEvent( inheritedIdentityVc, auditEventUser, deviceInformation); - if (configService.enabled(EVCS_WRITE_ENABLED)) { - storeInheritedIdentity( - userId, ipvSessionItem, clientOAuthSessionItem, inheritedIdentityVc); - } + storeInheritedIdentity( + userId, ipvSessionItem, clientOAuthSessionItem, inheritedIdentityVc); } catch (VerifiableCredentialException | UnrecognisedVotException e) { throw new RecoverableJarValidationException( INVALID_INHERITED_IDENTITY_ERROR_OBJECT.setDescription( @@ -426,21 +424,6 @@ private boolean incomingInheritedIdHasStrongerOrEqualVot( return true; } - private String getEvcsAccessToken(JWTClaimsSet claimsSet) - throws RecoverableJarValidationException, ParseException { - try { - return validateEvcsAccessToken( - getJarUserInfo(claimsSet).map(JarUserInfo::evcsAccessToken), claimsSet); - } catch (RecoverableJarValidationException | ParseException e) { - if (configService.enabled(EVCS_WRITE_ENABLED) - || configService.enabled(EVCS_READ_ENABLED)) { - throw e; - } else { - return null; - } - } - } - private String validateEvcsAccessToken( Optional evcsAccessTokenClaim, JWTClaimsSet claimsSet) throws RecoverableJarValidationException, ParseException { diff --git a/lambdas/initialise-ipv-session/src/test/java/uk/gov/di/ipv/core/initialiseipvsession/InitialiseIpvSessionHandlerTest.java b/lambdas/initialise-ipv-session/src/test/java/uk/gov/di/ipv/core/initialiseipvsession/InitialiseIpvSessionHandlerTest.java index 0b27b248cf..91adb85268 100644 --- a/lambdas/initialise-ipv-session/src/test/java/uk/gov/di/ipv/core/initialiseipvsession/InitialiseIpvSessionHandlerTest.java +++ b/lambdas/initialise-ipv-session/src/test/java/uk/gov/di/ipv/core/initialiseipvsession/InitialiseIpvSessionHandlerTest.java @@ -109,7 +109,6 @@ import static org.mockito.Mockito.when; import static org.mockito.quality.Strictness.LENIENT; import static uk.gov.di.ipv.core.library.auditing.extension.AuditExtensionsIpvJourneyStart.REPROVE_IDENTITY_KEY; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_WRITE_ENABLED; import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.MFA_RESET; import static uk.gov.di.ipv.core.library.domain.Cri.HMRC_MIGRATION; import static uk.gov.di.ipv.core.library.domain.ErrorResponse.FAILED_TO_CONSTRUCT_EVCS_URI; @@ -153,7 +152,7 @@ class InitialiseIpvSessionHandlerTest { private static final String INVALID_INHERITED_IDENTITY = "invalid_inherited_identity"; private static final String INVALID_EVCS_ACCESS_TOKEN = "invalid_evcs_access_token"; private static final APIGatewayProxyRequestEvent validEvent = new APIGatewayProxyRequestEvent(); - public static final String TEST_EVCS_ACCESS_TOKEN = "TEST_EVCS_ACCESS_TOKEN"; + private static final String TEST_EVCS_ACCESS_TOKEN = "TEST_EVCS_ACCESS_TOKEN"; private static SignedJWT signedJWT; private static JWEObject signedEncryptedJwt; private static @Spy IpvSessionItem ipvSessionItem; @@ -162,6 +161,7 @@ class InitialiseIpvSessionHandlerTest { private static VerifiableCredential PCL200_MIGRATION_VC; private static VerifiableCredential pcl200MigrationWithEvidenceVc; + @Captor private ArgumentCaptor stringArgumentCaptor; @Mock private Context mockContext; @Mock private IpvSessionService mockIpvSessionService; @Mock private ClientOAuthSessionDetailsService mockClientOAuthSessionDetailsService; @@ -222,7 +222,6 @@ void checkAuditEventWait() { @Test void shouldReturnIpvSessionIdWhenProvidedValidRequest() throws JsonProcessingException, JarValidationException, ParseException { - ArgumentCaptor evcsAccessTokenCaptor = ArgumentCaptor.forClass(String.class); // Arrange when(mockIpvSessionService.generateIpvSession(any(), any(), any(), anyBoolean())) .thenReturn(ipvSessionItem); @@ -248,14 +247,13 @@ void shouldReturnIpvSessionIdWhenProvidedValidRequest() assertEquals(AuditEventTypes.IPV_JOURNEY_START, auditEventCaptor.getValue().getEventName()); verify(mockClientOAuthSessionDetailsService) - .generateClientSessionDetails(any(), any(), any(), evcsAccessTokenCaptor.capture()); - assertNull(evcsAccessTokenCaptor.getValue()); + .generateClientSessionDetails(any(), any(), any(), stringArgumentCaptor.capture()); + assertEquals(TEST_EVCS_ACCESS_TOKEN, stringArgumentCaptor.getValue()); } @Test void shouldReturnIpvSessionIdAndSendAuditEventWhenProvidedValidReproveRequest() throws JsonProcessingException, JarValidationException, ParseException { - ArgumentCaptor evcsAccessTokenCaptor = ArgumentCaptor.forClass(String.class); // Arrange when(mockConfigService.enabled(any(FeatureFlag.class))).thenReturn(false); when(mockIpvSessionService.generateIpvSession(any(), any(), any(), anyBoolean())) @@ -291,19 +289,24 @@ void shouldReturnIpvSessionIdAndSendAuditEventWhenProvidedValidReproveRequest() assertNull(extensions.getSuccess()); verify(mockClientOAuthSessionDetailsService) - .generateClientSessionDetails(any(), any(), any(), evcsAccessTokenCaptor.capture()); - assertNull(evcsAccessTokenCaptor.getValue()); + .generateClientSessionDetails(any(), any(), any(), stringArgumentCaptor.capture()); + assertEquals(TEST_EVCS_ACCESS_TOKEN, stringArgumentCaptor.getValue()); } @Test - void shouldRecoverIfEvcsEnabledButMissingEvcsAccesToken() throws Exception { + void shouldRecoverIfMissingEvcsAccessToken() throws Exception { // Arrange when(mockIpvSessionService.generateIpvSession(any(), any(), any(), anyBoolean())) .thenReturn(ipvSessionItem); when(mockConfigService.enabled(MFA_RESET)).thenReturn(false); - when(mockConfigService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); + var evcsAccessTokenClaims = + Map.of( + USER_INFO, + Map.of( + INHERITED_IDENTITY_JWT_CLAIM_NAME, + Map.of(VALUES, List.of(PCL200_MIGRATION_VC.getVcString())))); when(mockJarValidator.validateRequestJwt(any(), any())) - .thenReturn(signedJWT.getJWTClaimsSet()); + .thenReturn(getValidClaimsBuilder().claim(CLAIMS, evcsAccessTokenClaims).build()); // Act APIGatewayProxyResponseEvent response = @@ -335,16 +338,6 @@ void shouldRecoverIfEvcsEnabledButMissingEvcsAccesToken() throws Exception { @Test void shouldReturnIpvSessionIdWhenProvidedValidRequest_andSaveEvcsAccessToken() throws JsonProcessingException, JarValidationException, ParseException { - ArgumentCaptor evcsAccessTokenCaptor = ArgumentCaptor.forClass(String.class); - - var evcsAccessTokenClaims = - Map.of( - USER_INFO, - Map.of( - INHERITED_IDENTITY_JWT_CLAIM_NAME, - Map.of(VALUES, List.of(PCL200_MIGRATION_VC.getVcString())), - EVCS_ACCESS_TOKEN_CLAIM_NAME, - Map.of(VALUES, List.of(TEST_EVCS_ACCESS_TOKEN)))); // Arrange when(mockIpvSessionService.generateIpvSession(any(), any(), any(), anyBoolean())) .thenReturn(ipvSessionItem); @@ -352,7 +345,7 @@ void shouldReturnIpvSessionIdWhenProvidedValidRequest_andSaveEvcsAccessToken() any(), any(), any(), any())) .thenReturn(clientOAuthSessionItem); when(mockJarValidator.validateRequestJwt(any(), any())) - .thenReturn(getValidClaimsBuilder().claim(CLAIMS, evcsAccessTokenClaims).build()); + .thenReturn(signedJWT.getJWTClaimsSet()); when(mockConfigService.enabled(MFA_RESET)).thenReturn(false); // Act @@ -371,8 +364,8 @@ void shouldReturnIpvSessionIdWhenProvidedValidRequest_andSaveEvcsAccessToken() assertEquals(AuditEventTypes.IPV_JOURNEY_START, auditEventCaptor.getValue().getEventName()); verify(mockClientOAuthSessionDetailsService) - .generateClientSessionDetails(any(), any(), any(), evcsAccessTokenCaptor.capture()); - assertEquals(TEST_EVCS_ACCESS_TOKEN, evcsAccessTokenCaptor.getValue()); + .generateClientSessionDetails(any(), any(), any(), stringArgumentCaptor.capture()); + assertEquals(TEST_EVCS_ACCESS_TOKEN, stringArgumentCaptor.getValue()); } @ParameterizedTest @@ -385,7 +378,6 @@ void shouldRecoverIfEvcsAccessClaimsHasMultipleTokenValues( when(mockIpvSessionService.generateIpvSession(any(), any(), any(), anyBoolean())) .thenReturn(ipvSessionItem); when(mockConfigService.enabled(MFA_RESET)).thenReturn(false); - when(mockConfigService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); when(mockJarValidator.validateRequestJwt(any(), any())) .thenReturn(getValidClaimsBuilder().claim(CLAIMS, evcsAccessTokenClaims).build()); @@ -680,272 +672,259 @@ void setUp() throws Exception { .thenReturn(clientOAuthSessionItem); } - @Nested - @DisplayName("evcs turned on") - class EvcsTurnedOn { - @BeforeEach - void setUp() { - when(mockConfigService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); - } + @Test + void shouldStoreInheritedIdentityWhenNoExistingIdentity() throws Exception { + // Arrange + setupMocksForReceivedInheritedId(PCL200_MIGRATION_VC); + when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); + when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) + .thenReturn(List.of()); - @Test - void shouldStoreInheritedIdentityWhenNoExistingIdentity() throws Exception { - // Arrange - setupMocksForReceivedInheritedId(PCL200_MIGRATION_VC); - when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); - when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) - .thenReturn(List.of()); + // Act + initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); - // Act - initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); + // Assert + verify(mockEvcsService) + .storeInheritedIdentity(TEST_USER_ID, PCL200_MIGRATION_VC, List.of()); - // Assert - verify(mockEvcsService) - .storeInheritedIdentity(TEST_USER_ID, PCL200_MIGRATION_VC, List.of()); + InOrder inOrder = inOrder(ipvSessionItem, mockIpvSessionService); + inOrder.verify(ipvSessionItem).setInheritedIdentityReceivedThisSession(true); + inOrder.verify(mockIpvSessionService).updateIpvSession(ipvSessionItem); + } - InOrder inOrder = inOrder(ipvSessionItem, mockIpvSessionService); - inOrder.verify(ipvSessionItem).setInheritedIdentityReceivedThisSession(true); - inOrder.verify(mockIpvSessionService).updateIpvSession(ipvSessionItem); - } + @Test + void shouldStoreInheritedIdentityWhenVotEqualToExisting() throws Exception { + // Arrange + setupMocksForReceivedInheritedId(PCL200_MIGRATION_VC); + when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); + when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) + .thenReturn(List.of(PCL200_MIGRATION_VC)); - @Test - void shouldStoreInheritedIdentityWhenVotEqualToExisting() throws Exception { - // Arrange - setupMocksForReceivedInheritedId(PCL200_MIGRATION_VC); - when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); - when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) - .thenReturn(List.of(PCL200_MIGRATION_VC)); + // Act + initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); - // Act - initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); + // Assert + verify(mockEvcsService) + .storeInheritedIdentity( + TEST_USER_ID, PCL200_MIGRATION_VC, List.of(PCL200_MIGRATION_VC)); - // Assert - verify(mockEvcsService) - .storeInheritedIdentity( - TEST_USER_ID, PCL200_MIGRATION_VC, List.of(PCL200_MIGRATION_VC)); + InOrder inOrder = inOrder(ipvSessionItem, mockIpvSessionService); + inOrder.verify(ipvSessionItem).setInheritedIdentityReceivedThisSession(true); + inOrder.verify(mockIpvSessionService).updateIpvSession(ipvSessionItem); + } - InOrder inOrder = inOrder(ipvSessionItem, mockIpvSessionService); - inOrder.verify(ipvSessionItem).setInheritedIdentityReceivedThisSession(true); - inOrder.verify(mockIpvSessionService).updateIpvSession(ipvSessionItem); - } + @Test + void shouldStoreInheritedIdentityWhenVotEqualToMultipleExisting() throws Exception { + // Arrange + setupMocksForReceivedInheritedId(PCL200_MIGRATION_VC); + when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); + when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) + .thenReturn(List.of(PCL200_MIGRATION_VC, pcl200MigrationWithEvidenceVc)); - @Test - void shouldStoreInheritedIdentityWhenVotEqualToMultipleExisting() throws Exception { - // Arrange - setupMocksForReceivedInheritedId(PCL200_MIGRATION_VC); - when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); - when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) - .thenReturn(List.of(PCL200_MIGRATION_VC, pcl200MigrationWithEvidenceVc)); + // Act + initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); - // Act - initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); + // Assert + verify(mockEvcsService) + .storeInheritedIdentity( + TEST_USER_ID, + PCL200_MIGRATION_VC, + List.of(PCL200_MIGRATION_VC, pcl200MigrationWithEvidenceVc)); - // Assert - verify(mockEvcsService) - .storeInheritedIdentity( - TEST_USER_ID, - PCL200_MIGRATION_VC, - List.of(PCL200_MIGRATION_VC, pcl200MigrationWithEvidenceVc)); + InOrder inOrder = inOrder(ipvSessionItem, mockIpvSessionService); + inOrder.verify(ipvSessionItem).setInheritedIdentityReceivedThisSession(true); + inOrder.verify(mockIpvSessionService).updateIpvSession(ipvSessionItem); + } - InOrder inOrder = inOrder(ipvSessionItem, mockIpvSessionService); - inOrder.verify(ipvSessionItem).setInheritedIdentityReceivedThisSession(true); - inOrder.verify(mockIpvSessionService).updateIpvSession(ipvSessionItem); - } + @Test + void shouldStoreInheritedIdentityWhenVotStrongerThanExisting() throws Exception { + // Arrange + setupMocksForReceivedInheritedId(PCL250_MIGRATION_VC); + when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); + when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) + .thenReturn(List.of(PCL200_MIGRATION_VC)); - @Test - void shouldStoreInheritedIdentityWhenVotStrongerThanExisting() throws Exception { - // Arrange - setupMocksForReceivedInheritedId(PCL250_MIGRATION_VC); - when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); - when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) - .thenReturn(List.of(PCL200_MIGRATION_VC)); + // Act + initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); - // Act - initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); + // Assert + verify(mockEvcsService) + .storeInheritedIdentity( + TEST_USER_ID, PCL250_MIGRATION_VC, List.of(PCL200_MIGRATION_VC)); - // Assert - verify(mockEvcsService) - .storeInheritedIdentity( - TEST_USER_ID, PCL250_MIGRATION_VC, List.of(PCL200_MIGRATION_VC)); + InOrder inOrder = inOrder(ipvSessionItem, mockIpvSessionService); + inOrder.verify(ipvSessionItem).setInheritedIdentityReceivedThisSession(true); + inOrder.verify(mockIpvSessionService).updateIpvSession(ipvSessionItem); + } - InOrder inOrder = inOrder(ipvSessionItem, mockIpvSessionService); - inOrder.verify(ipvSessionItem).setInheritedIdentityReceivedThisSession(true); - inOrder.verify(mockIpvSessionService).updateIpvSession(ipvSessionItem); - } + @Test + void shouldStoreInheritedIdentityWhenVotStrongerThanMultipleExisting() throws Exception { + // Arrange + setupMocksForReceivedInheritedId(PCL250_MIGRATION_VC); + when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); + when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) + .thenReturn(List.of(PCL200_MIGRATION_VC, pcl200MigrationWithEvidenceVc)); - @Test - void shouldStoreInheritedIdentityWhenVotStrongerThanMultipleExisting() - throws Exception { - // Arrange - setupMocksForReceivedInheritedId(PCL250_MIGRATION_VC); - when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); - when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) - .thenReturn(List.of(PCL200_MIGRATION_VC, pcl200MigrationWithEvidenceVc)); + // Act + initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); - // Act - initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); + // Assert + verify(mockEvcsService) + .storeInheritedIdentity( + TEST_USER_ID, + PCL250_MIGRATION_VC, + List.of(PCL200_MIGRATION_VC, pcl200MigrationWithEvidenceVc)); - // Assert - verify(mockEvcsService) - .storeInheritedIdentity( - TEST_USER_ID, - PCL250_MIGRATION_VC, - List.of(PCL200_MIGRATION_VC, pcl200MigrationWithEvidenceVc)); + InOrder inOrder = inOrder(ipvSessionItem, mockIpvSessionService); + inOrder.verify(ipvSessionItem).setInheritedIdentityReceivedThisSession(true); + inOrder.verify(mockIpvSessionService).updateIpvSession(ipvSessionItem); + } - InOrder inOrder = inOrder(ipvSessionItem, mockIpvSessionService); - inOrder.verify(ipvSessionItem).setInheritedIdentityReceivedThisSession(true); - inOrder.verify(mockIpvSessionService).updateIpvSession(ipvSessionItem); - } + @Test + void shouldNotStoreInheritedIdentityWhenVotWeakerThanExisting() throws Exception { + // Arrange + setupMocksForReceivedInheritedId(PCL200_MIGRATION_VC); + when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); + when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) + .thenReturn(List.of(PCL250_MIGRATION_VC)); - @Test - void shouldNotStoreInheritedIdentityWhenVotWeakerThanExisting() throws Exception { - // Arrange - setupMocksForReceivedInheritedId(PCL200_MIGRATION_VC); - when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); - when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) - .thenReturn(List.of(PCL250_MIGRATION_VC)); + // Act + initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); - // Act - initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); + // Assert + verify(mockEvcsService, never()).storeInheritedIdentity(any(), any(), any()); + } - // Assert - verify(mockEvcsService, never()).storeInheritedIdentity(any(), any(), any()); - } + @Test + void shouldNotStoreInheritedIdentityWhenVotWeakerThanAnyExisting() throws Exception { + // Arrange + setupMocksForReceivedInheritedId(PCL200_MIGRATION_VC); + when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); + when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) + .thenReturn(List.of(PCL200_MIGRATION_VC, PCL250_MIGRATION_VC)); - @Test - void shouldNotStoreInheritedIdentityWhenVotWeakerThanAnyExisting() throws Exception { - // Arrange - setupMocksForReceivedInheritedId(PCL200_MIGRATION_VC); - when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); - when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) - .thenReturn(List.of(PCL200_MIGRATION_VC, PCL250_MIGRATION_VC)); + // Act + initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); - // Act - initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); + // Assert + verify(mockEvcsService, never()).storeInheritedIdentity(any(), any(), any()); + } - // Assert - verify(mockEvcsService, never()).storeInheritedIdentity(any(), any(), any()); - } + @Test + void shouldSendAuditEventForIpvInheritedIdentityVcReceived() throws Exception { + // Arrange + setupMocksForReceivedInheritedId(PCL200_MIGRATION_VC); + when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); + when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) + .thenReturn(List.of()); - @Test - void shouldSendAuditEventForIpvInheritedIdentityVcReceived() throws Exception { - // Arrange - setupMocksForReceivedInheritedId(PCL200_MIGRATION_VC); - when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); - when(mockEvcsService.getVerifiableCredentials(eq(TEST_USER_ID), any(), eq(CURRENT))) - .thenReturn(List.of()); + // Act + initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); - // Act - initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); + // Assert + ArgumentCaptor auditEventCaptor = ArgumentCaptor.forClass(AuditEvent.class); + verify(mockAuditService, times(2)).sendAuditEvent(auditEventCaptor.capture()); - // Assert - ArgumentCaptor auditEventCaptor = - ArgumentCaptor.forClass(AuditEvent.class); - verify(mockAuditService, times(2)).sendAuditEvent(auditEventCaptor.capture()); - - var inheritedIdentityAuditEvent = auditEventCaptor.getAllValues().get(0); - assertEquals( - AuditEventTypes.IPV_INHERITED_IDENTITY_VC_RECEIVED, - inheritedIdentityAuditEvent.getEventName()); - - var extension = inheritedIdentityAuditEvent.getExtensions(); - var expectedExtension = - new AuditExtensionsVcEvidence( - "https://orch.stubs.account.gov.uk/migration/v1", - List.of(), - null, - Vot.PCL200, - Boolean.TRUE, - Period.between(LocalDate.parse(TestVc.DEFAULT_DOB), LocalDate.now()) - .getYears()); - assertEquals(expectedExtension, extension); - - var restricted = - (AuditRestrictedInheritedIdentity) - inheritedIdentityAuditEvent.getRestricted(); - var expectedName = - List.of( - createName( - List.of( - createNamePart( - "KENNETH", - NamePart.NamePartType.GIVEN_NAME), - createNamePart( - "DECERQUEIRA", - NamePart.NamePartType.FAMILY_NAME)))); - - var expectedBirthDate = List.of(createBirthDate("1965-07-08")); - var expectedSocialSecurityRecord = - List.of( - createSocialSecurityRecordDetails( - "AB123456C")); // pragma: allowlist secret - assertEquals(expectedName, restricted.name()); - assertEquals(expectedBirthDate, restricted.birthDate()); - assertEquals(expectedSocialSecurityRecord, restricted.socialSecurityRecord()); - - assertEquals( - AuditEventTypes.IPV_JOURNEY_START, - auditEventCaptor.getAllValues().get(1).getEventName()); - } + var inheritedIdentityAuditEvent = auditEventCaptor.getAllValues().get(0); + assertEquals( + AuditEventTypes.IPV_INHERITED_IDENTITY_VC_RECEIVED, + inheritedIdentityAuditEvent.getEventName()); + + var extension = inheritedIdentityAuditEvent.getExtensions(); + var expectedExtension = + new AuditExtensionsVcEvidence( + "https://orch.stubs.account.gov.uk/migration/v1", + List.of(), + null, + Vot.PCL200, + Boolean.TRUE, + Period.between(LocalDate.parse(TestVc.DEFAULT_DOB), LocalDate.now()) + .getYears()); + assertEquals(expectedExtension, extension); + + var restricted = + (AuditRestrictedInheritedIdentity) inheritedIdentityAuditEvent.getRestricted(); + var expectedName = + List.of( + createName( + List.of( + createNamePart( + "KENNETH", NamePart.NamePartType.GIVEN_NAME), + createNamePart( + "DECERQUEIRA", + NamePart.NamePartType.FAMILY_NAME)))); + + var expectedBirthDate = List.of(createBirthDate("1965-07-08")); + var expectedSocialSecurityRecord = + List.of( + createSocialSecurityRecordDetails( + "AB123456C")); // pragma: allowlist secret + assertEquals(expectedName, restricted.name()); + assertEquals(expectedBirthDate, restricted.birthDate()); + assertEquals(expectedSocialSecurityRecord, restricted.socialSecurityRecord()); - @Test - void shouldRecoverIfInheritedIdentityJwtFailsToPersist() throws Exception { - // Arrange - when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); - when(mockJarValidator.validateRequestJwt(any(), any())) - .thenReturn( - getValidClaimsBuilder() - .claim( - CLAIMS, - Map.of( - USER_INFO, - Map.of( - INHERITED_IDENTITY_JWT_CLAIM_NAME, - Map.of( - VALUES, - List.of( - PCL200_MIGRATION_VC - .getVcString())), - EVCS_ACCESS_TOKEN_CLAIM_NAME, - Map.of( - VALUES, - List.of( - TEST_EVCS_ACCESS_TOKEN))))) - .build()); - when(mockConfigService.getCriConfig(HMRC_MIGRATION)).thenReturn(TEST_CRI_CONFIG); - when(mockVerifiableCredentialValidator.parseAndValidate( - TEST_USER_ID, - HMRC_MIGRATION, - PCL200_MIGRATION_VC.getVcString(), - TEST_SIGNING_KEY, - TEST_COMPONENT_ID, - true)) - .thenReturn(PCL200_MIGRATION_VC); - when(mockEvcsService.getVerifiableCredentials(any(), any(), any())) - .thenReturn(List.of()); - - doThrow(new EvcsServiceException(SC_SERVER_ERROR, FAILED_TO_CONSTRUCT_EVCS_URI)) - .when(mockEvcsService) - .storeInheritedIdentity(any(), any(), any()); - - // Act - APIGatewayProxyResponseEvent response = - initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); - - // Assert - Map responseBody = - OBJECT_MAPPER.readValue(response.getBody(), new TypeReference<>() {}); - - assertEquals(HttpStatus.SC_OK, response.getStatusCode()); - assertEquals(ipvSessionItem.getIpvSessionId(), responseBody.get("ipvSessionId")); - verify(mockClientOAuthSessionDetailsService) - .generateErrorClientSessionDetails( - any(String.class), - eq("https://example.com"), - eq("test-client"), - eq("test-state"), - eq(null)); - } + assertEquals( + AuditEventTypes.IPV_JOURNEY_START, + auditEventCaptor.getAllValues().get(1).getEventName()); + } + + @Test + void shouldRecoverIfInheritedIdentityJwtFailsToPersist() throws Exception { + // Arrange + when(mockUserIdentityService.getVot(any())).thenCallRealMethod(); + when(mockJarValidator.validateRequestJwt(any(), any())) + .thenReturn( + getValidClaimsBuilder() + .claim( + CLAIMS, + Map.of( + USER_INFO, + Map.of( + INHERITED_IDENTITY_JWT_CLAIM_NAME, + Map.of( + VALUES, + List.of( + PCL200_MIGRATION_VC + .getVcString())), + EVCS_ACCESS_TOKEN_CLAIM_NAME, + Map.of( + VALUES, + List.of( + TEST_EVCS_ACCESS_TOKEN))))) + .build()); + when(mockConfigService.getCriConfig(HMRC_MIGRATION)).thenReturn(TEST_CRI_CONFIG); + when(mockVerifiableCredentialValidator.parseAndValidate( + TEST_USER_ID, + HMRC_MIGRATION, + PCL200_MIGRATION_VC.getVcString(), + TEST_SIGNING_KEY, + TEST_COMPONENT_ID, + true)) + .thenReturn(PCL200_MIGRATION_VC); + when(mockEvcsService.getVerifiableCredentials(any(), any(), any())) + .thenReturn(List.of()); + + doThrow(new EvcsServiceException(SC_SERVER_ERROR, FAILED_TO_CONSTRUCT_EVCS_URI)) + .when(mockEvcsService) + .storeInheritedIdentity(any(), any(), any()); + + // Act + APIGatewayProxyResponseEvent response = + initialiseIpvSessionHandler.handleRequest(validEvent, mockContext); + + // Assert + Map responseBody = + OBJECT_MAPPER.readValue(response.getBody(), new TypeReference<>() {}); + + assertEquals(HttpStatus.SC_OK, response.getStatusCode()); + assertEquals(ipvSessionItem.getIpvSessionId(), responseBody.get("ipvSessionId")); + verify(mockClientOAuthSessionDetailsService) + .generateErrorClientSessionDetails( + any(String.class), + eq("https://example.com"), + eq("test-client"), + eq("test-state"), + eq(null)); } @Test @@ -1510,6 +1489,8 @@ private static JWTClaimsSet.Builder getValidClaimsBuilder() { INHERITED_IDENTITY_JWT_CLAIM_NAME, Map.of(VALUES, List.of()), PASSPORT_CLAIM_NAME, - new Essential(true)))); + new Essential(true), + EVCS_ACCESS_TOKEN_CLAIM_NAME, + Map.of(VALUES, List.of(TEST_EVCS_ACCESS_TOKEN))))); } } diff --git a/lambdas/process-async-cri-credential/src/main/java/uk/gov/di/ipv/core/processasynccricredential/ProcessAsyncCriCredentialHandler.java b/lambdas/process-async-cri-credential/src/main/java/uk/gov/di/ipv/core/processasynccricredential/ProcessAsyncCriCredentialHandler.java index f940ee4011..c67b3e1b8c 100644 --- a/lambdas/process-async-cri-credential/src/main/java/uk/gov/di/ipv/core/processasynccricredential/ProcessAsyncCriCredentialHandler.java +++ b/lambdas/process-async-cri-credential/src/main/java/uk/gov/di/ipv/core/processasynccricredential/ProcessAsyncCriCredentialHandler.java @@ -34,23 +34,18 @@ import uk.gov.di.ipv.core.library.service.CriResponseService; import uk.gov.di.ipv.core.library.service.EvcsService; import uk.gov.di.ipv.core.library.verifiablecredential.helpers.VcHelper; -import uk.gov.di.ipv.core.library.verifiablecredential.service.VerifiableCredentialService; import uk.gov.di.ipv.core.library.verifiablecredential.validator.VerifiableCredentialValidator; -import uk.gov.di.ipv.core.processasynccricredential.domain.BaseAsyncCriResponse; import uk.gov.di.ipv.core.processasynccricredential.domain.ErrorAsyncCriResponse; import uk.gov.di.ipv.core.processasynccricredential.domain.SuccessAsyncCriResponse; import uk.gov.di.ipv.core.processasynccricredential.exceptions.AsyncVerifiableCredentialException; import java.text.ParseException; -import java.time.Instant; import java.util.ArrayList; import java.util.List; import java.util.Optional; import static uk.gov.di.ipv.core.library.auditing.helpers.AuditExtensionsHelper.getExtensionsForAudit; import static uk.gov.di.ipv.core.library.auditing.helpers.AuditExtensionsHelper.getRestrictedAuditDataForF2F; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_ASYNC_WRITE_ENABLED; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_READ_ENABLED; import static uk.gov.di.ipv.core.library.domain.ErrorResponse.UNEXPECTED_ASYNC_VERIFIABLE_CREDENTIAL; import static uk.gov.di.ipv.core.library.helpers.LogHelper.LogField.LOG_ERROR_CODE; import static uk.gov.di.ipv.core.library.helpers.LogHelper.LogField.LOG_ERROR_DESCRIPTION; @@ -62,7 +57,6 @@ public class ProcessAsyncCriCredentialHandler implements RequestHandler { private static final Logger LOGGER = LogManager.getLogger(); private final ConfigService configService; - private final VerifiableCredentialService verifiableCredentialService; private final VerifiableCredentialValidator verifiableCredentialValidator; private final AuditService auditService; private final CimitService cimitService; @@ -71,7 +65,6 @@ public class ProcessAsyncCriCredentialHandler public ProcessAsyncCriCredentialHandler( ConfigService configService, - VerifiableCredentialService verifiableCredentialService, VerifiableCredentialValidator verifiableCredentialValidator, AuditService auditService, CimitService cimitService, @@ -79,7 +72,6 @@ public ProcessAsyncCriCredentialHandler( EvcsService evcsService) { this.configService = configService; this.verifiableCredentialValidator = verifiableCredentialValidator; - this.verifiableCredentialService = verifiableCredentialService; this.auditService = auditService; this.cimitService = cimitService; this.criResponseService = criResponseService; @@ -91,7 +83,6 @@ public ProcessAsyncCriCredentialHandler( public ProcessAsyncCriCredentialHandler() { this.configService = ConfigService.create(); this.verifiableCredentialValidator = new VerifiableCredentialValidator(configService); - this.verifiableCredentialService = new VerifiableCredentialService(configService); this.auditService = AuditService.create(configService); this.cimitService = new CimitService(configService); this.criResponseService = new CriResponseService(configService); @@ -105,10 +96,10 @@ public ProcessAsyncCriCredentialHandler() { public SQSBatchResponse handleRequest(SQSEvent event, Context context) { try { LogHelper.attachComponentId(configService); - List failedRecords = new ArrayList<>(); + var failedRecords = new ArrayList(); - for (SQSMessage message : event.getRecords()) { - failedRecords.addAll(processOrReturnItemFailure(message)); + for (var sqsMessage : event.getRecords()) { + failedRecords.addAll(processOrReturnItemFailure(sqsMessage)); } return SQSBatchResponse.builder().withBatchItemFailures(failedRecords).build(); @@ -122,8 +113,7 @@ public SQSBatchResponse handleRequest(SQSEvent event, Context context) { private List processOrReturnItemFailure(SQSMessage message) { try { - final BaseAsyncCriResponse asyncCriResponse = - getAsyncResponseMessage(message.getBody()); + final var asyncCriResponse = getAsyncResponseMessage(message.getBody()); if (isSuccessAsyncCriResponse(asyncCriResponse)) { processSuccessAsyncCriResponse((SuccessAsyncCriResponse) asyncCriResponse); } else { @@ -193,9 +183,8 @@ private void processSuccessAsyncCriResponse(SuccessAsyncCriResponse successAsync HttpResponseExceptionWithErrorBody { var userId = successAsyncCriResponse.getUserId(); var state = successAsyncCriResponse.getOauthState(); - Optional criResponseItem = - criResponseService.getCriResponseItemWithState(userId, state); + var criResponseItem = criResponseService.getCriResponseItemWithState(userId, state); if (criResponseItem.isEmpty()) { LOGGER.error( LogHelper.buildLogMessage("No response item found given user id and state")); @@ -217,29 +206,12 @@ private void processSuccessAsyncCriResponse(SuccessAsyncCriResponse successAsync oauthCriConfig.getComponentId()); for (var vc : vcs) { - boolean isSuccessful = VcHelper.isSuccessfulVc(vc); - - AuditEventUser auditEventUser = new AuditEventUser(userId, null, null, null); - sendIpvVcReceivedAuditEvent(auditEventUser, vc, cri, isSuccessful); + var auditEventUser = new AuditEventUser(userId, null, null, null); + sendIpvVcReceivedAuditEvent(auditEventUser, vc, cri, VcHelper.isSuccessfulVc(vc)); submitVcToCiStorage(vc); postMitigatingVc(vc); - - if (configService.enabled(EVCS_ASYNC_WRITE_ENABLED)) { - try { - evcsService.storePendingVc(vc); - vc.setMigrated(Instant.now()); - } catch (EvcsServiceException e) { - if (configService.enabled(EVCS_READ_ENABLED)) { - throw e; - } else { - LOGGER.error( - LogHelper.buildErrorMessage("Failed to store EVCS async VC", e)); - } - } - } - verifiableCredentialService.persistUserCredentials(vc); - + evcsService.storePendingVc(vc); sendIpvVcConsumedAuditEvent(auditEventUser, vc, cri); } } diff --git a/lambdas/process-async-cri-credential/src/test/java/uk/gov/di/ipv/core/processasynccricredential/ProcessAsyncCriCredentialHandlerTest.java b/lambdas/process-async-cri-credential/src/test/java/uk/gov/di/ipv/core/processasynccricredential/ProcessAsyncCriCredentialHandlerTest.java index 25add1d2af..198e990392 100644 --- a/lambdas/process-async-cri-credential/src/test/java/uk/gov/di/ipv/core/processasynccricredential/ProcessAsyncCriCredentialHandlerTest.java +++ b/lambdas/process-async-cri-credential/src/test/java/uk/gov/di/ipv/core/processasynccricredential/ProcessAsyncCriCredentialHandlerTest.java @@ -9,9 +9,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; import org.mockito.ArgumentCaptor; +import org.mockito.Captor; import org.mockito.InOrder; import org.mockito.InjectMocks; import org.mockito.Mock; @@ -23,7 +22,6 @@ import uk.gov.di.ipv.core.library.domain.Cri; import uk.gov.di.ipv.core.library.domain.VerifiableCredential; import uk.gov.di.ipv.core.library.dto.OauthCriConfig; -import uk.gov.di.ipv.core.library.exception.EvcsServiceException; import uk.gov.di.ipv.core.library.exceptions.VerifiableCredentialException; import uk.gov.di.ipv.core.library.persistence.item.CriResponseItem; import uk.gov.di.ipv.core.library.service.AuditService; @@ -32,14 +30,12 @@ import uk.gov.di.ipv.core.library.service.CriResponseService; import uk.gov.di.ipv.core.library.service.EvcsService; import uk.gov.di.ipv.core.library.testhelpers.unit.LogCollector; -import uk.gov.di.ipv.core.library.verifiablecredential.service.VerifiableCredentialService; import uk.gov.di.ipv.core.library.verifiablecredential.validator.VerifiableCredentialValidator; import uk.gov.di.ipv.core.processasynccricredential.dto.CriResponseMessageDto; import java.net.URI; import java.net.URISyntaxException; import java.util.List; -import java.util.Objects; import java.util.Optional; import java.util.UUID; @@ -57,7 +53,6 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_ASYNC_WRITE_ENABLED; import static uk.gov.di.ipv.core.library.domain.Cri.F2F; import static uk.gov.di.ipv.core.library.fixtures.TestFixtures.EC_PRIVATE_KEY_JWK; import static uk.gov.di.ipv.core.library.fixtures.VcFixtures.vcF2fM1a; @@ -80,7 +75,7 @@ class ProcessAsyncCriCredentialHandlerTest { null, CriResponseService.STATUS_PENDING, 0, - List.of(EVCS_ASYNC_WRITE_ENABLED.getName())); + List.of()); private static final String TEST_ASYNC_ACCESS_DENIED_ERROR = "access_denied"; private static final String TEST_ASYNC_ERROR = "invalid"; @@ -91,9 +86,9 @@ class ProcessAsyncCriCredentialHandlerTest { private static OauthCriConfig TEST_CREDENTIAL_ISSUER_CONFIG; private VerifiableCredential F2F_VC; + @Captor private ArgumentCaptor vcArgumentCaptor; @Mock private ConfigService configService; @Mock private VerifiableCredentialValidator verifiableCredentialValidator; - @Mock private VerifiableCredentialService verifiableCredentialService; @Mock private AuditService auditService; @Mock private CimitService cimitService; @Mock private CriResponseService criResponseService; @@ -117,52 +112,24 @@ void checkAuditEventWait() { auditInOrder.verifyNoMoreInteractions(); } - @ParameterizedTest - @ValueSource(booleans = {true, false}) - void shouldProcessValidExpectedAsyncVerifiableCredentialSuccessfully(boolean evcsAsyncWrites) - throws Exception { - final SQSEvent testEvent = createSuccessTestEvent(TEST_OAUTH_STATE); - - when(verifiableCredentialValidator.parseAndValidate( - eq(TEST_USER_ID), eq(F2F), anyList(), any(), any())) - .thenReturn(List.of(F2F_VC)); - when(criResponseService.getCriResponseItemWithState(TEST_USER_ID, TEST_OAUTH_STATE)) - .thenReturn(Optional.of(TEST_CRI_RESPONSE_ITEM)); - mockCredentialIssuerConfig(); - when(configService.enabled(EVCS_ASYNC_WRITE_ENABLED)).thenReturn(evcsAsyncWrites); - - final SQSBatchResponse batchResponse = handler.handleRequest(testEvent, null); - - assertEquals(0, batchResponse.getBatchItemFailures().size()); - - verifyVerifiableCredentialJwtValidator(); - verifyCiStorageServicePutContraIndicators(); - verifyCiStorageServicePostMitigations(); - verifyVerifiableCredentialService(evcsAsyncWrites); - verify(evcsService, times(evcsAsyncWrites ? 1 : 0)).storePendingVc(F2F_VC); - verifyAuditService(); - } - @Test - void shouldProcessSuccessfullyIfEvcsFailsAndEvcsReadsIsNotEnabled() throws Exception { - final SQSEvent testEvent = createSuccessTestEvent(TEST_OAUTH_STATE); - + void shouldProcessValidExpectedAsyncVerifiableCredentialSuccessfully() throws Exception { when(verifiableCredentialValidator.parseAndValidate( eq(TEST_USER_ID), eq(F2F), anyList(), any(), any())) .thenReturn(List.of(F2F_VC)); when(criResponseService.getCriResponseItemWithState(TEST_USER_ID, TEST_OAUTH_STATE)) .thenReturn(Optional.of(TEST_CRI_RESPONSE_ITEM)); mockCredentialIssuerConfig(); - when(configService.enabled(EVCS_ASYNC_WRITE_ENABLED)).thenReturn(true); - doThrow(EvcsServiceException.class).when(evcsService).storePendingVc(F2F_VC); - final SQSBatchResponse batchResponse = handler.handleRequest(testEvent, null); + var batchResponse = handler.handleRequest(createSuccessTestEvent(TEST_OAUTH_STATE), null); assertEquals(0, batchResponse.getBatchItemFailures().size()); verifyVerifiableCredentialJwtValidator(); verifyCiStorageServicePutContraIndicators(); verifyCiStorageServicePostMitigations(); + verifyVerifiableCredentialService(); + verify(evcsService).storePendingVc(F2F_VC); verifyAuditService(); } @@ -277,7 +244,6 @@ void willNotPersistVerifiableCredentialIfFailsToPutCredentialToCIMIT() throws Ex assertEquals(1, auditEvents.size()); assertEquals(AuditEventTypes.IPV_F2F_CRI_VC_RECEIVED, auditEvents.get(0).getEventName()); - verify(verifiableCredentialService, never()).persistUserCredentials(any()); verify(evcsService, never()).storePendingVc(any()); verifyBatchResponseFailures(testEvent, batchResponse); @@ -305,7 +271,6 @@ void willNotPersistVerifiableCredentialIfFailsToPostMitigatingCredentialToCIMIT( verify(auditService, times(1)) .sendAuditEvent(ArgumentCaptor.forClass(AuditEvent.class).capture()); verify(cimitService, times(1)).submitVC(any(), any(), any()); - verify(verifiableCredentialService, never()).persistUserCredentials(any()); verify(evcsService, never()).storePendingVc(any()); verifyBatchResponseFailures(testEvent, batchResponse); @@ -426,21 +391,17 @@ private void verifyCiStorageServicePostMitigations() throws Exception { assertNull(ciIpAddresses.get(0)); } - private void verifyVerifiableCredentialService(boolean evcsWrites) throws Exception { - var vcCaptor = ArgumentCaptor.forClass(VerifiableCredential.class); - - verify(verifiableCredentialService, times(1)).persistUserCredentials(vcCaptor.capture()); + private void verifyVerifiableCredentialService() throws Exception { + verify(evcsService).storePendingVc(vcArgumentCaptor.capture()); - var storedVcs = vcCaptor.getAllValues(); + var storedVcs = vcArgumentCaptor.getAllValues(); assertEquals(1, storedVcs.size()); assertEquals(F2F_VC, storedVcs.get(0)); - assertEquals(evcsWrites, !Objects.isNull(storedVcs.get(0).getMigrated())); } private void verifyVerifiableCredentialNotProcessedFurther() throws Exception { verify(auditService, never()) .sendAuditEvent(ArgumentCaptor.forClass(AuditEvent.class).capture()); - verify(verifiableCredentialService, never()).persistUserCredentials(any()); verify(evcsService, never()).storePendingVc(any()); verify(cimitService, never()).submitVC(any(), any(), any()); verify(cimitService, never()).submitMitigatingVcList(any(), any(), any()); diff --git a/lambdas/reset-session-identity/src/main/java/uk/gov/di/ipv/core/resetsessionidentity/ResetSessionIdentityHandler.java b/lambdas/reset-session-identity/src/main/java/uk/gov/di/ipv/core/resetsessionidentity/ResetSessionIdentityHandler.java index d27c8deda5..904690c08a 100644 --- a/lambdas/reset-session-identity/src/main/java/uk/gov/di/ipv/core/resetsessionidentity/ResetSessionIdentityHandler.java +++ b/lambdas/reset-session-identity/src/main/java/uk/gov/di/ipv/core/resetsessionidentity/ResetSessionIdentityHandler.java @@ -26,13 +26,10 @@ import uk.gov.di.ipv.core.library.service.EvcsService; import uk.gov.di.ipv.core.library.service.IpvSessionService; import uk.gov.di.ipv.core.library.verifiablecredential.service.SessionCredentialsService; -import uk.gov.di.ipv.core.library.verifiablecredential.service.VerifiableCredentialService; import java.util.Map; import static org.apache.http.HttpStatus.SC_INTERNAL_SERVER_ERROR; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_READ_ENABLED; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_WRITE_ENABLED; import static uk.gov.di.ipv.core.library.domain.Cri.F2F; import static uk.gov.di.ipv.core.library.domain.ErrorResponse.FAILED_TO_PARSE_ISSUED_CREDENTIALS; import static uk.gov.di.ipv.core.library.domain.ErrorResponse.IPV_SESSION_NOT_FOUND; @@ -56,7 +53,6 @@ public class ResetSessionIdentityHandler private final SessionCredentialsService sessionCredentialsService; private final ClientOAuthSessionDetailsService clientOAuthSessionDetailsService; private final CriResponseService criResponseService; - private final VerifiableCredentialService verifiableCredentialService; private final EvcsService evcsService; public ResetSessionIdentityHandler( @@ -65,14 +61,12 @@ public ResetSessionIdentityHandler( SessionCredentialsService sessionCredentialsService, ClientOAuthSessionDetailsService clientOAuthSessionDetailsService, CriResponseService criResponseService, - VerifiableCredentialService verifiableCredentialService, EvcsService evcsService) { this.configService = configService; this.ipvSessionService = ipvSessionService; this.sessionCredentialsService = sessionCredentialsService; this.clientOAuthSessionDetailsService = clientOAuthSessionDetailsService; this.criResponseService = criResponseService; - this.verifiableCredentialService = verifiableCredentialService; this.evcsService = evcsService; } @@ -88,7 +82,6 @@ public ResetSessionIdentityHandler(ConfigService configService) { this.sessionCredentialsService = new SessionCredentialsService(configService); this.clientOAuthSessionDetailsService = new ClientOAuthSessionDetailsService(configService); this.criResponseService = new CriResponseService(configService); - this.verifiableCredentialService = new VerifiableCredentialService(configService); this.evcsService = new EvcsService(configService); } @@ -119,13 +112,10 @@ public Map handleRequest(ProcessRequest input, Context context) if (sessionCredentialsResetType == REINSTATE) { var existingIdentityVcs = - configService.enabled(EVCS_READ_ENABLED) - ? evcsService.getVerifiableCredentials( - clientOAuthSessionItem.getUserId(), - clientOAuthSessionItem.getEvcsAccessToken(), - CURRENT) - : verifiableCredentialService.getVcs( - clientOAuthSessionItem.getUserId()); + evcsService.getVerifiableCredentials( + clientOAuthSessionItem.getUserId(), + clientOAuthSessionItem.getEvcsAccessToken(), + CURRENT); sessionCredentialsService.persistCredentials( existingIdentityVcs, ipvSessionId, false); LOGGER.info( @@ -171,26 +161,10 @@ public Map handleRequest(ProcessRequest input, Context context) } private void doResetForPendingF2f(ClientOAuthSessionItem clientOAuthSessionItem) - throws VerifiableCredentialException, EvcsServiceException { - String userId = clientOAuthSessionItem.getUserId(); + throws EvcsServiceException { + var userId = clientOAuthSessionItem.getUserId(); criResponseService.deleteCriResponseItem(userId, F2F); - verifiableCredentialService.deleteVCs(userId); - updateEvcsPendingIdentity(userId, clientOAuthSessionItem.getEvcsAccessToken()); + evcsService.abandonPendingIdentity(userId, clientOAuthSessionItem.getEvcsAccessToken()); LOGGER.info(LogHelper.buildLogMessage("Reset done for F2F pending identity.")); } - - private void updateEvcsPendingIdentity(String userId, String evcsAccessToken) - throws EvcsServiceException { - try { - if (configService.enabled(EVCS_WRITE_ENABLED)) { - evcsService.abandonPendingIdentity(userId, evcsAccessToken); - } - } catch (EvcsServiceException e) { - if (configService.enabled(EVCS_READ_ENABLED)) { - throw e; - } else { - LOGGER.error(LogHelper.buildErrorMessage("Failed to update EVCS identity", e)); - } - } - } } diff --git a/lambdas/reset-session-identity/src/test/java/uk/gov/di/ipv/core/resetsessionidentity/ResetSessionIdentityHandlerTest.java b/lambdas/reset-session-identity/src/test/java/uk/gov/di/ipv/core/resetsessionidentity/ResetSessionIdentityHandlerTest.java index bdf34b6f99..bec00ce2c5 100644 --- a/lambdas/reset-session-identity/src/test/java/uk/gov/di/ipv/core/resetsessionidentity/ResetSessionIdentityHandlerTest.java +++ b/lambdas/reset-session-identity/src/test/java/uk/gov/di/ipv/core/resetsessionidentity/ResetSessionIdentityHandlerTest.java @@ -6,8 +6,6 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; -import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.ValueSource; import org.mockito.InOrder; import org.mockito.InjectMocks; import org.mockito.Mock; @@ -20,10 +18,8 @@ import uk.gov.di.ipv.core.library.exceptions.CredentialParseException; import uk.gov.di.ipv.core.library.exceptions.VerifiableCredentialException; import uk.gov.di.ipv.core.library.helpers.SecureTokenHelper; -import uk.gov.di.ipv.core.library.persistence.DataStore; import uk.gov.di.ipv.core.library.persistence.item.ClientOAuthSessionItem; import uk.gov.di.ipv.core.library.persistence.item.IpvSessionItem; -import uk.gov.di.ipv.core.library.persistence.item.VcStoreItem; import uk.gov.di.ipv.core.library.service.ClientOAuthSessionDetailsService; import uk.gov.di.ipv.core.library.service.ConfigService; import uk.gov.di.ipv.core.library.service.CriResponseService; @@ -31,7 +27,6 @@ import uk.gov.di.ipv.core.library.service.IpvSessionService; import uk.gov.di.ipv.core.library.testhelpers.unit.LogCollector; import uk.gov.di.ipv.core.library.verifiablecredential.service.SessionCredentialsService; -import uk.gov.di.ipv.core.library.verifiablecredential.service.VerifiableCredentialService; import java.util.List; import java.util.Map; @@ -48,8 +43,6 @@ import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_READ_ENABLED; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_WRITE_ENABLED; import static uk.gov.di.ipv.core.library.domain.Cri.F2F; import static uk.gov.di.ipv.core.library.domain.ErrorResponse.FAILED_AT_EVCS_HTTP_REQUEST_SEND; import static uk.gov.di.ipv.core.library.domain.ErrorResponse.FAILED_TO_DELETE_CREDENTIAL; @@ -79,17 +72,15 @@ class ResetSessionIdentityHandlerTest { private static IpvSessionItem ipvSessionItem; private static ClientOAuthSessionItem clientOAuthSessionItem; + @Mock private ConfigService mockConfigService; @Mock private SessionCredentialsService mockSessionCredentialsService; - @Mock private DataStore mockDataStore; @Mock private IpvSessionService mockIpvSessionService; @Mock private ClientOAuthSessionDetailsService mockClientOAuthSessionDetailsService; @Mock private Context mockContext; @Mock private CriResponseService mockCriResponseService; - @Mock private VerifiableCredentialService mockVerifiableCredentialService; @Mock private EvcsService mockEvcsService; @Mock private VerifiableCredential mockVerifiableCredential; @InjectMocks private ResetSessionIdentityHandler resetSessionIdentityHandler; - @Mock private ConfigService mockConfigService; @BeforeEach void setUpEach() { @@ -117,7 +108,7 @@ void handleRequestShouldDeleteUsersSessionVcsAndReturnNext() throws Exception { when(mockIpvSessionService.getIpvSession(TEST_SESSION_ID)).thenReturn(ipvSessionItem); when(mockClientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - ProcessRequest event = + var event = ProcessRequest.processRequestBuilder() .ipvSessionId(TEST_SESSION_ID) .featureSet(TEST_FEATURE_SET) @@ -125,7 +116,7 @@ void handleRequestShouldDeleteUsersSessionVcsAndReturnNext() throws Exception { .build(); // Act - JourneyResponse journeyResponse = + var journeyResponse = OBJECT_MAPPER.convertValue( resetSessionIdentityHandler.handleRequest(event, mockContext), JourneyResponse.class); @@ -142,50 +133,10 @@ void handleRequestShouldDeleteUsersSessionVcsAndReturnNext() throws Exception { @Test void handleRequestShouldCleanupVcsAndReturnNext_forPendingF2f() throws Exception { // Arrange - when(mockConfigService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); when(mockIpvSessionService.getIpvSession(TEST_SESSION_ID)).thenReturn(ipvSessionItem); when(mockClientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - ProcessRequest event = - ProcessRequest.processRequestBuilder() - .ipvSessionId(TEST_SESSION_ID) - .featureSet(TEST_FEATURE_SET) - .lambdaInput(Map.of("resetType", PENDING_F2F_ALL.name())) - .build(); - - // Act - JourneyResponse journeyResponse = - OBJECT_MAPPER.convertValue( - resetSessionIdentityHandler.handleRequest(event, mockContext), - JourneyResponse.class); - - // Assert - verifyVotSetToP0(); - - verify(mockSessionCredentialsService) - .deleteSessionCredentialsForResetType( - ipvSessionItem.getIpvSessionId(), PENDING_F2F_ALL); - verify(mockCriResponseService).deleteCriResponseItem(TEST_USER_ID, F2F); - verify(mockVerifiableCredentialService).deleteVCs(TEST_USER_ID); - verify(mockEvcsService).abandonPendingIdentity(TEST_USER_ID, TEST_EVCS_TOKEN); - - assertEquals(JOURNEY_NEXT.getJourney(), journeyResponse.getJourney()); - } - - @Test - void - handleRequestShouldCleanupVcsAndReturnNext_forPendingF2f_evenWhenEvcsFailsAndEvcsReadsIsNotEnabled() - throws Exception { - // Arrange - when(mockConfigService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); - when(mockIpvSessionService.getIpvSession(TEST_SESSION_ID)).thenReturn(ipvSessionItem); - when(mockClientOAuthSessionDetailsService.getClientOAuthSession(any())) - .thenReturn(clientOAuthSessionItem); - doThrow(EvcsServiceException.class) - .when(mockEvcsService) - .abandonPendingIdentity(TEST_USER_ID, TEST_EVCS_TOKEN); - - ProcessRequest event = + var event = ProcessRequest.processRequestBuilder() .ipvSessionId(TEST_SESSION_ID) .featureSet(TEST_FEATURE_SET) @@ -193,7 +144,7 @@ void handleRequestShouldCleanupVcsAndReturnNext_forPendingF2f() throws Exception .build(); // Act - JourneyResponse journeyResponse = + var journeyResponse = OBJECT_MAPPER.convertValue( resetSessionIdentityHandler.handleRequest(event, mockContext), JourneyResponse.class); @@ -205,18 +156,14 @@ void handleRequestShouldCleanupVcsAndReturnNext_forPendingF2f() throws Exception .deleteSessionCredentialsForResetType( ipvSessionItem.getIpvSessionId(), PENDING_F2F_ALL); verify(mockCriResponseService).deleteCriResponseItem(TEST_USER_ID, F2F); - verify(mockVerifiableCredentialService).deleteVCs(TEST_USER_ID); verify(mockEvcsService).abandonPendingIdentity(TEST_USER_ID, TEST_EVCS_TOKEN); assertEquals(JOURNEY_NEXT.getJourney(), journeyResponse.getJourney()); } @Test - void shouldReturnErrorJourney_forPendingF2f_evenWhenEvcsFailsAndEvcsReadsIsEnabled() - throws Exception { + void shouldReturnErrorJourneyIfFailureToUpdatePendingIdentityInEvcs() throws Exception { // Arrange - when(mockConfigService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); - when(mockConfigService.enabled(EVCS_READ_ENABLED)).thenReturn(true); when(mockIpvSessionService.getIpvSession(TEST_SESSION_ID)).thenReturn(ipvSessionItem); when(mockClientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); @@ -226,7 +173,7 @@ void shouldReturnErrorJourney_forPendingF2f_evenWhenEvcsFailsAndEvcsReadsIsEnabl .when(mockEvcsService) .abandonPendingIdentity(TEST_USER_ID, TEST_EVCS_TOKEN); - ProcessRequest event = + var event = ProcessRequest.processRequestBuilder() .ipvSessionId(TEST_SESSION_ID) .featureSet(TEST_FEATURE_SET) @@ -243,7 +190,6 @@ void shouldReturnErrorJourney_forPendingF2f_evenWhenEvcsFailsAndEvcsReadsIsEnabl .deleteSessionCredentialsForResetType( ipvSessionItem.getIpvSessionId(), PENDING_F2F_ALL); verify(mockCriResponseService).deleteCriResponseItem(TEST_USER_ID, F2F); - verify(mockVerifiableCredentialService).deleteVCs(TEST_USER_ID); verify(mockEvcsService).abandonPendingIdentity(TEST_USER_ID, TEST_EVCS_TOKEN); assertEquals(JOURNEY_ERROR_PATH, journeyResponse.get("journey")); @@ -252,23 +198,16 @@ void shouldReturnErrorJourney_forPendingF2f_evenWhenEvcsFailsAndEvcsReadsIsEnabl assertEquals(FAILED_AT_EVCS_HTTP_REQUEST_SEND.getMessage(), journeyResponse.get("message")); } - @ParameterizedTest - @ValueSource(booleans = {true, false}) - void shouldReinstateUsersIdentity(boolean evcsReadEnabled) throws Exception { + @Test + void shouldReinstateUsersIdentity() throws Exception { // Arrange when(mockIpvSessionService.getIpvSession(TEST_SESSION_ID)).thenReturn(ipvSessionItem); when(mockClientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - when(mockConfigService.enabled(EVCS_READ_ENABLED)).thenReturn(evcsReadEnabled); - if (evcsReadEnabled) { - when(mockEvcsService.getVerifiableCredentials(TEST_USER_ID, TEST_EVCS_TOKEN, CURRENT)) - .thenReturn(List.of(mockVerifiableCredential)); - } else { - when(mockVerifiableCredentialService.getVcs(TEST_USER_ID)) - .thenReturn(List.of(mockVerifiableCredential)); - } - - ProcessRequest event = + when(mockEvcsService.getVerifiableCredentials(TEST_USER_ID, TEST_EVCS_TOKEN, CURRENT)) + .thenReturn(List.of(mockVerifiableCredential)); + + var event = ProcessRequest.processRequestBuilder() .ipvSessionId(TEST_SESSION_ID) .featureSet(TEST_FEATURE_SET) @@ -276,7 +215,7 @@ void shouldReinstateUsersIdentity(boolean evcsReadEnabled) throws Exception { .build(); // Act - JourneyResponse journeyResponse = + var journeyResponse = OBJECT_MAPPER.convertValue( resetSessionIdentityHandler.handleRequest(event, mockContext), JourneyResponse.class); @@ -292,22 +231,14 @@ void shouldReinstateUsersIdentity(boolean evcsReadEnabled) throws Exception { assertEquals(JOURNEY_NEXT.getJourney(), journeyResponse.getJourney()); } - @ParameterizedTest - @ValueSource(booleans = {true, false}) - void shouldReturnErrorJourneyIfReinstateAndUnableToReadFromLongTermStore( - boolean evcsReadEnabled) throws Exception { + @Test + void shouldReturnErrorJourneyIfReinstateAndUnableToReadFromLongTermStore() throws Exception { // Arrange when(mockIpvSessionService.getIpvSession(TEST_SESSION_ID)).thenReturn(ipvSessionItem); when(mockClientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - when(mockConfigService.enabled(EVCS_READ_ENABLED)).thenReturn(evcsReadEnabled); - if (evcsReadEnabled) { - when(mockEvcsService.getVerifiableCredentials(TEST_USER_ID, TEST_EVCS_TOKEN, CURRENT)) - .thenThrow(new CredentialParseException("Boop")); - } else { - when(mockVerifiableCredentialService.getVcs(TEST_USER_ID)) - .thenThrow(new CredentialParseException("Beep")); - } + when(mockEvcsService.getVerifiableCredentials(TEST_USER_ID, TEST_EVCS_TOKEN, CURRENT)) + .thenThrow(new CredentialParseException("Boop")); var event = ProcessRequest.processRequestBuilder() @@ -334,7 +265,7 @@ void shouldReturnErrorJourneyIfReinstateAndUnableToReadFromLongTermStore( @Test void shouldReturnErrorJourneyIfIpvSessionIdMissing() { // Arrange - ProcessRequest event = + var event = ProcessRequest.processRequestBuilder() .featureSet(TEST_FEATURE_SET) .lambdaInput(Map.of("resetType", ALL.name())) @@ -359,7 +290,7 @@ void shouldReturnAnErrorJourneyIfCantDeleteSessionCredentials() throws Exception doThrow(new VerifiableCredentialException(418, FAILED_TO_DELETE_CREDENTIAL)) .when(mockSessionCredentialsService) .deleteSessionCredentialsForResetType(TEST_SESSION_ID, NAME_ONLY_CHANGE); - ProcessRequest event = + var event = ProcessRequest.processRequestBuilder() .ipvSessionId(TEST_SESSION_ID) .featureSet(TEST_FEATURE_SET) @@ -384,7 +315,7 @@ void shouldReturnErrorJourneyIfUnknownResetType() throws Exception { when(mockIpvSessionService.getIpvSession(TEST_SESSION_ID)).thenReturn(ipvSessionItem); when(mockClientOAuthSessionDetailsService.getClientOAuthSession(any())) .thenReturn(clientOAuthSessionItem); - ProcessRequest event = + var event = ProcessRequest.processRequestBuilder() .ipvSessionId(TEST_SESSION_ID) .featureSet(TEST_FEATURE_SET) @@ -408,7 +339,7 @@ void shouldLogRuntimeExceptionsAndRethrow() throws Exception { // Arrange when(mockIpvSessionService.getIpvSession(anyString())) .thenThrow(new RuntimeException("Test error")); - ProcessRequest event = + var event = ProcessRequest.processRequestBuilder() .ipvSessionId(TEST_SESSION_ID) .featureSet(TEST_FEATURE_SET) diff --git a/lambdas/store-identity/src/main/java/uk/gov/di/ipv/core/storeidentity/StoreIdentityHandler.java b/lambdas/store-identity/src/main/java/uk/gov/di/ipv/core/storeidentity/StoreIdentityHandler.java index 4ef8311b1d..810c5569fd 100644 --- a/lambdas/store-identity/src/main/java/uk/gov/di/ipv/core/storeidentity/StoreIdentityHandler.java +++ b/lambdas/store-identity/src/main/java/uk/gov/di/ipv/core/storeidentity/StoreIdentityHandler.java @@ -16,7 +16,6 @@ import uk.gov.di.ipv.core.library.domain.JourneyErrorResponse; import uk.gov.di.ipv.core.library.domain.JourneyResponse; import uk.gov.di.ipv.core.library.domain.ProcessRequest; -import uk.gov.di.ipv.core.library.domain.VerifiableCredential; import uk.gov.di.ipv.core.library.enums.IdentityType; import uk.gov.di.ipv.core.library.enums.Vot; import uk.gov.di.ipv.core.library.exception.EvcsServiceException; @@ -33,15 +32,10 @@ import uk.gov.di.ipv.core.library.service.EvcsService; import uk.gov.di.ipv.core.library.service.IpvSessionService; import uk.gov.di.ipv.core.library.verifiablecredential.service.SessionCredentialsService; -import uk.gov.di.ipv.core.library.verifiablecredential.service.VerifiableCredentialService; -import java.time.Instant; -import java.util.List; import java.util.Map; import static uk.gov.di.ipv.core.library.auditing.AuditEventTypes.IPV_IDENTITY_STORED; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_READ_ENABLED; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_WRITE_ENABLED; import static uk.gov.di.ipv.core.library.domain.ErrorResponse.IPV_SESSION_NOT_FOUND; import static uk.gov.di.ipv.core.library.enums.Vot.P0; import static uk.gov.di.ipv.core.library.journeys.JourneyUris.JOURNEY_ERROR_PATH; @@ -55,7 +49,6 @@ public class StoreIdentityHandler implements RequestHandler credentials = + var userId = clientOAuthSessionItem.getUserId(); + var credentials = sessionCredentialsService.getCredentials(ipvSessionItem.getIpvSessionId(), userId); - if (configService.enabled(EVCS_WRITE_ENABLED)) { - try { - if (identityType != IdentityType.PENDING) { - evcsService.storeCompletedIdentity( - userId, credentials, clientOAuthSessionItem.getEvcsAccessToken()); - } else { - evcsService.storePendingIdentity( - userId, credentials, clientOAuthSessionItem.getEvcsAccessToken()); - } - credentials.forEach(credential -> credential.setMigrated(Instant.now())); - } catch (EvcsServiceException e) { - if (configService.enabled(EVCS_READ_ENABLED)) { - throw e; - } else { - LOGGER.error(LogHelper.buildErrorMessage("Failed to store EVCS identity", e)); - } - } + if (identityType == IdentityType.PENDING) { + evcsService.storePendingIdentity( + userId, credentials, clientOAuthSessionItem.getEvcsAccessToken()); + } else { + evcsService.storeCompletedIdentity( + userId, credentials, clientOAuthSessionItem.getEvcsAccessToken()); } - verifiableCredentialService.storeIdentity(credentials, userId); - LOGGER.info(LogHelper.buildLogMessage("Identity successfully stored")); } diff --git a/lambdas/store-identity/src/test/java/uk/gov/di/ipv/core/storeidentity/StoreIdentityHandlerTest.java b/lambdas/store-identity/src/test/java/uk/gov/di/ipv/core/storeidentity/StoreIdentityHandlerTest.java index 6712252e62..d2495da02c 100644 --- a/lambdas/store-identity/src/test/java/uk/gov/di/ipv/core/storeidentity/StoreIdentityHandlerTest.java +++ b/lambdas/store-identity/src/test/java/uk/gov/di/ipv/core/storeidentity/StoreIdentityHandlerTest.java @@ -1,7 +1,6 @@ package uk.gov.di.ipv.core.storeidentity; import com.amazonaws.services.lambda.runtime.Context; -import com.nimbusds.oauth2.sdk.http.HTTPResponse; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeEach; @@ -12,9 +11,7 @@ import org.mockito.InOrder; import org.mockito.InjectMocks; import org.mockito.Mock; -import org.mockito.Mockito; import org.mockito.junit.jupiter.MockitoExtension; -import org.mockito.junit.jupiter.MockitoSettings; import uk.gov.di.ipv.core.library.auditing.AuditEvent; import uk.gov.di.ipv.core.library.auditing.AuditEventUser; import uk.gov.di.ipv.core.library.auditing.extension.AuditExtensionIdentityType; @@ -33,37 +30,30 @@ import uk.gov.di.ipv.core.library.service.IpvSessionService; import uk.gov.di.ipv.core.library.testhelpers.unit.LogCollector; import uk.gov.di.ipv.core.library.verifiablecredential.service.SessionCredentialsService; -import uk.gov.di.ipv.core.library.verifiablecredential.service.VerifiableCredentialService; -import java.time.Instant; import java.util.HashMap; import java.util.List; import java.util.Map; +import static com.nimbusds.oauth2.sdk.http.HTTPResponse.SC_SERVER_ERROR; import static org.apache.http.HttpStatus.SC_BAD_REQUEST; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.core.StringContains.containsString; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.inOrder; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.never; -import static org.mockito.Mockito.reset; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static org.mockito.quality.Strictness.LENIENT; import static uk.gov.di.ipv.core.library.auditing.AuditEventTypes.IPV_IDENTITY_STORED; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_READ_ENABLED; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_WRITE_ENABLED; -import static uk.gov.di.ipv.core.library.domain.Cri.EXPERIAN_FRAUD; import static uk.gov.di.ipv.core.library.domain.ErrorResponse.FAILED_AT_EVCS_HTTP_REQUEST_SEND; import static uk.gov.di.ipv.core.library.domain.ErrorResponse.FAILED_TO_GET_CREDENTIAL; -import static uk.gov.di.ipv.core.library.domain.ErrorResponse.FAILED_TO_STORE_IDENTITY; +import static uk.gov.di.ipv.core.library.domain.ErrorResponse.FAILED_TO_PARSE_EVCS_REQUEST_BODY; import static uk.gov.di.ipv.core.library.domain.ErrorResponse.INVALID_IDENTITY_TYPE_PARAMETER; import static uk.gov.di.ipv.core.library.domain.ErrorResponse.MISSING_IPV_SESSION_ID; import static uk.gov.di.ipv.core.library.enums.Vot.P0; @@ -86,6 +76,7 @@ class StoreIdentityHandlerTest { private static final String SESSION_ID = "session-id"; private static final String STATUS_CODE = "statusCode"; private static final String USER_ID = "user-id"; + private static final String TEST_EVCS_ACCESS_TOKEN = "TEST_EVCS_ACCESS_TOKEN"; private static final ProcessRequest PROCESS_REQUEST_FOR_COMPLETED_IDENTITY = ProcessRequest.processRequestBuilder() .ipvSessionId(SESSION_ID) @@ -112,7 +103,6 @@ class StoreIdentityHandlerTest { @Mock private ClientOAuthSessionDetailsService mockClientOauthSessionDetailsService; @Mock private IpvSessionService mockIpvSessionService; @Mock private SessionCredentialsService mockSessionCredentialService; - @Mock private VerifiableCredentialService mockVerifiableCredentialService; @Mock private AuditService mockAuditService; @Mock private EvcsService mockEvcsService; @InjectMocks private StoreIdentityHandler storeIdentityHandler; @@ -122,7 +112,7 @@ static void setUpBeforeAll() { clientOAuthSessionItem = new ClientOAuthSessionItem(); clientOAuthSessionItem.setUserId(USER_ID); clientOAuthSessionItem.setGovukSigninJourneyId(GOVUK_JOURNEY_ID); - clientOAuthSessionItem.setEvcsAccessToken("TEST_EVCS_ACCESS_TOKEN"); + clientOAuthSessionItem.setEvcsAccessToken(TEST_EVCS_ACCESS_TOKEN); } @BeforeEach @@ -132,16 +122,14 @@ void setUpBeforeEach() throws Exception { ipvSessionItem.setClientOAuthSessionId(CLIENT_SESSION_ID); ipvSessionItem.setVot(P2); - Mockito.lenient() - .when(mockIpvSessionService.getIpvSession(SESSION_ID)) - .thenReturn(ipvSessionItem); - Mockito.lenient() + lenient().when(mockIpvSessionService.getIpvSession(SESSION_ID)).thenReturn(ipvSessionItem); + lenient() .when(mockClientOauthSessionDetailsService.getClientOAuthSession(CLIENT_SESSION_ID)) .thenReturn(clientOAuthSessionItem); - Mockito.lenient() + lenient() .when(mockSessionCredentialService.getCredentials(SESSION_ID, USER_ID)) .thenReturn(VCS); - Mockito.lenient() + lenient() .when(mockConfigService.getParameter(ConfigurationVariable.COMPONENT_ID)) .thenReturn(COMPONENT_ID); } @@ -154,44 +142,19 @@ void checkAuditEventWait() { } @Test - void shouldReturnAnIdentityStoredJourney_whenEvcsWriteEnabled() throws Exception { - reset(mockSessionCredentialService); - VCS.forEach( - credential -> { - if (credential.getCri().equals(EXPERIAN_FRAUD)) { - credential.setMigrated(null); - } else { - credential.setMigrated(Instant.now()); - } - }); + void shouldReturnAnIdentityStoredJourney() throws Exception { when(mockSessionCredentialService.getCredentials(SESSION_ID, USER_ID)).thenReturn(VCS); - when(mockConfigService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); + var response = storeIdentityHandler.handleRequest( PROCESS_REQUEST_FOR_COMPLETED_IDENTITY, mockContext); assertEquals(JOURNEY_IDENTITY_STORED_PATH, response.get(JOURNEY)); - ArgumentCaptor> storesVcsCaptor = - ArgumentCaptor.forClass(List.class); - verify(mockVerifiableCredentialService).storeIdentity(storesVcsCaptor.capture(), any()); - storesVcsCaptor.getValue().forEach(vc -> assertNotNull(vc.getMigrated())); - verify(mockEvcsService, times(1)).storeCompletedIdentity(anyString(), any(), any()); + verify(mockEvcsService).storeCompletedIdentity(USER_ID, VCS, TEST_EVCS_ACCESS_TOKEN); } @Test void shouldSendAuditEventWithVotExtensionWhenIdentityAchieved() throws Exception { - reset(mockSessionCredentialService); - VCS.stream() - .map( - credential -> { - if (credential.getCri().equals(EXPERIAN_FRAUD)) { - credential.setMigrated(null); - } else { - credential.setMigrated(Instant.now()); - } - return credential; - }) - .toList(); when(mockSessionCredentialService.getCredentials(SESSION_ID, USER_ID)).thenReturn(VCS); storeIdentityHandler.handleRequest(PROCESS_REQUEST_FOR_COMPLETED_IDENTITY, mockContext); @@ -208,19 +171,7 @@ void shouldSendAuditEventWithVotExtensionWhenIdentityAchieved() throws Exception assertEquals( new AuditEventUser(USER_ID, SESSION_ID, GOVUK_JOURNEY_ID, IP_ADDRESS), auditEvent.getUser()); - ArgumentCaptor> storesVcs = ArgumentCaptor.forClass(List.class); - verify(mockVerifiableCredentialService).storeIdentity(storesVcs.capture(), any()); - storesVcs - .getValue() - .forEach( - vc -> { - if (vc.getCri().equals(EXPERIAN_FRAUD)) { - assertNull(vc.getMigrated()); - } else { - assertNotNull(vc.getMigrated()); - } - }); - verify(mockEvcsService, times(0)).storeCompletedIdentity(anyString(), any(), any()); + verify(mockEvcsService).storeCompletedIdentity(USER_ID, VCS, TEST_EVCS_ACCESS_TOKEN); } @Test @@ -245,12 +196,11 @@ void shouldSendAuditEventWithVotAndIdentityTypeExtensionWhenIdentityUpdated() th assertEquals( new AuditEventUser(USER_ID, SESSION_ID, GOVUK_JOURNEY_ID, IP_ADDRESS), auditEvent.getUser()); - verify(mockEvcsService, times(0)).storeCompletedIdentity(anyString(), any(), any()); + verify(mockEvcsService).storeCompletedIdentity(USER_ID, VCS, TEST_EVCS_ACCESS_TOKEN); } @Test - void shouldSendAuditEventWithVotAndIdentityTypeExtensionWhenIdentityIncomplete() - throws Exception { + void shouldSendAuditEventWithVotAndIdentityTypeExtensionWhenIdentityIncomplete() { ipvSessionItem.setVot(P0); storeIdentityHandler.handleRequest(PROCESS_REQUEST_FOR_COMPLETED_IDENTITY, mockContext); @@ -284,7 +234,8 @@ void shouldReturnErrorIfMissingIdentityTypeParameter() throws Exception { assertEquals(SC_BAD_REQUEST, response.get(STATUS_CODE)); assertEquals(INVALID_IDENTITY_TYPE_PARAMETER.getCode(), response.get(CODE)); assertEquals(INVALID_IDENTITY_TYPE_PARAMETER.getMessage(), response.get(MESSAGE)); - verify(mockVerifiableCredentialService, never()).storeIdentity(any(), any()); + verify(mockEvcsService, never()).storeCompletedIdentity(any(), any(), any()); + verify(mockEvcsService, never()).storePendingIdentity(any(), any(), any()); } @Test @@ -302,11 +253,11 @@ void shouldReturnErrorIfInvalidIdentityTypeParameter() throws Exception { assertEquals(SC_BAD_REQUEST, response.get(STATUS_CODE)); assertEquals(INVALID_IDENTITY_TYPE_PARAMETER.getCode(), response.get(CODE)); assertEquals(INVALID_IDENTITY_TYPE_PARAMETER.getMessage(), response.get(MESSAGE)); - verify(mockVerifiableCredentialService, never()).storeIdentity(any(), any()); + verify(mockEvcsService, never()).storeCompletedIdentity(any(), any(), any()); + verify(mockEvcsService, never()).storePendingIdentity(any(), any(), any()); } @Test - @MockitoSettings(strictness = LENIENT) void shouldReturnAnErrorJourneyIfIpvSessionIdMissing() throws Exception { var processRequestWithMissingSessionId = ProcessRequest.processRequestBuilder().build(); @@ -317,7 +268,8 @@ void shouldReturnAnErrorJourneyIfIpvSessionIdMissing() throws Exception { assertEquals(SC_BAD_REQUEST, response.get(STATUS_CODE)); assertEquals(MISSING_IPV_SESSION_ID.getCode(), response.get(CODE)); assertEquals(MISSING_IPV_SESSION_ID.getMessage(), response.get(MESSAGE)); - verify(mockVerifiableCredentialService, never()).storeIdentity(any(), any()); + verify(mockEvcsService, never()).storeCompletedIdentity(any(), any(), any()); + verify(mockEvcsService, never()).storePendingIdentity(any(), any(), any()); } @Test @@ -333,14 +285,15 @@ void shouldReturnAnErrorJourneyIfCantFetchSessionCredentials() throws Exception assertEquals(418, response.get(STATUS_CODE)); assertEquals(FAILED_TO_GET_CREDENTIAL.getCode(), response.get(CODE)); assertEquals(FAILED_TO_GET_CREDENTIAL.getMessage(), response.get(MESSAGE)); - verify(mockVerifiableCredentialService, never()).storeIdentity(any(), any()); + verify(mockEvcsService, never()).storeCompletedIdentity(any(), any(), any()); + verify(mockEvcsService, never()).storePendingIdentity(any(), any(), any()); } @Test void shouldReturnAnErrorJourneyIfCantStoreIdentity() throws Exception { - doThrow(new VerifiableCredentialException(418, FAILED_TO_STORE_IDENTITY)) - .when(mockVerifiableCredentialService) - .storeIdentity(any(), any()); + doThrow(new EvcsServiceException(418, FAILED_TO_PARSE_EVCS_REQUEST_BODY)) + .when(mockEvcsService) + .storeCompletedIdentity(USER_ID, VCS, TEST_EVCS_ACCESS_TOKEN); var response = storeIdentityHandler.handleRequest( @@ -348,18 +301,12 @@ void shouldReturnAnErrorJourneyIfCantStoreIdentity() throws Exception { assertEquals(JOURNEY_ERROR_PATH, response.get(JOURNEY)); assertEquals(418, response.get(STATUS_CODE)); - assertEquals(FAILED_TO_STORE_IDENTITY.getCode(), response.get(CODE)); - assertEquals(FAILED_TO_STORE_IDENTITY.getMessage(), response.get(MESSAGE)); + assertEquals(FAILED_TO_PARSE_EVCS_REQUEST_BODY.getCode(), response.get(CODE)); + assertEquals(FAILED_TO_PARSE_EVCS_REQUEST_BODY.getMessage(), response.get(MESSAGE)); } @Test - void - shouldStoreIdentityInEvcsAndSendAuditEventAndSendIdentityStoredJourney_whenEvcsWriteEnabled_forPendingF2f() - throws Exception { - reset(mockIpvSessionService); - when(mockIpvSessionService.getIpvSession(SESSION_ID)).thenReturn(ipvSessionItem); - when(mockConfigService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); - + void shouldStorePendingIdentityInEvcs() throws Exception { var response = storeIdentityHandler.handleRequest( PROCESS_REQUEST_FOR_PENDING_IDENTITY, mockContext); @@ -377,53 +324,25 @@ void shouldReturnAnErrorJourneyIfCantStoreIdentity() throws Exception { assertEquals( new AuditEventUser(USER_ID, SESSION_ID, GOVUK_JOURNEY_ID, IP_ADDRESS), auditEvent.getUser()); - verify(mockEvcsService, times(1)) - .storePendingIdentity(USER_ID, VCS, clientOAuthSessionItem.getEvcsAccessToken()); + verify(mockEvcsService).storePendingIdentity(USER_ID, VCS, TEST_EVCS_ACCESS_TOKEN); } @Test - void shouldReturnAnErrorJourneyIfFailedAtEvcsIdentityStore_whenEvcsReadEnabled_forPendingF2f() - throws Exception { - reset(mockIpvSessionService); - when(mockIpvSessionService.getIpvSession(SESSION_ID)).thenReturn(ipvSessionItem); - when(mockConfigService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); - when(mockConfigService.enabled(EVCS_READ_ENABLED)).thenReturn(true); - doThrow( - new EvcsServiceException( - HTTPResponse.SC_SERVER_ERROR, FAILED_AT_EVCS_HTTP_REQUEST_SEND)) + void shouldReturnAnErrorJourneyIfStoringPendingFailed() throws Exception { + doThrow(new EvcsServiceException(SC_SERVER_ERROR, FAILED_AT_EVCS_HTTP_REQUEST_SEND)) .when(mockEvcsService) - .storePendingIdentity(USER_ID, VCS, clientOAuthSessionItem.getEvcsAccessToken()); + .storePendingIdentity(USER_ID, VCS, TEST_EVCS_ACCESS_TOKEN); var response = storeIdentityHandler.handleRequest( PROCESS_REQUEST_FOR_PENDING_IDENTITY, mockContext); assertEquals(JOURNEY_ERROR_PATH, response.get(JOURNEY)); - assertEquals(500, response.get(STATUS_CODE)); + assertEquals(SC_SERVER_ERROR, response.get(STATUS_CODE)); assertEquals(FAILED_AT_EVCS_HTTP_REQUEST_SEND.getCode(), response.get(CODE)); assertEquals(FAILED_AT_EVCS_HTTP_REQUEST_SEND.getMessage(), response.get(MESSAGE)); } - @Test - void - shouldNotReturnAnErrorJourneyIfFailedAtEvcsIdentityStore_whenEvcsReadNotEnabled_forPendingF2f() - throws Exception { - reset(mockIpvSessionService); - when(mockIpvSessionService.getIpvSession(SESSION_ID)).thenReturn(ipvSessionItem); - when(mockConfigService.enabled(EVCS_WRITE_ENABLED)).thenReturn(true); - doThrow( - new EvcsServiceException( - HTTPResponse.SC_SERVER_ERROR, FAILED_AT_EVCS_HTTP_REQUEST_SEND)) - .when(mockEvcsService) - .storePendingIdentity(USER_ID, VCS, clientOAuthSessionItem.getEvcsAccessToken()); - - var response = - storeIdentityHandler.handleRequest( - PROCESS_REQUEST_FOR_PENDING_IDENTITY, mockContext); - - assertEquals(JOURNEY_IDENTITY_STORED_PATH, response.get(JOURNEY)); - } - @Test void shouldLogRuntimeExceptionsAndRethrow() throws Exception { // Arrange diff --git a/libs/common-services/src/main/java/uk/gov/di/ipv/core/library/config/CoreFeatureFlag.java b/libs/common-services/src/main/java/uk/gov/di/ipv/core/library/config/CoreFeatureFlag.java index 096c0c93c3..3a9b8dc502 100644 --- a/libs/common-services/src/main/java/uk/gov/di/ipv/core/library/config/CoreFeatureFlag.java +++ b/libs/common-services/src/main/java/uk/gov/di/ipv/core/library/config/CoreFeatureFlag.java @@ -5,9 +5,6 @@ public enum CoreFeatureFlag implements FeatureFlag { RESET_IDENTITY("resetIdentity"), INHERITED_IDENTITY("inheritedIdentity"), REPEAT_FRAUD_CHECK("repeatFraudCheckEnabled"), - EVCS_WRITE_ENABLED("evcsWriteEnabled"), - EVCS_ASYNC_WRITE_ENABLED("evcsAsyncWriteEnabled"), - EVCS_READ_ENABLED("evcsReadEnabled"), MFA_RESET("mfaResetEnabled"), P1_JOURNEYS_ENABLED("p1JourneysEnabled"), SQS_ASYNC("sqsAsync"), diff --git a/libs/cri-response-service/src/test/java/uk/gov/di/ipv/core/library/service/CriResponseServiceTest.java b/libs/cri-response-service/src/test/java/uk/gov/di/ipv/core/library/service/CriResponseServiceTest.java index f17586a757..acf20fbaa3 100644 --- a/libs/cri-response-service/src/test/java/uk/gov/di/ipv/core/library/service/CriResponseServiceTest.java +++ b/libs/cri-response-service/src/test/java/uk/gov/di/ipv/core/library/service/CriResponseServiceTest.java @@ -21,14 +21,13 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_READ_ENABLED; -import static uk.gov.di.ipv.core.library.config.CoreFeatureFlag.EVCS_WRITE_ENABLED; import static uk.gov.di.ipv.core.library.domain.Cri.ADDRESS; import static uk.gov.di.ipv.core.library.domain.Cri.F2F; import static uk.gov.di.ipv.core.library.fixtures.VcFixtures.PASSPORT_NON_DCMAW_SUCCESSFUL_VC; @ExtendWith(MockitoExtension.class) class CriResponseServiceTest { + private static final String TEST_FEATURE_SET = "test-feature-set"; @Mock private DataStore mockDataStore; private CriResponseService criResponseService; @@ -64,8 +63,7 @@ void shouldReturnCredentialFromDataStoreForSpecificCri() { @Test void shouldPersistCriResponse() { - List featureSet = - List.of(EVCS_WRITE_ENABLED.getName(), EVCS_READ_ENABLED.getName()); + var featureSet = List.of(TEST_FEATURE_SET); criResponseService.persistCriResponse( TEST_USER_ID, F2F, diff --git a/libs/evcs-service/src/main/java/uk/gov/di/ipv/core/library/service/EvcsMigrationService.java b/libs/evcs-service/src/main/java/uk/gov/di/ipv/core/library/service/EvcsMigrationService.java deleted file mode 100644 index ad1971cbac..0000000000 --- a/libs/evcs-service/src/main/java/uk/gov/di/ipv/core/library/service/EvcsMigrationService.java +++ /dev/null @@ -1,42 +0,0 @@ -package uk.gov.di.ipv.core.library.service; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import software.amazon.lambda.powertools.tracing.Tracing; -import uk.gov.di.ipv.core.library.annotations.ExcludeFromGeneratedCoverageReport; -import uk.gov.di.ipv.core.library.domain.VerifiableCredential; -import uk.gov.di.ipv.core.library.exception.EvcsServiceException; -import uk.gov.di.ipv.core.library.exceptions.VerifiableCredentialException; -import uk.gov.di.ipv.core.library.helpers.LogHelper; -import uk.gov.di.ipv.core.library.verifiablecredential.service.VerifiableCredentialService; - -import java.time.Instant; -import java.util.List; - -public class EvcsMigrationService { - private static final Logger LOGGER = LogManager.getLogger(); - private final EvcsService evcsService; - private final VerifiableCredentialService verifiableCredentialService; - - @ExcludeFromGeneratedCoverageReport - public EvcsMigrationService( - EvcsService evcsService, VerifiableCredentialService verifiableCredentialService) { - this.evcsService = evcsService; - this.verifiableCredentialService = verifiableCredentialService; - } - - @ExcludeFromGeneratedCoverageReport - public EvcsMigrationService(ConfigService configService) { - this(new EvcsService(configService), new VerifiableCredentialService(configService)); - } - - @Tracing - public void migrateExistingIdentity(String userId, List credentials) - throws EvcsServiceException, VerifiableCredentialException { - LOGGER.info(LogHelper.buildLogMessage("Migrating existing user VCs to Evcs.")); - evcsService.storeMigratedIdentity(userId, credentials); - credentials.forEach(credential -> credential.setMigrated(Instant.now())); - verifiableCredentialService.updateIdentity(credentials); - LOGGER.info(LogHelper.buildLogMessage("Migrated existing user VCs to Evcs.")); - } -} diff --git a/libs/evcs-service/src/test/java/uk/gov/di/ipv/core/library/service/EvcsMigrationServiceTest.java b/libs/evcs-service/src/test/java/uk/gov/di/ipv/core/library/service/EvcsMigrationServiceTest.java deleted file mode 100644 index 85f0319b24..0000000000 --- a/libs/evcs-service/src/test/java/uk/gov/di/ipv/core/library/service/EvcsMigrationServiceTest.java +++ /dev/null @@ -1,41 +0,0 @@ -package uk.gov.di.ipv.core.library.service; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.jupiter.MockitoExtension; -import uk.gov.di.ipv.core.library.domain.VerifiableCredential; -import uk.gov.di.ipv.core.library.verifiablecredential.service.VerifiableCredentialService; - -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.verify; -import static uk.gov.di.ipv.core.library.fixtures.VcFixtures.vcAddressEmpty; -import static uk.gov.di.ipv.core.library.fixtures.VcFixtures.vcDrivingPermit; -import static uk.gov.di.ipv.core.library.fixtures.VcFixtures.vcFraudNotExpired; - -@ExtendWith(MockitoExtension.class) -class EvcsMigrationServiceTest { - private static final String TEST_USER_ID = "a-user-id"; - - @Captor ArgumentCaptor> vcsToUpdateCaptor; - - @Mock EvcsService mockEvcsService; - @Mock VerifiableCredentialService mockVerifiableCredentialService; - @InjectMocks EvcsMigrationService evcsMigrationService; - - @Test - void testMigrateExistingIdentity() throws Exception { - var vcs = List.of(vcDrivingPermit(), vcAddressEmpty(), vcFraudNotExpired()); - - evcsMigrationService.migrateExistingIdentity(TEST_USER_ID, vcs); - - verify(mockEvcsService).storeMigratedIdentity(TEST_USER_ID, vcs); - verify(mockVerifiableCredentialService).updateIdentity(vcsToUpdateCaptor.capture()); - vcsToUpdateCaptor.getValue().forEach(vc -> assertNotNull(vc.getMigrated())); - } -} diff --git a/local-running/core.local.params.yaml b/local-running/core.local.params.yaml index fba342dd7c..2f238e0eb5 100644 --- a/local-running/core.local.params.yaml +++ b/local-running/core.local.params.yaml @@ -380,9 +380,6 @@ core: internationalAddressEnabled: false inheritedIdentity: true repeatFraudCheckEnabled: true - evcsWriteEnabled: true - evcsAsyncWriteEnabled: true - evcsReadEnabled: true mfaResetEnabled: true parseVcClasses: true p1JourneysEnabled: false @@ -402,19 +399,6 @@ core: mfaReset: featureFlags: mfaResetEnabled: true - evcsWrite: - featureFlags: - evcsWriteEnabled: true - evcsAsyncWriteEnabled: true - evcsAsyncWrite: - featureFlags: - evcsAsyncWriteEnabled: true - evcsNonAsyncWrite: - featureFlags: - evcsWriteEnabled: true - evcsRead: - featureFlags: - evcsReadEnabled: true clearUsersIdentity: featureFlags: resetIdentity: true