diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index cce3710df..000000000 --- a/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -name: Custom issue template -about: " There's a better way to get help!" -title: '' -labels: '' -assignees: '' - ---- - -# -# Wait ✋ -# -# There's a better way to get help! -# -# Send your questions or issues to sdksupport@yoti.com -# -# diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..9486bc243 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Yoti Support + url: https://support.yoti.com/yotisupport/s/contactsupport + about: Please send your questions or issues here. diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3aa4c37c2..252b8654c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -9,7 +9,8 @@ updates: reviewers: - bucky-boy - MrBurtyyy - - psmelia - pn-santos + - irotech assignees: - MrBurtyyy + - irotech diff --git a/.github/workflows/junit.yml b/.github/workflows/junit.yml index 4d8055bb9..32bf8fd46 100644 --- a/.github/workflows/junit.yml +++ b/.github/workflows/junit.yml @@ -18,10 +18,11 @@ jobs: jdk-version: [8,11,17] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - name: Set up Java ${{ matrix.jdk-version }} - uses: actions/setup-java@v1 + uses: actions/setup-java@v4 with: + distribution: 'zulu' java-version: ${{ matrix.jdk-version }} architecture: x64 - run: mvn test -B -pl yoti-sdk-api -Ddependency-check.skip=true diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml index 226a5e86a..fe02d37c5 100644 --- a/.github/workflows/sonar.yml +++ b/.github/workflows/sonar.yml @@ -11,17 +11,18 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 with: # Disabling shallow clone is recommended for improving relevancy of reporting fetch-depth: 0 - - name: Set up Java 11 - uses: actions/setup-java@v1 + - name: Set up Java 17 + uses: actions/setup-java@v4 with: - java-version: 11 + distribution: 'zulu' + java-version: 17 architecture: x64 - name: Scan SDK run: mvn -B clean install sonar:sonar -Ddependency-check.skip=true -Dgpg.skip=true -Dfindbugs.skip=true env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} \ No newline at end of file + SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }} diff --git a/README.md b/README.md index 2c4847ea7..183657f40 100644 --- a/README.md +++ b/README.md @@ -101,13 +101,13 @@ If you are using Maven, you need to add the following dependency: com.yoti yoti-sdk-api - 3.8.0 + 3.9.0 ``` If you are using Gradle, here is the dependency to add: -`compile group: 'com.yoti', name: 'yoti-sdk-api', version: '3.8.0'` +`compile group: 'com.yoti', name: 'yoti-sdk-api', version: '3.9.0'` You will find all classes packaged under `com.yoti.api` diff --git a/examples/doc-scan/pom.xml b/examples/doc-scan/pom.xml index 0847b23cf..9cefeb59d 100644 --- a/examples/doc-scan/pom.xml +++ b/examples/doc-scan/pom.xml @@ -6,7 +6,7 @@ org.springframework.boot spring-boot-starter-parent - 2.7.16 + 2.7.18 @@ -53,7 +53,7 @@ com.yoti yoti-sdk-api - 3.8.0 + 3.9.0 diff --git a/examples/doc-scan/src/main/java/com/yoti/docscan/demo/service/DocScanService.java b/examples/doc-scan/src/main/java/com/yoti/docscan/demo/service/DocScanService.java index 6d8576e52..4538f9075 100644 --- a/examples/doc-scan/src/main/java/com/yoti/docscan/demo/service/DocScanService.java +++ b/examples/doc-scan/src/main/java/com/yoti/docscan/demo/service/DocScanService.java @@ -60,7 +60,7 @@ public CreateSessionResult createSession() throws DocScanException { SessionSpec sessionSpec = SessionSpec.builder() .withClientSessionTokenTtl(600) - .withResourcesTtl(90000) + .withResourcesTtl(604800) .withUserTrackingId("some-user-tracking-id") .withSdkConfig(sdkConfig) .withRequestedCheck( @@ -69,13 +69,13 @@ public CreateSessionResult createSession() throws DocScanException { ) .withRequestedCheck( RequestedFaceMatchCheck.builder() - .withManualCheckAlways() + .withManualCheckFallback() .build() ) .withRequestedCheck( RequestedLivenessCheck.builder() - .forZoomLiveness() - .withMaxRetries(1) + .forStaticLiveness() + .withMaxRetries(3) .build() ) .withRequestedCheck( @@ -97,12 +97,12 @@ public CreateSessionResult createSession() throws DocScanException { ) .withRequestedTask( RequestedIdDocTextExtractionTask.builder() - .withManualCheckAlways() + .withManualCheckFallback() .build() ) .withRequestedTask( RequestedSupplementaryDocTextExtractionTask.builder() - .withManualCheckAlways() + .withManualCheckFallback() .build() ) .withRequiredDocument( diff --git a/examples/doc-scan/src/main/resources/templates/success.html b/examples/doc-scan/src/main/resources/templates/success.html index c232a5c84..1eab041d2 100644 --- a/examples/doc-scan/src/main/resources/templates/success.html +++ b/examples/doc-scan/src/main/resources/templates/success.html @@ -924,6 +924,92 @@

Import Token

+ +
+
+

Identity Profile

+
+
+ + + +
+
+
+
+ Failure Reason: + +
+ Failure Type: + Document Type: + Document Country ISO Code: + Audit ID: + Details: +
+
+
+
+
+
+
+ +
+ + +
+
+

+ Advanced Identity Profile + + +

+
+
+ +
+
+ + Subject ID: + +
+
+ + +
+ Generated Profile Media: + +
+ +
+ +
+

+ +

+
+
+
+
+ + Type:
+ Objective:
+ Label:
+ Requirements Met:
+ Requirements Not Met Info:
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml index 9f9daab8c..7a6a69ded 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ com.yoti yoti-sdk pom - 3.8.0 + 3.9.0 Yoti SDK Java SDK for simple integration with the Yoti platform https://github.com/getyoti/yoti-java-sdk @@ -20,17 +20,68 @@ + 1.8 + + 3.8.5 + 3.1.1 - 1.1.0 - 4.7.3.4 + 1.2.1 + 4.8.3.1 + 3.4.1 + 1.7.0 - + + + + maven-enforcer-plugin + ${maven-enforcer-plugin.version} + + + enforce-bytecode-version + + enforce + + verify + + + + ${supported.java.version} + + + true + + + + enforce-dependency-versions + + enforce + + + + + + ${maven.min.version} + + + + + + + + org.codehaus.mojo + extra-enforcer-rules + ${extra-enforcer-rules.version} + + + + + + - org.apache.maven.plugins maven-deploy-plugin ${maven-deploy-plugin.version} @@ -62,6 +113,10 @@ spotbugs-maven-plugin ${spotbugs-maven-plugin.version} + + + maven-enforcer-plugin + diff --git a/yoti-sdk-api/pom.xml b/yoti-sdk-api/pom.xml index 721095648..f38e0752e 100644 --- a/yoti-sdk-api/pom.xml +++ b/yoti-sdk-api/pom.xml @@ -11,7 +11,7 @@ com.yoti yoti-sdk-parent - 3.8.0 + 3.9.0 ../yoti-sdk-parent @@ -87,7 +87,6 @@ animal-sniffer-maven-plugin - org.apache.maven.plugins maven-enforcer-plugin @@ -95,11 +94,9 @@ ${maven-compiler-plugin.version} - org.apache.maven.plugins maven-source-plugin - org.apache.maven.plugins maven-javadoc-plugin @@ -121,7 +118,6 @@ - org.apache.maven.plugins maven-project-info-reports-plugin diff --git a/yoti-sdk-api/spotbugs/exclude-filter.xml b/yoti-sdk-api/spotbugs/exclude-filter.xml index c1a507e96..827443487 100644 --- a/yoti-sdk-api/spotbugs/exclude-filter.xml +++ b/yoti-sdk-api/spotbugs/exclude-filter.xml @@ -22,6 +22,10 @@ + + + + diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/ActivityDetails.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/ActivityDetails.java index ae5263d36..794fec6ce 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/ActivityDetails.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/ActivityDetails.java @@ -1,6 +1,6 @@ package com.yoti.api.client; -import static com.yoti.api.client.spi.remote.util.Validation.notNull; +import static com.yoti.validation.Validation.notNull; import static org.bouncycastle.util.encoders.Base64.toBase64String; @@ -13,26 +13,26 @@ public final class ActivityDetails { private final String rememberMeId; private final String parentRememberMeId; - private final ApplicationProfile applicationProfile; - private final HumanProfile userProfile; + private final ApplicationProfile thisPartyProfile; + private final HumanProfile otherPartyProfile; private final Date timestamp; private final String receiptId; private final ExtraData extraData; public ActivityDetails(String rememberMeId, String parentRememberMeId, - HumanProfile userProfile, - ApplicationProfile applicationProfile, + HumanProfile otherPartyProfile, + ApplicationProfile thisPartyProfile, ExtraData extraData, Date timestamp, byte[] receiptId) { - this.rememberMeId = notNull(rememberMeId, "Remember Me id"); + this.rememberMeId = rememberMeId; this.parentRememberMeId = parentRememberMeId; - this.userProfile = notNull(userProfile, "User profile"); - this.applicationProfile = notNull(applicationProfile, "Application profile"); + this.otherPartyProfile = notNull(otherPartyProfile, "User profile"); + this.thisPartyProfile = notNull(thisPartyProfile, "Application profile"); this.timestamp = notNull(timestamp, "Timestamp"); this.receiptId = toBase64String(notNull(receiptId, "Receipt id")); - this.extraData = notNull(extraData, "extraData"); + this.extraData = extraData; } /** @@ -41,7 +41,7 @@ public ActivityDetails(String rememberMeId, * @return profile containing attributes for the user */ public HumanProfile getUserProfile() { - return userProfile; + return otherPartyProfile; } /** @@ -50,7 +50,7 @@ public HumanProfile getUserProfile() { * @return profile containing attributes for the application */ public ApplicationProfile getApplicationProfile() { - return applicationProfile; + return thisPartyProfile; } /** diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/ActivityFailureException.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/ActivityFailureException.java index 37d17f7b6..b16f4262e 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/ActivityFailureException.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/ActivityFailureException.java @@ -21,7 +21,10 @@ public ActivityFailureException(ProfileResponse profile) { String.format( ERROR_MSG, profile.getReceipt().getDisplayReceiptId(), - Optional.ofNullable(profile.getError()).map(e -> String.format(" - %s", e)).orElse("")) + Optional.ofNullable(profile.getError()) + .map(error -> String.format(" - %s", error)) + .orElse("") + ) ); errorDetails = profile.getError(); } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SessionSpec.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SessionSpec.java index e15317a61..b7a0a763a 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SessionSpec.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/SessionSpec.java @@ -7,6 +7,7 @@ import com.yoti.api.client.docs.session.create.check.RequestedCheck; import com.yoti.api.client.docs.session.create.filters.RequiredDocument; +import com.yoti.api.client.docs.session.create.identityprofile.advanced.AdvancedIdentityProfileRequirementsPayload; import com.yoti.api.client.docs.session.create.resources.ResourceCreationContainer; import com.yoti.api.client.docs.session.create.task.RequestedTask; @@ -56,6 +57,9 @@ public class SessionSpec { @JsonProperty(Property.IDENTITY_PROFILE_REQUIREMENTS) private final Map identityProfile; + @JsonProperty(Property.ADVANCED_IDENTITY_PROFILE_REQUIREMENTS) + private final AdvancedIdentityProfileRequirementsPayload advancedIdentityProfileRequirements; + @JsonProperty(Property.SUBJECT) private final Map subject; @@ -80,7 +84,8 @@ public class SessionSpec { Map identityProfile, Map subject, ResourceCreationContainer resources, - Boolean createIdentityProfilePreview) { + Boolean createIdentityProfilePreview, + AdvancedIdentityProfileRequirementsPayload advancedIdentityProfileRequirements) { this.clientSessionTokenTtl = clientSessionTokenTtl; this.resourcesTtl = resourcesTtl; this.importToken = importToken; @@ -97,6 +102,7 @@ public class SessionSpec { this.subject = subject; this.resources = resources; this.createIdentityProfilePreview = createIdentityProfilePreview; + this.advancedIdentityProfileRequirements = advancedIdentityProfileRequirements; } public static Builder builder() { @@ -248,6 +254,15 @@ public Boolean getCreateIdentityProfilePreview() { return createIdentityProfilePreview; } + /** + * The Advanced Identity Profile that is being requested. + * + * @return the advanced identity profile payload + */ + public AdvancedIdentityProfileRequirementsPayload getAdvancedIdentityProfileRequirements() { + return advancedIdentityProfileRequirements; + } + public static class Builder { private final List> requestedChecks; @@ -263,6 +278,7 @@ public static class Builder { private IbvOptions ibvOptions; private ZonedDateTime sessionDeadline; private Map identityProfile; + private AdvancedIdentityProfileRequirementsPayload advancedIdentityProfileRequirementsPayload; private Map subject; private ResourceCreationContainer resources; private Boolean createIdentityProfilePreview; @@ -450,6 +466,17 @@ public Builder withCreateIdentityProfilePreview(boolean createIdentityProfilePre return this; } + /** + * Sets the advanced identity profile requirements to be requested + * + * @param advancedIdentityProfileRequirements the advanced identity profile requirements + * @return the builder + */ + public Builder withAdvancedIdentityProfileRequirements(AdvancedIdentityProfileRequirementsPayload advancedIdentityProfileRequirements) { + this.advancedIdentityProfileRequirementsPayload = advancedIdentityProfileRequirements; + return this; + } + /** * Builds the {@link SessionSpec} based on the values supplied to the builder * @@ -472,7 +499,8 @@ public SessionSpec build() { identityProfile, subject, resources, - createIdentityProfilePreview); + createIdentityProfilePreview, + advancedIdentityProfileRequirementsPayload); } } @@ -490,6 +518,7 @@ private static final class Property { private static final String BLOCK_BIOMETRIC_CONSENT = "block_biometric_consent"; private static final String IBV_OPTIONS = "ibv_options"; private static final String IDENTITY_PROFILE_REQUIREMENTS = "identity_profile_requirements"; + private static final String ADVANCED_IDENTITY_PROFILE_REQUIREMENTS = "advanced_identity_profile_requirements"; private static final String SUBJECT = "subject"; private static final String RESOURCES = "resources"; private static final String CREATE_IDENTITY_PROFILE_PREVIEW = "create_identity_profile_preview"; diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/advanced/AdvancedIdentityProfilePayload.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/advanced/AdvancedIdentityProfilePayload.java new file mode 100644 index 000000000..cad49ebf4 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/advanced/AdvancedIdentityProfilePayload.java @@ -0,0 +1,80 @@ +package com.yoti.api.client.docs.session.create.identityprofile.advanced; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AdvancedIdentityProfilePayload { + + @JsonProperty("trust_framework") + private final String trustFramework; + + @JsonProperty("schemes") + private final List schemes; + + private AdvancedIdentityProfilePayload(String trustFramework, List schemes) { + this.trustFramework = trustFramework; + this.schemes = schemes; + } + + public static AdvancedIdentityProfilePayload.Builder builder() { + return new AdvancedIdentityProfilePayload.Builder(); + } + + /** + * Returns the trust framework of the profile being requested + * + * @return the trust framework + */ + public String getTrustFramework() { + return trustFramework; + } + + /** + * Returns the schemes being requested under the trust framework + * + * @return the schemes + */ + public List getSchemes() { + return schemes; + } + + public static final class Builder { + + private String trustFramework; + private List schemes; + + private Builder() { + schemes = new ArrayList<>(); + } + + /** + * Sets the trust framework of the requested profile + * + * @param trustFramework the trust framework + * @return the builder + */ + public Builder withTrustFramework(String trustFramework) { + this.trustFramework = trustFramework; + return this; + } + + /** + * Adds a scheme to be requested under the trust framework + * + * @param scheme the scheme + * @return the builder + */ + public Builder withScheme(AdvancedIdentityProfileSchemePayload scheme) { + this.schemes.add(scheme); + return this; + } + + public AdvancedIdentityProfilePayload build() { + return new AdvancedIdentityProfilePayload(trustFramework, schemes); + } + + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/advanced/AdvancedIdentityProfileRequirementsPayload.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/advanced/AdvancedIdentityProfileRequirementsPayload.java new file mode 100644 index 000000000..b74f820fb --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/advanced/AdvancedIdentityProfileRequirementsPayload.java @@ -0,0 +1,49 @@ +package com.yoti.api.client.docs.session.create.identityprofile.advanced; + +import java.util.ArrayList; +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AdvancedIdentityProfileRequirementsPayload { + + @JsonProperty("profiles") + private final List profiles; + + private AdvancedIdentityProfileRequirementsPayload(List profiles) { + this.profiles = profiles; + } + + public static AdvancedIdentityProfileRequirementsPayload.Builder builder() { + return new AdvancedIdentityProfileRequirementsPayload.Builder(); + } + + /** + * Returns the list of profiles that have been requested as part of the Advanced Identity Profile + * + * @return the list of profiles + */ + public List getProfiles() { + return profiles; + } + + public static final class Builder { + + private List profiles; + + private Builder() { + profiles = new ArrayList<>(); + } + + public Builder withProfile(AdvancedIdentityProfilePayload profile) { + this.profiles.add(profile); + return this; + } + + public AdvancedIdentityProfileRequirementsPayload build() { + return new AdvancedIdentityProfileRequirementsPayload(profiles); + } + + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/advanced/AdvancedIdentityProfileSchemeConfigPayload.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/advanced/AdvancedIdentityProfileSchemeConfigPayload.java new file mode 100644 index 000000000..9e1d426b0 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/advanced/AdvancedIdentityProfileSchemeConfigPayload.java @@ -0,0 +1,53 @@ +package com.yoti.api.client.docs.session.create.identityprofile.advanced; + +import com.yoti.api.client.docs.session.create.filters.DocumentFilter; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AdvancedIdentityProfileSchemeConfigPayload { + + @JsonProperty("filter") + private final DocumentFilter filter; + + private AdvancedIdentityProfileSchemeConfigPayload(DocumentFilter filter) { + this.filter = filter; + } + + public static AdvancedIdentityProfileSchemeConfigPayload.Builder builder() { + return new AdvancedIdentityProfileSchemeConfigPayload.Builder(); + } + + /** + * Gets the filter for the configuration + * + * @return the filter + */ + public DocumentFilter getFilter() { + return filter; + } + + public static final class Builder { + + private DocumentFilter filter; + + private Builder() {} + + /** + * Sets the filter for the scheme configuration + * + * @param filter the document filter + * @return the builder + */ + public Builder withFilter(DocumentFilter filter) { + this.filter = filter; + return this; + } + + public AdvancedIdentityProfileSchemeConfigPayload build() { + return new AdvancedIdentityProfileSchemeConfigPayload(filter); + } + + } + + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/advanced/AdvancedIdentityProfileSchemePayload.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/advanced/AdvancedIdentityProfileSchemePayload.java new file mode 100644 index 000000000..0f4028ffc --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/create/identityprofile/advanced/AdvancedIdentityProfileSchemePayload.java @@ -0,0 +1,104 @@ +package com.yoti.api.client.docs.session.create.identityprofile.advanced; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AdvancedIdentityProfileSchemePayload { + + @JsonProperty("type") + private final String type; + + @JsonProperty("objective") + private final String objective; + + @JsonProperty("label") + private final String label; + + @JsonProperty("config") + private final AdvancedIdentityProfileSchemeConfigPayload config; + + private AdvancedIdentityProfileSchemePayload(String type, String objective, String label, AdvancedIdentityProfileSchemeConfigPayload config) { + this.type = type; + this.objective = objective; + this.label = label; + this.config = config; + } + + public static AdvancedIdentityProfileSchemePayload.Builder builder() { + return new AdvancedIdentityProfileSchemePayload.Builder(); + } + + public String getType() { + return type; + } + + public String getObjective() { + return objective; + } + + public String getLabel() { + return label; + } + + public AdvancedIdentityProfileSchemeConfigPayload getConfig() { + return config; + } + + public static final class Builder { + + private String type; + private String objective; + private String label; + private AdvancedIdentityProfileSchemeConfigPayload config; + + private Builder() {} + + /** + * Sets the type of the scheme + * + * @param type the type + * @return the builder + */ + public Builder withType(String type) { + this.type = type; + return this; + } + + /** + * Sets the objective of the scheme + * + * @param objective the objective + * @return the builder + */ + public Builder withObjective(String objective) { + this.objective = objective; + return this; + } + + /** + * Sets the label for the scheme + * + * @param label the label + * @return the builder + */ + public Builder withLabel(String label) { + this.label = label; + return this; + } + + /** + * Sets the configuration for the scheme + * + * @param config the configuration + * @return the builder + */ + public Builder withConfig(AdvancedIdentityProfileSchemeConfigPayload config) { + this.config = config; + return this; + } + + public AdvancedIdentityProfileSchemePayload build() { + return new AdvancedIdentityProfileSchemePayload(type, objective, label, config); + } + + } +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/GetSessionResult.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/GetSessionResult.java index 6d77e4456..5c56bad89 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/GetSessionResult.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/GetSessionResult.java @@ -3,6 +3,8 @@ import java.util.List; import java.util.stream.Collectors; +import com.yoti.api.client.docs.session.retrieve.identityprofile.advanced.AdvancedIdentityProfileResponse; + import com.fasterxml.jackson.annotation.JsonProperty; public class GetSessionResult { @@ -34,9 +36,15 @@ public class GetSessionResult { @JsonProperty(Property.IDENTITY_PROFILE) private IdentityProfileResponse identityProfile; + @JsonProperty(Property.ADVANCED_IDENTITY_PROFILE) + private AdvancedIdentityProfileResponse advancedIdentityProfile; + @JsonProperty(Property.IDENTITY_PROFILE_PREVIEW) private IdentityProfilePreviewResponse identityProfilePreview; + @JsonProperty(Property.ADVANCED_IDENTITY_PROFILE_PREVIEW) + private IdentityProfilePreviewResponse advancedIdentityProfilePreview; + @JsonProperty(Property.IMPORT_TOKEN) private ImportTokenResponse importToken; @@ -76,10 +84,18 @@ public IdentityProfileResponse getIdentityProfile() { return identityProfile; } + public AdvancedIdentityProfileResponse getAdvancedIdentityProfile() { + return advancedIdentityProfile; + } + public IdentityProfilePreviewResponse getIdentityProfilePreview() { return identityProfilePreview; } + public IdentityProfilePreviewResponse getAdvancedIdentityProfilePreview() { + return advancedIdentityProfilePreview; + } + public ImportTokenResponse getImportToken() { return importToken; } @@ -162,7 +178,9 @@ private static final class Property { private static final String CHECKS = "checks"; private static final String RESOURCES = "resources"; private static final String IDENTITY_PROFILE = "identity_profile"; + private static final String ADVANCED_IDENTITY_PROFILE = "advanced_identity_profile"; private static final String IDENTITY_PROFILE_PREVIEW = "identity_profile_preview"; + private static final String ADVANCED_IDENTITY_PROFILE_PREVIEW = "advanced_identity_profile_preview"; private static final String IMPORT_TOKEN = "import_token"; private Property() { } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdentityProfileFailureResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdentityProfileFailureResponse.java index 55dbf4ce7..8c73a8b0c 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdentityProfileFailureResponse.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/IdentityProfileFailureResponse.java @@ -1,5 +1,7 @@ package com.yoti.api.client.docs.session.retrieve; +import java.util.List; + import com.fasterxml.jackson.annotation.JsonProperty; public class IdentityProfileFailureResponse { @@ -7,8 +9,15 @@ public class IdentityProfileFailureResponse { @JsonProperty("reason_code") private String reasonCode; + @JsonProperty("requirements_not_met_details") + private List requirementsNotMetDetails; + public String getReasonCode() { return reasonCode; } + public List getRequirementsNotMetDetails() { + return requirementsNotMetDetails; + } + } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/RequirementNotMetDetailsResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/RequirementNotMetDetailsResponse.java new file mode 100644 index 000000000..5927ca047 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/RequirementNotMetDetailsResponse.java @@ -0,0 +1,42 @@ +package com.yoti.api.client.docs.session.retrieve; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class RequirementNotMetDetailsResponse { + + @JsonProperty("failure_type") + private String failureType; + + @JsonProperty("document_type") + private String documentType; + + @JsonProperty("document_country_iso_code") + private String documentCountryIsoCode; + + @JsonProperty("audit_id") + private String auditId; + + @JsonProperty("details") + private String details; + + public String getFailureType() { + return failureType; + } + + public String getDocumentType() { + return documentType; + } + + public String getDocumentCountryIsoCode() { + return documentCountryIsoCode; + } + + public String getAuditId() { + return auditId; + } + + public String getDetails() { + return details; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileReportResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileReportResponse.java new file mode 100644 index 000000000..b2906e696 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileReportResponse.java @@ -0,0 +1,35 @@ +package com.yoti.api.client.docs.session.retrieve.identityprofile.advanced; + +import java.util.List; + +import com.yoti.api.client.docs.session.retrieve.MediaResponse; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AdvancedIdentityProfileReportResponse { + + @JsonProperty("compliance") + private List compliance; + + @JsonProperty("media") + private MediaResponse media; + + /** + * Gets the compliance reports for the advanced identity profile + * + * @return the compliance reports + */ + public List getCompliance() { + return compliance; + } + + /** + * Gets the media for the generated profile of the advanced identity profile + * + * @return the generated media + */ + public MediaResponse getMedia() { + return media; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileResponse.java new file mode 100644 index 000000000..9d1e9c35a --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileResponse.java @@ -0,0 +1,57 @@ +package com.yoti.api.client.docs.session.retrieve.identityprofile.advanced; + +import com.yoti.api.client.docs.session.retrieve.IdentityProfileFailureResponse; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AdvancedIdentityProfileResponse { + + @JsonProperty("subject_id") + private String subjectId; + + @JsonProperty("result") + private String result; + + @JsonProperty("failure_reason") + private IdentityProfileFailureResponse failureReason; + + @JsonProperty("identity_profile_report") + private AdvancedIdentityProfileReportResponse identityProfileReport; + + /** + * Returns the subject ID of the Advanced Identity Profile + * + * @return the subject ID + */ + public String getSubjectId() { + return subjectId; + } + + /** + * Returns the result of the Advanced Identity Profile + * + * @return the result + */ + public String getResult() { + return result; + } + + /** + * Returns the failure reason of the Advanced Identity Profile + * + * @return the failure reason + */ + public IdentityProfileFailureResponse getFailureReason() { + return failureReason; + } + + /** + * Returns the report for the Advanced Identity Profile + * + * @return the report + */ + public AdvancedIdentityProfileReportResponse getIdentityProfileReport() { + return identityProfileReport; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileSchemeComplianceReportResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileSchemeComplianceReportResponse.java new file mode 100644 index 000000000..9cc05a67d --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileSchemeComplianceReportResponse.java @@ -0,0 +1,28 @@ +package com.yoti.api.client.docs.session.retrieve.identityprofile.advanced; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AdvancedIdentityProfileSchemeComplianceReportResponse { + + @JsonProperty("scheme") + private AdvancedIdentityProfileSchemeResponse scheme; + + @JsonProperty("requirements_met") + private Boolean requirementsMet; + + @JsonProperty("requirements_not_met_info") + private String requirementsNotMetInfo; + + public AdvancedIdentityProfileSchemeResponse getScheme() { + return scheme; + } + + public Boolean getRequirementsMet() { + return requirementsMet; + } + + public String getRequirementsNotMetInfo() { + return requirementsNotMetInfo; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileSchemeResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileSchemeResponse.java new file mode 100644 index 000000000..62348d9c1 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileSchemeResponse.java @@ -0,0 +1,28 @@ +package com.yoti.api.client.docs.session.retrieve.identityprofile.advanced; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AdvancedIdentityProfileSchemeResponse { + + @JsonProperty("type") + private String type; + + @JsonProperty("objective") + private String objective; + + @JsonProperty("label") + private String label; + + public String getType() { + return type; + } + + public String getObjective() { + return objective; + } + + public String getLabel() { + return label; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileTrustFrameworkResponse.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileTrustFrameworkResponse.java new file mode 100644 index 000000000..33cdc50aa --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/docs/session/retrieve/identityprofile/advanced/AdvancedIdentityProfileTrustFrameworkResponse.java @@ -0,0 +1,33 @@ +package com.yoti.api.client.docs.session.retrieve.identityprofile.advanced; + +import java.util.List; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class AdvancedIdentityProfileTrustFrameworkResponse { + + @JsonProperty("trust_framework") + private String trustFramework; + + @JsonProperty("schemes_compliance") + private List schemesCompliance; + + /** + * Gets the trust framework for the report + * + * @return the trust framework + */ + public String getTrustFramework() { + return trustFramework; + } + + /** + * Gets the list of schemes that are part of the trust framework report + * + * @return the scheme compliances + */ + public List getSchemesCompliance() { + return schemesCompliance; + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/policy/Policy.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/policy/Policy.java index 06d8bad28..7c377ca88 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/policy/Policy.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/policy/Policy.java @@ -32,12 +32,16 @@ public class Policy { @JsonProperty(Property.IDENTITY_PROFILE_REQUIREMENTS) private final Object identityProfile; + @JsonProperty(Property.ADVANCED_IDENTITY_PROFILE_REQUIREMENTS) + private final Object advancedIdentityProfile; + private Policy(Builder builder) { wantedAttributes = builder.wantedAttributes.values(); wantedAuthTypes = builder.wantedAuthTypes; wantedRememberMe = builder.wantedRememberMe; wantedRememberMeOptional = builder.wantedRememberMeOptional; identityProfile = builder.identityProfile; + advancedIdentityProfile = builder.advancedIdentityProfile; } public Collection getWantedAttributes() { @@ -60,6 +64,10 @@ public Object getIdentityProfile() { return identityProfile; } + public Object getAdvancedIdentityProfile() { + return advancedIdentityProfile; + } + public static Builder builder() { return new Builder(); } @@ -75,6 +83,7 @@ public static class Builder { private boolean wantedRememberMe; private boolean wantedRememberMeOptional; private Object identityProfile; + private Object advancedIdentityProfile; private Builder() { wantedAttributes = new HashMap<>(); @@ -266,6 +275,11 @@ public Builder withIdentityProfile(Object identityProfile) { this.identityProfile = identityProfile; return this; } + + public Builder withAdvancedIdentityProfile(Object advancedIdentityProfile) { + this.advancedIdentityProfile = advancedIdentityProfile; + return this; + } public Policy build() { return new Policy(this); @@ -280,6 +294,7 @@ private static final class Property { private static final String WANTED_REMEMBER_ME = "wanted_remember_me"; private static final String WANTED_REMEMBER_ME_OPTIONAL = "wanted_remember_me_optional"; private static final String IDENTITY_PROFILE_REQUIREMENTS = "identity_profile_requirements"; + private static final String ADVANCED_IDENTITY_PROFILE_REQUIREMENTS = "advanced_identity_profile_requirements"; } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/policy/WantedAttribute.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/policy/WantedAttribute.java index 010b0dc00..ab556dcd3 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/policy/WantedAttribute.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/identity/policy/WantedAttribute.java @@ -1,11 +1,14 @@ package com.yoti.api.client.identity.policy; +import static com.yoti.validation.Validation.notNullOrEmpty; + import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import com.yoti.api.client.identity.constraint.Constraint; -import com.yoti.validation.Validation; import com.fasterxml.jackson.annotation.JsonProperty; @@ -26,12 +29,16 @@ public class WantedAttribute { @JsonProperty(Property.CONSTRAINTS) private final List constraints; + @JsonProperty(Property.ALTERNATIVE_NAMES) + private final Set alternativeNames; + private WantedAttribute(Builder builder) { name = builder.name; derivation = builder.derivation; optional = builder.optional; acceptSelfAsserted = builder.acceptSelfAsserted; - constraints = builder.constraints; + constraints = Collections.unmodifiableList(builder.constraints); + alternativeNames = Collections.unmodifiableSet(builder.alternativeNames); } public String getName() { @@ -58,6 +65,10 @@ public boolean hasConstraints() { return !constraints.isEmpty(); } + public Set getAlternativeNames() { + return alternativeNames; + } + public static Builder builder() { return new Builder(); } @@ -69,9 +80,11 @@ public static class Builder { private boolean optional; private Boolean acceptSelfAsserted; private List constraints; + private Set alternativeNames; private Builder() { - this.constraints = new ArrayList<>(); + constraints = new ArrayList<>(); + alternativeNames = new HashSet<>(); } public Builder withName(String name) { @@ -95,17 +108,27 @@ public Builder withAcceptSelfAsserted(boolean acceptSelfAsserted) { } public Builder withConstraints(List constraints) { - this.constraints = Collections.unmodifiableList(constraints); + this.constraints.addAll(constraints); return this; } public Builder withConstraint(Constraint constraint) { - this.constraints.add(constraint); + constraints.add(constraint); + return this; + } + + public Builder withAlternativeNames(Set alternativeNames) { + this.alternativeNames.addAll(alternativeNames); + return this; + } + + public Builder withAlternativeName(String alternativeName) { + alternativeNames.add(alternativeName); return this; } public WantedAttribute build() { - Validation.notNullOrEmpty(name, Property.NAME); + notNullOrEmpty(name, Property.NAME); return new WantedAttribute(this); } @@ -119,6 +142,9 @@ private static final class Property { private static final String OPTIONAL = "optional"; private static final String ACCEPT_SELF_ASSERTED = "accept_self_asserted"; private static final String CONSTRAINTS = "constraints"; + private static final String ALTERNATIVE_NAMES = "alternative_names"; + + private Property() { } } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/shareurl/policy/DynamicPolicy.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/shareurl/policy/DynamicPolicy.java index 43a4668fb..492e708db 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/shareurl/policy/DynamicPolicy.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/shareurl/policy/DynamicPolicy.java @@ -13,9 +13,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; -/** - * Set of data required to request a sharing transaction - */ public class DynamicPolicy { @JsonProperty(Property.WANTED) @@ -33,67 +30,46 @@ public class DynamicPolicy { @JsonProperty(Property.IDENTITY_PROFILE_REQUIREMENTS) private final Object identityProfile; - DynamicPolicy(Collection wantedAttributes, - Set wantedAuthTypes, - boolean wantedRememberMe, - boolean wantedRememberMeOptional, - Object identityProfile) { - this.wantedAttributes = wantedAttributes; - this.wantedAuthTypes = wantedAuthTypes; - this.wantedRememberMe = wantedRememberMe; - this.wantedRememberMeOptional = wantedRememberMeOptional; - this.identityProfile = identityProfile; + @JsonProperty(Property.ADVANCED_IDENTITY_PROFILE_REQUIREMENTS) + private final Object advancedIdentityProfile; + + private DynamicPolicy(Builder builder) { + wantedAttributes = builder.wantedAttributes.values(); + wantedAuthTypes = builder.wantedAuthTypes; + wantedRememberMe = builder.wantedRememberMe; + wantedRememberMeOptional = builder.wantedRememberMeOptional; + identityProfile = builder.identityProfile; + advancedIdentityProfile = builder.advancedIdentityProfile; } public static DynamicPolicy.Builder builder() { return new DynamicPolicy.Builder(); } - /** - * Set of required {@link WantedAttribute} - * - * @return attributes - */ public Collection getWantedAttributes() { return wantedAttributes; } - /** - * Type of authentications - * - * @return authentication types - */ public Set getWantedAuthTypes() { return wantedAuthTypes; } - /** - * Allows to remember the {@link DynamicPolicy} - * - * @return RememberMe - */ public boolean isWantedRememberMe() { return wantedRememberMe; } - /** - * Defines the {@link #isWantedRememberMe()} optional for the sharing - * - * @return RememberMeOptional - */ public boolean isWantedRememberMeOptional() { return wantedRememberMeOptional; } - /** - * Defines a required identity profile within the scope of a trust framework and scheme. - * - * @return IdentityProfile - */ public Object getIdentityProfile() { return identityProfile; } + public Object getAdvancedIdentityProfile() { + return advancedIdentityProfile; + } + public static class Builder { private static final int SELFIE_AUTH_TYPE = 1; @@ -104,6 +80,7 @@ public static class Builder { private boolean wantedRememberMe; private boolean wantedRememberMeOptional; private Object identityProfile; + private Object advancedIdentityProfile; private Builder() { } @@ -114,7 +91,7 @@ public Builder withWantedAttribute(WantedAttribute wantedAttribute) { key += "-" + wantedAttribute.getConstraints().hashCode(); } - this.wantedAttributes.put(key, wantedAttribute); + wantedAttributes.put(key, wantedAttribute); return this; } @@ -245,11 +222,11 @@ public Builder withEmail(boolean optional) { } public Builder withSelfieAuthentication(boolean enabled) { - return this.withWantedAuthType(SELFIE_AUTH_TYPE, enabled); + return withWantedAuthType(SELFIE_AUTH_TYPE, enabled); } public Builder withPinAuthentication(boolean enabled) { - return this.withWantedAuthType(PIN_AUTH_TYPE, enabled); + return withWantedAuthType(PIN_AUTH_TYPE, enabled); } public Builder withWantedAuthType(int wantedAuthType) { @@ -259,7 +236,7 @@ public Builder withWantedAuthType(int wantedAuthType) { public Builder withWantedAuthType(int wantedAuthType, boolean enabled) { if (enabled) { - return this.withWantedAuthType(wantedAuthType); + return withWantedAuthType(wantedAuthType); } else { this.wantedAuthTypes.remove(wantedAuthType); return this; @@ -280,15 +257,14 @@ public Builder withIdentityProfile(Object identityProfile) { this.identityProfile = identityProfile; return this; } + + public Builder withAdvancedIdentityProfile(Object advancedIdentityProfile) { + this.advancedIdentityProfile = advancedIdentityProfile; + return this; + } public DynamicPolicy build() { - return new DynamicPolicy( - wantedAttributes.values(), - wantedAuthTypes, - wantedRememberMe, - wantedRememberMeOptional, - identityProfile - ); + return new DynamicPolicy(this); } } @@ -300,6 +276,7 @@ private static final class Property { private static final String WANTED_REMEMBER_ME = "wanted_remember_me"; private static final String WANTED_REMEMBER_ME_OPTIONAL = "wanted_remember_me_optional"; private static final String IDENTITY_PROFILE_REQUIREMENTS = "identity_profile_requirements"; + private static final String ADVANCED_IDENTITY_PROFILE_REQUIREMENTS = "advanced_identity_profile_requirements"; private Property() { } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/shareurl/policy/WantedAttribute.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/shareurl/policy/WantedAttribute.java index e910a6637..1709dc587 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/shareurl/policy/WantedAttribute.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/shareurl/policy/WantedAttribute.java @@ -1,52 +1,51 @@ package com.yoti.api.client.shareurl.policy; -import static com.yoti.api.client.spi.remote.util.Validation.notNullOrEmpty; +import static com.yoti.validation.Validation.notNullOrEmpty; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; import com.yoti.api.client.shareurl.constraint.Constraint; import com.fasterxml.jackson.annotation.JsonProperty; /** - * Type and content of an user detail + * Type and content of a user detail */ public class WantedAttribute { - @JsonProperty("name") + @JsonProperty(Property.NAME) private final String name; - @JsonProperty("derivation") + @JsonProperty(Property.DERIVATION) private final String derivation; - @JsonProperty("optional") + @JsonProperty(Property.OPTIONAL) private final boolean optional; - @JsonProperty("accept_self_asserted") + @JsonProperty(Property.ACCEPT_SELF_ASSERTED) private final Boolean acceptSelfAsserted; - @JsonProperty("constraints") + @JsonProperty(Property.CONSTRAINTS) private final List constraints; - WantedAttribute(String name, String derivation, boolean optional, Boolean acceptSelfAsserted, List constraints) { - notNullOrEmpty(name, "name"); + @JsonProperty(Property.ALTERNATIVE_NAMES) + private final Set alternativeNames; - this.name = name; - this.derivation = derivation; - this.optional = optional; - this.acceptSelfAsserted = acceptSelfAsserted; - - if (constraints == null) { - this.constraints = Collections.emptyList(); - } else { - this.constraints = constraints; - } + private WantedAttribute(Builder builder) { + name = builder.name; + derivation = builder.derivation; + optional = builder.optional; + acceptSelfAsserted = builder.acceptSelfAsserted; + constraints = Collections.unmodifiableList(builder.constraints); + alternativeNames = Collections.unmodifiableSet(builder.alternativeNames); } - public static WantedAttribute.Builder builder() { - return new WantedAttribute.Builder(); + public static Builder builder() { + return new Builder(); } /** @@ -78,6 +77,7 @@ public boolean isOptional() { /** * Allows self asserted attributes + * * @return accept self asserted */ public Boolean getAcceptSelfAsserted() { @@ -93,6 +93,21 @@ public List getConstraints() { return constraints; } + /** + *
+     * Alternatives for the attribute name that is being requested.
+     *
+     * The provided alternative attribute will be used exactly in the same way:
+     *     - if a derivation is requested it will be applied on the alternative
+     *     - if constraints are defined the alternative attribute will have to comply
+     * 
+ * + * @return the Set of alternative names + */ + public Set getAlternativeNames() { + return alternativeNames; + } + public static class Builder { private String name; @@ -100,9 +115,11 @@ public static class Builder { private boolean optional; private Boolean acceptSelfAsserted; private List constraints; + private Set alternativeNames; private Builder() { - this.constraints = new ArrayList<>(); + constraints = new ArrayList<>(); + alternativeNames = new HashSet<>(); } public Builder withName(String name) { @@ -126,19 +143,44 @@ public Builder withAcceptSelfAsserted(boolean acceptSelfAsserted) { } public Builder withConstraints(List constraints) { - this.constraints = Collections.unmodifiableList(constraints); + this.constraints.addAll(constraints); return this; } public Builder withConstraint(Constraint constraint) { - this.constraints.add(constraint); + constraints.add(constraint); + return this; + } + + public Builder withAlternativeNames(Set alternativeNames) { + this.alternativeNames.addAll(alternativeNames); + return this; + } + + public Builder withAlternativeName(String alternativeName) { + alternativeNames.add(alternativeName); return this; } public WantedAttribute build() { - return new WantedAttribute(name, derivation, optional, acceptSelfAsserted, constraints); + notNullOrEmpty(name, Property.NAME); + + return new WantedAttribute(this); } } + private static final class Property { + + private static final String NAME = "name"; + private static final String DERIVATION = "derivation"; + private static final String OPTIONAL = "optional"; + private static final String ACCEPT_SELF_ASSERTED = "accept_self_asserted"; + private static final String CONSTRAINTS = "constraints"; + private static final String ALTERNATIVE_NAMES = "alternative_names"; + + private Property() { } + + } + } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/ActivityDetailsFactory.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/ActivityDetailsFactory.java index cd3f1b3d1..cd7248075 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/ActivityDetailsFactory.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/ActivityDetailsFactory.java @@ -3,7 +3,7 @@ import static com.yoti.api.client.spi.remote.call.YotiConstants.DEFAULT_CHARSET; import static com.yoti.api.client.spi.remote.call.YotiConstants.RFC3339_PATTERN; import static com.yoti.api.client.spi.remote.call.YotiConstants.SYMMETRIC_CIPHER; -import static com.yoti.api.client.spi.remote.util.Validation.notNull; +import static com.yoti.validation.Validation.notNull; import java.io.UnsupportedEncodingException; import java.security.Key; @@ -53,11 +53,11 @@ public ActivityDetails create(Receipt receipt, PrivateKey privateKey) throws Pro byte[] decryptedKey = DecryptionHelper.decryptAsymmetric(receipt.getWrappedReceiptKey(), privateKey); Key secretKey = new SecretKeySpec(decryptedKey, SYMMETRIC_CIPHER); - List> userProfileAttr = attributeListReader.read(receipt.getOtherPartyProfile(), secretKey); - List> applicationProfileAttr = attributeListReader.read(receipt.getProfile(), secretKey); + List> otherPartyAttr = attributeListReader.read(receipt.getOtherPartyProfile(), secretKey); + List> thisPartyAttr = attributeListReader.read(receipt.getProfile(), secretKey); - HumanProfile userProfile = new HumanProfile(userProfileAttr); - ApplicationProfile applicationProfile = new ApplicationProfile(applicationProfileAttr); + HumanProfile otherPartyProfile = new HumanProfile(otherPartyAttr); + ApplicationProfile thisPartyProfile = new ApplicationProfile(thisPartyAttr); ExtraData extraData = parseExtraData(receipt.getExtraData(), secretKey); @@ -65,7 +65,15 @@ public ActivityDetails create(Receipt receipt, PrivateKey privateKey) throws Pro String parentRememberMeId = parseRememberMeId(receipt.getParentRememberMeId()); Date timestamp = parseTimestamp(receipt.getTimestamp()); - return new ActivityDetails(rememberMeId, parentRememberMeId, userProfile, applicationProfile, extraData, timestamp, receipt.getReceiptId()); + return new ActivityDetails( + rememberMeId, + parentRememberMeId, + otherPartyProfile, + thisPartyProfile, + extraData, + timestamp, + receipt.getReceiptId() + ); } private ExtraData parseExtraData(byte[] extraDataBytes, Key secretKey) throws ProfileException { diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ErrorDetails.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ErrorDetails.java index 91903054a..1f2b1ac88 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ErrorDetails.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ErrorDetails.java @@ -1,9 +1,12 @@ package com.yoti.api.client.spi.remote.call; import java.io.Serializable; +import java.util.Map; import java.util.Objects; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @JsonDeserialize(builder = ErrorDetails.Builder.class) @@ -11,12 +14,16 @@ public final class ErrorDetails implements Serializable { private static final long serialVersionUID = -6429196723990930305L; + private static final ObjectMapper MAPPER = new ObjectMapper(); + private final String code; private final String description; + private final String reason; private ErrorDetails(Builder builder) { this.code = builder.code; this.description = builder.description; + this.reason = builder.reason; } public static Builder builder() { @@ -31,6 +38,10 @@ public String getDescription() { return description; } + public String getReason() { + return reason; + } + @Override public boolean equals(Object o) { if (this == o) { @@ -51,13 +62,14 @@ public int hashCode() { @Override public String toString() { - return String.format("Error[code='%s', description='%s']", code, description); + return String.format("Error[code='%s', description='%s', reason='%s']", code, description, reason); } public static final class Builder { private String code; private String description; + private String reason; private Builder() { } @@ -73,6 +85,18 @@ public Builder description(String description) { return this; } + @JsonProperty(Property.REASON) + public Builder reason(Map map) { + try { + reason = MAPPER.writeValueAsString(map); + } catch (JsonProcessingException e) { + throw new ErrorDetailsException( + String.format("Failed to parse failure receipt error reason: '%s'", e.getMessage()) + ); + } + return this; + } + public ErrorDetails build() { return new ErrorDetails(this); } @@ -83,6 +107,7 @@ private static final class Property { private static final String ERROR_CODE = "error_code"; private static final String DESCRIPTION = "description"; + private static final String REASON = "error_reason"; private Property() { } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ErrorDetailsException.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ErrorDetailsException.java new file mode 100644 index 000000000..b4c8239a6 --- /dev/null +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ErrorDetailsException.java @@ -0,0 +1,9 @@ +package com.yoti.api.client.spi.remote.call; + +public class ErrorDetailsException extends RuntimeException { + + public ErrorDetailsException(String message) { + super(message); + } + +} diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ProfileService.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ProfileService.java index 5f9ba2ebb..fb2e5ecca 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ProfileService.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/ProfileService.java @@ -81,7 +81,7 @@ private ProfileResponse fetchReceipt(SignedRequest signedRequest) throws IOExcep case HTTP_INTERNAL_ERROR: throw new ProfileException("Error completing sharing: " + ex.getResponseBody(), ex); case HTTP_NOT_FOUND: - throw new ProfileException("Profile not found. This can be due to a used or expired token. Details: " + ex.getResponseBody(), ex); + throw new ProfileException("Profile not found. This can be due to a used or expired token.", ex); default: throw new ProfileException("Unexpected response: " + responseCode + " " + ex.getResponseBody(), ex); } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiConstants.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiConstants.java index 2de0ee21e..d51962446 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiConstants.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/YotiConstants.java @@ -29,7 +29,7 @@ private YotiConstants() {} public static final String CONTENT_TYPE_JPEG = "image/jpeg"; public static final String JAVA = "Java"; - public static final String SDK_VERSION = JAVA + "-3.8.0"; + public static final String SDK_VERSION = JAVA + "-3.9.0"; public static final String SIGNATURE_ALGORITHM = "SHA256withRSA"; public static final String ASYMMETRIC_CIPHER = "RSA/NONE/PKCS1Padding"; public static final String SYMMETRIC_CIPHER = "AES/CBC/PKCS7Padding"; diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/Receipt.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/Receipt.java index 13709fc6e..bbba848c5 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/Receipt.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/Receipt.java @@ -17,6 +17,7 @@ public final class Receipt { private final ApplicationContent applicationContent; private final UserContent userContent; private final String error; + private final String errorReason; private Receipt(Builder builder) { id = builder.id; @@ -27,6 +28,7 @@ private Receipt(Builder builder) { applicationContent = builder.applicationContent; userContent = builder.userContent; error = builder.error; + errorReason = builder.errorReason; } public String getId() { @@ -69,6 +71,10 @@ public Optional getError() { return Optional.ofNullable(error); } + public Optional getErrorReason() { + return Optional.ofNullable(errorReason); + } + public static Builder forReceipt(String id) { return new Builder(id); } @@ -84,6 +90,7 @@ public static final class Builder { private ApplicationContent applicationContent; private UserContent userContent; private String error; + private String errorReason; private Builder(String id) { this.id = id; @@ -124,6 +131,11 @@ public Builder error(String error) { return this; } + public Builder errorReason(String reason) { + errorReason = reason; + return this; + } + public Receipt build() { return new Receipt(this); } diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/ReceiptParser.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/ReceiptParser.java index 9b3a1e99b..9c57ef5fe 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/ReceiptParser.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/ReceiptParser.java @@ -73,11 +73,15 @@ public Receipt create(WrappedReceipt wrappedReceipt, ReceiptItemKey wrappedItemK } public Receipt create(WrappedReceipt failureReceipt) { - return Receipt.forReceipt(failureReceipt.getId()) + Receipt.Builder receipt = Receipt.forReceipt(failureReceipt.getId()) .sessionId(failureReceipt.getSessionId()) .timestamp(failureReceipt.getTimestamp()) - .error(failureReceipt.getError()) - .build(); + .error(failureReceipt.getError()); + + Optional.ofNullable(failureReceipt.getErrorReason()) + .ifPresent(receipt::errorReason); + + return receipt.build(); } private static Key decryptReceiptKey(byte[] wrappedKey, ReceiptItemKey wrappedItemKey, PrivateKey privateKey) { diff --git a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/WrappedReceipt.java b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/WrappedReceipt.java index 32d8d94eb..95f0b348a 100644 --- a/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/WrappedReceipt.java +++ b/yoti-sdk-api/src/main/java/com/yoti/api/client/spi/remote/call/identity/WrappedReceipt.java @@ -2,9 +2,12 @@ import java.time.OffsetDateTime; import java.util.Base64; +import java.util.Map; import java.util.Optional; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; @JsonDeserialize(builder = WrappedReceipt.Builder.class) @@ -20,6 +23,7 @@ public final class WrappedReceipt { private final byte[] parentRememberMeId; private final byte[] wrappedKey; private final String error; + private final String errorReason; private WrappedReceipt(Builder builder) { id = builder.id; @@ -32,6 +36,7 @@ private WrappedReceipt(Builder builder) { parentRememberMeId = builder.parentRememberMeId; wrappedKey = builder.wrappedKey; error = builder.error; + errorReason = builder.errorReason; } public String getId() { @@ -83,6 +88,10 @@ public String getError() { return error; } + public String getErrorReason() { + return errorReason; + } + public static final class Builder { private String id; @@ -95,6 +104,7 @@ public static final class Builder { private byte[] parentRememberMeId; private byte[] wrappedKey; private String error; + private String errorReason; private Builder() { } @@ -158,6 +168,16 @@ public Builder error(String error) { return this; } + @JsonProperty(Property.ERROR_REASON) + public Builder errorReason(Map reason) { + try { + this.errorReason = new ObjectMapper().writeValueAsString(reason); + } catch (JsonProcessingException e) { + throw new DigitalIdentityException("The reason of the failed share has an unexpected format"); + } + return this; + } + public WrappedReceipt build() { return new WrappedReceipt(this); } @@ -209,6 +229,7 @@ private static class Property { private static final String WRAPPED_ITEM_KEY_ID = "wrappedItemKeyId"; private static final String WRAPPED_KEY = "wrappedKey"; private static final String ERROR = "error"; + private static final String ERROR_REASON = "errorReason"; private static class Content { diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/ActivityDetailsTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/ActivityDetailsTest.java index 6dd3cdfeb..57f7fb673 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/ActivityDetailsTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/ActivityDetailsTest.java @@ -5,8 +5,8 @@ import java.util.Date; import org.bouncycastle.util.encoders.Base64; -import org.junit.Test; -import org.mockito.Mockito; +import org.junit.*; +import org.mockito.*; public class ActivityDetailsTest { @@ -18,22 +18,6 @@ public class ActivityDetailsTest { private static final byte[] RECEIPT_ID = { 1, 2, 3, 4, 5, 6, 7, 8 }; private static final String RECEIPT_ID_STRING = Base64.toBase64String(RECEIPT_ID); private static final Date TIMESTAMP = new Date(); - private static final byte[] SOME_SELFIE_BYTES = "selfieTestVal".getBytes(); - - @Test(expected = IllegalArgumentException.class) - public void shouldFailConstructionForNullRememberMeId() { - new ActivityDetails(null, null, USER_PROFILE, APP_PROFILE, EXTRA_DATA, TIMESTAMP, RECEIPT_ID); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldFailConstructionForNullUserProfile() { - new ActivityDetails(REMEMBER_ME, null, null, APP_PROFILE, EXTRA_DATA, TIMESTAMP, RECEIPT_ID); - } - - @Test(expected = IllegalArgumentException.class) - public void shouldFailConstructionForNullAppProfile() { - new ActivityDetails(REMEMBER_ME, null, USER_PROFILE, null, EXTRA_DATA, TIMESTAMP, RECEIPT_ID); - } @Test(expected = IllegalArgumentException.class) public void shouldFailConstructionForNullTimestamp() { @@ -45,11 +29,6 @@ public void shouldFailConstructionForNullReceiptId() { new ActivityDetails(REMEMBER_ME, null, USER_PROFILE, APP_PROFILE, EXTRA_DATA, TIMESTAMP, null); } - @Test(expected = IllegalArgumentException.class) - public void shouldFailConstructionForNullProfile() { - new ActivityDetails(REMEMBER_ME, null, null, APP_PROFILE, EXTRA_DATA, TIMESTAMP, RECEIPT_ID); - } - @Test public void shouldReturnUserId() { ActivityDetails s = new ActivityDetails(REMEMBER_ME, PARENT_REMEMBER_ME, USER_PROFILE, APP_PROFILE, EXTRA_DATA, TIMESTAMP, RECEIPT_ID); diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/common/IdentityProfile.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/common/IdentityProfile.java index af66d05b1..86a8e6bef 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/common/IdentityProfile.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/common/IdentityProfile.java @@ -4,10 +4,10 @@ public final class IdentityProfile { - @JsonProperty("trust_framework") + @JsonProperty(Share.Policy.Profile.TRUST_FRAMEWORK) private final String framework; - @JsonProperty("scheme") + @JsonProperty(Share.Policy.Profile.SCHEME) private final IdentityProfileScheme scheme; public IdentityProfile(String framework, IdentityProfileScheme scheme) { diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/common/IdentityProfileScheme.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/common/IdentityProfileScheme.java index fb9648aa7..ad91156f4 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/common/IdentityProfileScheme.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/common/IdentityProfileScheme.java @@ -4,10 +4,10 @@ public final class IdentityProfileScheme { - @JsonProperty("type") + @JsonProperty(Share.Policy.Profile.TYPE) private final String type; - @JsonProperty("objective") + @JsonProperty(Share.Policy.Profile.OBJECTIVE) private final String objective; public IdentityProfileScheme(String type, String objective) { diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/common/Share.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/common/Share.java new file mode 100644 index 000000000..53b980c2b --- /dev/null +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/common/Share.java @@ -0,0 +1,35 @@ +package com.yoti.api.client.common; + +public final class Share { + + public static final class Policy { + + public static final class Profile { + + private Profile() { } + + public static final String TYPE = "type"; + public static final String OBJECTIVE = "objective"; + public static final String TRUST_FRAMEWORK = "trust_framework"; + + // identity profile only + public static final String SCHEME = "scheme"; + public static final String IDENTITY_PROFILE_REQUIREMENTS = "identity_profile_requirements"; + + // advanced identity profile only + public static final String LABEL = "label"; + public static final String FILTER = "filter"; + public static final String CONFIG = "config"; + public static final String SCHEMES = "schemes"; + public static final String PROFILES = "profiles"; + public static final String DOCUMENTS = "documents"; + public static final String INCLUSION = "inclusion"; + public static final String COUNTRY_CODES = "country_codes"; + public static final String DOCUMENT_TYPES = "document_types"; + public static final String ADVANCED_IDENTITY_PROFILE_REQUIREMENTS = "advanced_identity_profile_requirements"; + + } + + } + +} diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/identity/policy/PolicyTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/identity/policy/PolicyTest.java index 035128b46..18526602f 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/identity/policy/PolicyTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/identity/policy/PolicyTest.java @@ -15,7 +15,6 @@ import static com.yoti.api.attributes.AttributeConstants.HumanProfileAttributes.POSTAL_ADDRESS; import static com.yoti.api.attributes.AttributeConstants.HumanProfileAttributes.SELFIE; import static com.yoti.api.attributes.AttributeConstants.HumanProfileAttributes.STRUCTURED_POSTAL_ADDRESS; -import static com.yoti.api.client.spi.remote.call.YotiConstants.DEFAULT_CHARSET; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; @@ -24,6 +23,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; @@ -32,8 +32,10 @@ import com.yoti.api.client.common.IdentityProfile; import com.yoti.api.client.common.IdentityProfileScheme; +import com.yoti.api.client.common.Share; import com.yoti.api.client.identity.constraint.Constraint; import com.yoti.api.client.identity.constraint.SourceConstraint; +import com.yoti.api.client.shareurl.policy.DynamicPolicy; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -371,55 +373,102 @@ public void buildWithIdentityProfile() throws IOException { IdentityProfile identityProfile = new IdentityProfile("A_FRAMEWORK", scheme); - JsonNode json = toJson(identityProfile); + JsonNode json = parse(Policy.builder() + .withIdentityProfile(identityProfile) + .build() + ).get(Share.Policy.Profile.IDENTITY_PROFILE_REQUIREMENTS); - assertThat(json.get(Property.TRUST_FRAMEWORK).asText(), is(equalTo(identityProfile.getFramework()))); + assertThat(json.get(Share.Policy.Profile.TRUST_FRAMEWORK).asText(), is(equalTo(identityProfile.getFramework()))); - JsonNode schemeJsonNode = json.get(Property.SCHEME); - assertThat(schemeJsonNode.get(Property.TYPE).asText(), is(equalTo(scheme.getType()))); - assertThat(schemeJsonNode.get(Property.OBJECTIVE).asText(), is(equalTo(scheme.getObjective()))); + JsonNode schemeJsonNode = json.get(Share.Policy.Profile.SCHEME); + assertThat(schemeJsonNode.get(Share.Policy.Profile.TYPE).asText(), is(equalTo(scheme.getType()))); + assertThat(schemeJsonNode.get(Share.Policy.Profile.OBJECTIVE).asText(), is(equalTo(scheme.getObjective()))); } @Test public void buildWithIdentityProfileMap() throws IOException { Map scheme = new HashMap<>(); - scheme.put(Property.TYPE, "A_TYPE"); - scheme.put(Property.OBJECTIVE, "AN_OBJECTIVE"); + scheme.put(Share.Policy.Profile.TYPE, "A_TYPE"); + scheme.put(Share.Policy.Profile.OBJECTIVE, "AN_OBJECTIVE"); Map identityProfile = new HashMap<>(); - identityProfile.put(Property.TRUST_FRAMEWORK, "A_FRAMEWORK"); - identityProfile.put(Property.SCHEME, scheme); + identityProfile.put(Share.Policy.Profile.TRUST_FRAMEWORK, "A_FRAMEWORK"); + identityProfile.put(Share.Policy.Profile.SCHEME, scheme); - JsonNode json = toJson(identityProfile); + JsonNode json = parse(Policy.builder() + .withIdentityProfile(identityProfile) + .build() + ).get(Share.Policy.Profile.IDENTITY_PROFILE_REQUIREMENTS); assertThat( - json.get(Property.TRUST_FRAMEWORK).asText(), - is(equalTo(identityProfile.get(Property.TRUST_FRAMEWORK))) + json.get(Share.Policy.Profile.TRUST_FRAMEWORK).asText(), + is(equalTo(identityProfile.get(Share.Policy.Profile.TRUST_FRAMEWORK))) ); - JsonNode schemeJsonNode = json.get(Property.SCHEME); - assertThat(schemeJsonNode.get(Property.TYPE).asText(), is(equalTo(scheme.get(Property.TYPE)))); - assertThat(schemeJsonNode.get(Property.OBJECTIVE).asText(), is(equalTo(scheme.get( - Property.OBJECTIVE)))); + JsonNode schemeJsonNode = json.get(Share.Policy.Profile.SCHEME); + assertThat(schemeJsonNode.get(Share.Policy.Profile.TYPE).asText(), is(equalTo(scheme.get(Share.Policy.Profile.TYPE)))); + assertThat(schemeJsonNode.get(Share.Policy.Profile.OBJECTIVE).asText(), is(equalTo(scheme.get(Share.Policy.Profile.OBJECTIVE)))); } - private static JsonNode toJson(Object obj) throws IOException { - Policy policy = Policy.builder() - .withIdentityProfile(obj) - .build(); + @Test + public void buildWithAdvancedIdentityProfileMap() throws IOException { + Map scheme1 = new HashMap<>(); + scheme1.put(Share.Policy.Profile.TYPE, "A_TYPE_1"); + scheme1.put(Share.Policy.Profile.LABEL, "A_LABEL_1"); + scheme1.put(Share.Policy.Profile.OBJECTIVE, "AN_OBJECTIVE_1"); + + Map scheme2 = new HashMap<>(); + scheme2.put(Share.Policy.Profile.TYPE, "A_TYPE_2"); + scheme2.put(Share.Policy.Profile.LABEL, "A_LABEL_2"); + + Map aProfile = new HashMap<>(); + aProfile.put(Share.Policy.Profile.TRUST_FRAMEWORK, "A_FRAMEWORK_1"); + aProfile.put(Share.Policy.Profile.SCHEMES, toArray(scheme1, scheme2)); + + Map documents = new HashMap<>(); + documents.put(Share.Policy.Profile.COUNTRY_CODES, toArray("GBR")); + documents.put(Share.Policy.Profile.DOCUMENT_TYPES, toArray("PASSPORT", "DRIVING_LICENCE")); + + Map filter = new HashMap<>(); + filter.put(Share.Policy.Profile.TYPE, "DOCUMENT_RESTRICTIONS"); + filter.put(Share.Policy.Profile.INCLUSION, "INCLUDE"); + filter.put(Share.Policy.Profile.DOCUMENTS, toArray(documents)); + + Map config = new HashMap<>(); + config.put(Share.Policy.Profile.FILTER, filter); + + Map anotherProfileScheme = new HashMap<>(); + anotherProfileScheme.put(Share.Policy.Profile.TYPE, "A_TYPE_3"); + anotherProfileScheme.put(Share.Policy.Profile.LABEL, "A_LABEL_3"); + anotherProfileScheme.put(Share.Policy.Profile.OBJECTIVE, "AN_OBJECTIVE_3"); + anotherProfileScheme.put(Share.Policy.Profile.CONFIG, config); + + Map anotherProfile = new HashMap<>(); + anotherProfile.put(Share.Policy.Profile.TRUST_FRAMEWORK, "A_FRAMEWORK_2"); + anotherProfile.put(Share.Policy.Profile.SCHEMES, toArray(anotherProfileScheme)); + + Map advancedIdentityProfile = new HashMap<>(); + advancedIdentityProfile.put(Share.Policy.Profile.PROFILES, toArray(aProfile, anotherProfile)); + + JsonNode advancedIdentityProfileJson = parse( + DynamicPolicy.builder() + .withAdvancedIdentityProfile(advancedIdentityProfile) + .build() + ).get(Share.Policy.Profile.ADVANCED_IDENTITY_PROFILE_REQUIREMENTS); - return MAPPER.readTree(MAPPER.writeValueAsString(policy.getIdentityProfile()).getBytes(DEFAULT_CHARSET)); + assertTrue(advancedIdentityProfileJson.equals(parse(advancedIdentityProfile))); } - private static final class Property { - - private Property() { } + private static List> toArray(Map... items) { + return new ArrayList<>(Arrays.asList(items)); + } - private static final String TYPE = "type"; - private static final String SCHEME = "scheme"; - private static final String OBJECTIVE = "objective"; - private static final String TRUST_FRAMEWORK = "trust_framework"; + private static List toArray(String... items) { + return new ArrayList<>(Arrays.asList(items)); + } + private static JsonNode parse(Object obj) throws IOException { + return MAPPER.readTree(MAPPER.writeValueAsString(obj)); } private static class WantedAttributeMatcher extends TypeSafeDiagnosingMatcher { diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/shareurl/policy/DynamicPolicyTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/shareurl/policy/DynamicPolicyTest.java index eeeb99d78..b5813bc4a 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/shareurl/policy/DynamicPolicyTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/shareurl/policy/DynamicPolicyTest.java @@ -15,7 +15,6 @@ import static com.yoti.api.attributes.AttributeConstants.HumanProfileAttributes.POSTAL_ADDRESS; import static com.yoti.api.attributes.AttributeConstants.HumanProfileAttributes.SELFIE; import static com.yoti.api.attributes.AttributeConstants.HumanProfileAttributes.STRUCTURED_POSTAL_ADDRESS; -import static com.yoti.api.client.spi.remote.call.YotiConstants.DEFAULT_CHARSET; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.*; @@ -23,11 +22,15 @@ import static org.junit.Assert.assertTrue; import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import com.yoti.api.client.common.IdentityProfile; import com.yoti.api.client.common.IdentityProfileScheme; +import com.yoti.api.client.common.Share; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; @@ -295,54 +298,104 @@ public void buildWithIdentityProfile() throws IOException { IdentityProfile identityProfile = new IdentityProfile("A_FRAMEWORK", scheme); - JsonNode json = toDynamicPolicyJson(identityProfile); + JsonNode identityProfileJson = parse( + DynamicPolicy.builder() + .withIdentityProfile(identityProfile) + .build() + ).get(Share.Policy.Profile.IDENTITY_PROFILE_REQUIREMENTS); - assertThat(json.get(Property.TRUST_FRAMEWORK).asText(), is(equalTo(identityProfile.getFramework()))); + assertThat(identityProfileJson.get(Share.Policy.Profile.TRUST_FRAMEWORK).asText(), is(equalTo(identityProfile.getFramework()))); - JsonNode schemeJsonNode = json.get(Property.SCHEME); - assertThat(schemeJsonNode.get(Property.TYPE).asText(), is(equalTo(scheme.getType()))); - assertThat(schemeJsonNode.get(Property.OBJECTIVE).asText(), is(equalTo(scheme.getObjective()))); + JsonNode schemeJsonNode = identityProfileJson.get(Share.Policy.Profile.SCHEME); + assertThat(schemeJsonNode.get(Share.Policy.Profile.TYPE).asText(), is(equalTo(scheme.getType()))); + assertThat(schemeJsonNode.get(Share.Policy.Profile.OBJECTIVE).asText(), is(equalTo(scheme.getObjective()))); } @Test public void buildWithIdentityProfileMap() throws IOException { Map scheme = new HashMap<>(); - scheme.put(Property.TYPE, "A_TYPE"); - scheme.put(Property.OBJECTIVE, "AN_OBJECTIVE"); + scheme.put(Share.Policy.Profile.TYPE, "A_TYPE"); + scheme.put(Share.Policy.Profile.OBJECTIVE, "AN_OBJECTIVE"); Map identityProfile = new HashMap<>(); - identityProfile.put(Property.TRUST_FRAMEWORK, "A_FRAMEWORK"); - identityProfile.put(Property.SCHEME, scheme); + identityProfile.put(Share.Policy.Profile.TRUST_FRAMEWORK, "A_FRAMEWORK"); + identityProfile.put(Share.Policy.Profile.SCHEME, scheme); - JsonNode json = toDynamicPolicyJson(identityProfile); + JsonNode identityProfileJson = parse( + DynamicPolicy.builder() + .withIdentityProfile(identityProfile) + .build() + ).get(Share.Policy.Profile.IDENTITY_PROFILE_REQUIREMENTS); assertThat( - json.get(Property.TRUST_FRAMEWORK).asText(), - is(equalTo(identityProfile.get(Property.TRUST_FRAMEWORK))) + identityProfileJson.get(Share.Policy.Profile.TRUST_FRAMEWORK).asText(), + is(equalTo(identityProfile.get(Share.Policy.Profile.TRUST_FRAMEWORK))) ); - JsonNode schemeJsonNode = json.get(Property.SCHEME); - assertThat(schemeJsonNode.get(Property.TYPE).asText(), is(equalTo(scheme.get(Property.TYPE)))); - assertThat(schemeJsonNode.get(Property.OBJECTIVE).asText(), is(equalTo(scheme.get(Property.OBJECTIVE)))); + JsonNode schemeJsonNode = identityProfileJson.get(Share.Policy.Profile.SCHEME); + assertThat(schemeJsonNode.get(Share.Policy.Profile.TYPE).asText(), is(equalTo(scheme.get(Share.Policy.Profile.TYPE)))); + assertThat(schemeJsonNode.get(Share.Policy.Profile.OBJECTIVE).asText(), is(equalTo(scheme.get(Share.Policy.Profile.OBJECTIVE)))); } - private static JsonNode toDynamicPolicyJson(Object obj) throws IOException { - DynamicPolicy policy = DynamicPolicy.builder() - .withIdentityProfile(obj) - .build(); - - return MAPPER.readTree(MAPPER.writeValueAsString(policy.getIdentityProfile()).getBytes(DEFAULT_CHARSET)); + @Test + public void buildWithAdvancedIdentityProfileMap() throws IOException { + Map scheme1 = new HashMap<>(); + scheme1.put(Share.Policy.Profile.TYPE, "A_TYPE_1"); + scheme1.put(Share.Policy.Profile.LABEL, "A_LABEL_1"); + scheme1.put(Share.Policy.Profile.OBJECTIVE, "AN_OBJECTIVE_1"); + + Map scheme2 = new HashMap<>(); + scheme2.put(Share.Policy.Profile.TYPE, "A_TYPE_2"); + scheme2.put(Share.Policy.Profile.LABEL, "A_LABEL_2"); + + Map aProfile = new HashMap<>(); + aProfile.put(Share.Policy.Profile.TRUST_FRAMEWORK, "A_FRAMEWORK_1"); + aProfile.put(Share.Policy.Profile.SCHEMES, toArray(scheme1, scheme2)); + + Map documents = new HashMap<>(); + documents.put(Share.Policy.Profile.COUNTRY_CODES, toArray("GBR")); + documents.put(Share.Policy.Profile.DOCUMENT_TYPES, toArray("PASSPORT", "DRIVING_LICENCE")); + + Map filter = new HashMap<>(); + filter.put(Share.Policy.Profile.TYPE, "DOCUMENT_RESTRICTIONS"); + filter.put(Share.Policy.Profile.INCLUSION, "INCLUDE"); + filter.put(Share.Policy.Profile.DOCUMENTS, toArray(documents)); + + Map config = new HashMap<>(); + config.put(Share.Policy.Profile.FILTER, filter); + + Map anotherProfileScheme = new HashMap<>(); + anotherProfileScheme.put(Share.Policy.Profile.TYPE, "A_TYPE_3"); + anotherProfileScheme.put(Share.Policy.Profile.LABEL, "A_LABEL_3"); + anotherProfileScheme.put(Share.Policy.Profile.OBJECTIVE, "AN_OBJECTIVE_3"); + anotherProfileScheme.put(Share.Policy.Profile.CONFIG, config); + + Map anotherProfile = new HashMap<>(); + anotherProfile.put(Share.Policy.Profile.TRUST_FRAMEWORK, "A_FRAMEWORK_2"); + anotherProfile.put(Share.Policy.Profile.SCHEMES, toArray(anotherProfileScheme)); + + Map advancedIdentityProfile = new HashMap<>(); + advancedIdentityProfile.put(Share.Policy.Profile.PROFILES, toArray(aProfile, anotherProfile)); + + JsonNode advancedIdentityProfileJson = parse( + DynamicPolicy.builder() + .withAdvancedIdentityProfile(advancedIdentityProfile) + .build() + ).get(Share.Policy.Profile.ADVANCED_IDENTITY_PROFILE_REQUIREMENTS); + + assertTrue(advancedIdentityProfileJson.equals(parse(advancedIdentityProfile))); } - private static final class Property { - - private Property() { } + private static List> toArray(Map... items) { + return new ArrayList<>(Arrays.asList(items)); + } - private static final String TYPE = "type"; - private static final String SCHEME = "scheme"; - private static final String OBJECTIVE = "objective"; - private static final String TRUST_FRAMEWORK = "trust_framework"; + private static List toArray(String... items) { + return new ArrayList<>(Arrays.asList(items)); + } + private static JsonNode parse(Object obj) throws IOException { + return MAPPER.readTree(MAPPER.writeValueAsString(obj)); } private static class WantedAttributeMatcher extends TypeSafeDiagnosingMatcher { diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/shareurl/policy/WantedAttributeTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/shareurl/policy/WantedAttributeTest.java index 9eae70114..a537d56de 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/shareurl/policy/WantedAttributeTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/shareurl/policy/WantedAttributeTest.java @@ -1,20 +1,23 @@ package com.yoti.api.client.shareurl.policy; import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.hasSize; +import static org.hamcrest.Matchers.*; import static org.hamcrest.core.StringContains.containsString; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; +import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import com.yoti.api.client.shareurl.constraint.Constraint; -import org.junit.Test; +import org.junit.*; import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.*; +import org.mockito.junit.*; @RunWith(MockitoJUnitRunner.class) public class WantedAttributeTest { @@ -22,8 +25,7 @@ public class WantedAttributeTest { public static final String SOME_NAME = "someName"; public static final String SOME_DERIVATION = "someDerivation"; - @Mock - List constraintListMock; + @Mock Constraint constraintMock; @Test public void buildsAnAttribute() { @@ -31,31 +33,107 @@ public void buildsAnAttribute() { .withName(SOME_NAME) .withDerivation(SOME_DERIVATION) .withOptional(true) + .withAcceptSelfAsserted(true) .build(); assertEquals(SOME_NAME, result.getName()); assertEquals(SOME_DERIVATION, result.getDerivation()); - assertEquals(true, result.isOptional()); + assertTrue(result.isOptional()); + assertTrue(result.getAcceptSelfAsserted()); } @Test - public void buildsAnAttributeWithSourceConstraint() { - when(constraintListMock.size()).thenReturn(1); + public void buildsAnAttributeWithSourceConstraints() { + List constraints = new ArrayList<>(); + constraints.add(constraintMock); WantedAttribute result = WantedAttribute.builder() .withName(SOME_NAME) - .withDerivation(SOME_DERIVATION) - .withOptional(true) - .withConstraints(constraintListMock) - .withAcceptSelfAsserted(true) + .withConstraints(constraints) + .build(); + + assertEquals(SOME_NAME, result.getName()); + assertThat(result.getConstraints(), hasSize(1)); + assertTrue(result.getConstraints().contains(constraintMock)); + } + + @Test + public void buildsAnAttributeWithSourceConstraint() { + WantedAttribute result = WantedAttribute.builder() + .withName(SOME_NAME) + .withConstraint(constraintMock) .build(); assertEquals(SOME_NAME, result.getName()); - assertEquals(SOME_DERIVATION, result.getDerivation()); - assertEquals(true, result.isOptional()); - assertEquals(true, result.getAcceptSelfAsserted()); assertThat(result.getConstraints(), hasSize(1)); - assertEquals(result.getConstraints(), constraintListMock); + assertTrue(result.getConstraints().contains(constraintMock)); + } + + @Test + public void buildsAnAttributeWithSingleAndMultipleSourceConstraint() { + List constraints = new ArrayList<>(); + constraints.add(constraintMock); + + Constraint extraConstraintMock = mock(Constraint.class); + + WantedAttribute result = WantedAttribute.builder() + .withName(SOME_NAME) + .withConstraints(constraints) + .withConstraint(extraConstraintMock) + .build(); + + assertEquals(SOME_NAME, result.getName()); + assertThat(result.getConstraints(), hasSize(2)); + assertTrue(result.getConstraints().contains(constraintMock)); + assertTrue(result.getConstraints().contains(extraConstraintMock)); + } + + @Test + public void buildsAnAttributeWithAlternativeNames() { + String anAlternativeName = "anAlternativeName"; + HashSet alternativeNames = new HashSet<>(); + alternativeNames.add(anAlternativeName); + + WantedAttribute result = WantedAttribute.builder() + .withName(SOME_NAME) + .withAlternativeNames(alternativeNames) + .build(); + + assertEquals(SOME_NAME, result.getName()); + assertThat(result.getAlternativeNames(), hasSize(1)); + assertTrue(result.getAlternativeNames().contains(anAlternativeName)); + } + + @Test + public void buildsAnAttributeWithAlternativeName() { + String anAlternativeName = "anAlternativeName"; + WantedAttribute result = WantedAttribute.builder() + .withName(SOME_NAME) + .withAlternativeName(anAlternativeName) + .build(); + + assertEquals(SOME_NAME, result.getName()); + assertThat(result.getAlternativeNames(), hasSize(1)); + assertTrue(result.getAlternativeNames().contains(anAlternativeName)); + } + + @Test + public void buildsAnAttributeWithSingleAndMultipleAlternativeNames() { + String anAlternativeName = "anAlternativeName"; + String anExtraAlternativeName = "anExtraAlternativeName"; + HashSet alternativeNames = new HashSet<>(); + alternativeNames.add(anAlternativeName); + + WantedAttribute result = WantedAttribute.builder() + .withName(SOME_NAME) + .withAlternativeNames(alternativeNames) + .withAlternativeName(anExtraAlternativeName) + .build(); + + assertEquals(SOME_NAME, result.getName()); + assertThat(result.getAlternativeNames(), hasSize(2)); + assertTrue(result.getAlternativeNames().contains(anAlternativeName)); + assertTrue(result.getAlternativeNames().contains(anExtraAlternativeName)); } @Test diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/ActivityDetailsFactoryTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/ActivityDetailsFactoryTest.java index 662a8b8df..ee664d49a 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/ActivityDetailsFactoryTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/ActivityDetailsFactoryTest.java @@ -14,9 +14,8 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.when; +import static org.mockito.ArgumentMatchers.*; +import static org.mockito.Mockito.*; import java.security.GeneralSecurityException; import java.security.Key; @@ -31,17 +30,14 @@ import com.yoti.api.client.ActivityDetails; import com.yoti.api.client.ExtraData; -import com.yoti.api.client.Profile; import com.yoti.api.client.ProfileException; import com.yoti.api.client.spi.remote.call.Receipt; import com.yoti.api.client.spi.remote.util.CryptoUtil; -import org.junit.Before; -import org.junit.Test; +import org.junit.*; import org.junit.runner.RunWith; -import org.mockito.InjectMocks; -import org.mockito.Mock; -import org.mockito.junit.MockitoJUnitRunner; +import org.mockito.*; +import org.mockito.junit.*; @RunWith(MockitoJUnitRunner.class) public class ActivityDetailsFactoryTest { @@ -68,8 +64,6 @@ public class ActivityDetailsFactoryTest { KeyPair keyPair; byte[] validReceiptKey; - @Mock Profile profileMock; - @Mock Profile otherProfileMock; @Mock ExtraData extraDataMock; @Before @@ -235,4 +229,4 @@ public void shouldReThrowProfileExceptionFromExtraDataConverter() throws Excepti fail("Expected an exception"); } -} \ No newline at end of file +} diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/ReceiptFetcherTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/ReceiptFetcherTest.java index c5353461d..5ee4bc815 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/ReceiptFetcherTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/ReceiptFetcherTest.java @@ -18,6 +18,8 @@ import java.security.KeyPair; import java.security.PublicKey; import java.util.Base64; +import java.util.HashMap; +import java.util.Map; import com.yoti.api.client.ActivityFailureException; import com.yoti.api.client.ProfileException; @@ -27,6 +29,7 @@ import com.yoti.api.client.spi.remote.call.Receipt; import com.yoti.api.client.spi.remote.util.CryptoUtil; +import com.fasterxml.jackson.databind.ObjectMapper; import org.junit.*; import org.junit.runner.RunWith; import org.mockito.*; @@ -40,6 +43,8 @@ public class ReceiptFetcherTest { private static final String ENCODED_RECEIPT_STRING = "base64EncodedReceipt"; private static final byte[] DECODED_RECEIPT_BYTES = decode(ENCODED_RECEIPT_STRING); + private static final ObjectMapper MAPPER = new ObjectMapper(); + @InjectMocks ReceiptFetcher testObj; @Mock ProfileService profileService; @@ -189,6 +194,47 @@ public void shouldFailForFailureReceiptWithNoErrorCode() throws Exception { fail("Expected an Exception"); } + @Test + public void shouldFailForFailureReceiptWithErrorReason() throws Exception { + Receipt receipt = new Receipt.Builder() + .withReceiptId(DECODED_RECEIPT_BYTES) + .withOutcome(Receipt.Outcome.FAILURE) + .build(); + + String errorCode = "anErrorCode"; + + Map errorReason = new HashMap<>(); + errorReason.put("aReasonKey", "aReasonValue"); + + ErrorDetails error = ErrorDetails.builder() + .code(errorCode) + .reason(errorReason) + .build(); + + ProfileResponse profileResponse = new ProfileResponse.ProfileResponseBuilder() + .setReceipt(receipt) + .setError(error) + .build(); + when(profileService.getProfile(keyPair, APP_ID, TOKEN)).thenReturn(profileResponse); + + try { + testObj.fetch(encryptedToken, keyPair, APP_ID); + } catch (ActivityFailureException ex) { + String exMsg = ex.getMessage(); + assertThat(exMsg, containsString(ENCODED_RECEIPT_STRING)); + assertThat(exMsg, containsString(errorCode)); + assertThat(exMsg, containsString("aReasonValue")); + + ErrorDetails exError = ex.errorDetails(); + assertThat(exError.getCode(), is(equalTo(errorCode))); + assertThat(exError.getReason(), is(equalTo(MAPPER.writeValueAsString(errorReason)))); + + return; + } + + fail("Expected an Exception"); + } + @Test public void shouldReturnSuccessReceipt() throws Exception { Receipt receipt = new Receipt.Builder() diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ErrorDetailsTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ErrorDetailsTest.java index 73f84de5b..a7647dfbe 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ErrorDetailsTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ErrorDetailsTest.java @@ -17,7 +17,7 @@ public class ErrorDetailsTest { private static final String ERROR_DESCRIPTION = "AnErrorDescription"; @Test - public void shouldParseFromJson() { + public void shouldParseFromJson_WithErrorDescription() { Map map = new HashMap<>(); map.put(Property.ERROR_CODE, ERROR_CODE); map.put(Property.DESCRIPTION, ERROR_DESCRIPTION); @@ -29,10 +29,27 @@ public void shouldParseFromJson() { assertThat(errorDetails.getDescription(), equalTo(ERROR_DESCRIPTION)); } + @Test + public void shouldParseFromJson_WithErrorReason() throws Exception { + Map reason = new HashMap<>(); + reason.put("aReasonKey", "aReasonValue"); + + Map map = new HashMap<>(); + map.put(Property.ERROR_CODE, ERROR_CODE); + map.put(Property.ERROR_REASON, reason); + + ErrorDetails errorDetails = OBJECT_MAPPER.convertValue(map, ErrorDetails.class); + + assertThat(errorDetails, notNullValue()); + assertThat(errorDetails.getCode(), equalTo(ERROR_CODE)); + assertThat(errorDetails.getReason(), equalTo(OBJECT_MAPPER.writeValueAsString(reason))); + } + private static final class Property { private static final String ERROR_CODE = "error_code"; private static final String DESCRIPTION = "description"; + private static final String ERROR_REASON = "error_reason"; private Property() { } diff --git a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ProfileResponseTest.java b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ProfileResponseTest.java index 513adbfe9..f65c3c1e8 100644 --- a/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ProfileResponseTest.java +++ b/yoti-sdk-api/src/test/java/com/yoti/api/client/spi/remote/call/ProfileResponseTest.java @@ -133,6 +133,27 @@ public void failureReceipt_shouldParseFromJson() { assertThat(error.getDescription(), equalTo(errorDescription)); } + @Test + public void failureReceipt_shouldParseErrorReasonFromJson() throws Exception { + String errorCode = "anErrorCode"; + + Map reason = new HashMap<>(); + reason.put("aReasonKey", "aReasonValue"); + + HashMap errorJson = new HashMap<>(); + errorJson.put(Property.ERROR_CODE, errorCode); + errorJson.put(Property.ERROR_REASON, reason); + + HashMap json = new HashMap<>(); + json.put(Property.ERROR_DETAILS, errorJson); + + ProfileResponse obj = OBJECT_MAPPER.convertValue(json, ProfileResponse.class); + + ErrorDetails error = obj.getError(); + assertThat(error.getCode(), equalTo(errorCode)); + assertThat(error.getReason(), equalTo(OBJECT_MAPPER.writeValueAsString(reason))); + } + private static Receipt createReceipt() { return new Receipt.Builder() .withProfile(VALID_CONTENT) @@ -167,6 +188,7 @@ private static class Property { private static final String ERROR_DETAILS = "error_details"; private static final String ERROR_CODE = "error_code"; private static final String ERROR_DESCRIPTION = "description"; + private static final String ERROR_REASON = "error_reason"; } diff --git a/yoti-sdk-parent/pom.xml b/yoti-sdk-parent/pom.xml index ac6bf9cc1..1728a6b82 100644 --- a/yoti-sdk-parent/pom.xml +++ b/yoti-sdk-parent/pom.xml @@ -5,7 +5,7 @@ com.yoti yoti-sdk-parent pom - 3.8.0 + 3.9.0 Yoti SDK Parent Pom Parent pom for the Java SDK projects https://github.com/getyoti/yoti-java-sdk @@ -100,13 +100,13 @@ 2.0.9 1.70 - 2.15.2 - 3.24.4 + 2.16.1 + 3.25.3 4.5.14 - 2.7.16 + 2.7.18 4.0.1 @@ -116,36 +116,38 @@ 3.13.0 + 3.8.5 + 3.11.0 - 4.7.3 - 4.7.3.4 - 1.12.0 + 4.8.3 + 4.8.3.1 + 1.13.0 - 8.4.0 + 8.4.3 12 1.23 java18 1.0 - 3.3.0 + 3.4.1 1.7.0 1.6.13 - 3.2.1 + 3.3.0 - 3.5.0 + 3.6.3 8 3.1.0 - 3.4.3 + 3.5.0 4.3.0 - 0.8.10 + 0.8.11 @@ -236,7 +238,6 @@ - org.apache.maven.plugins maven-compiler-plugin ${maven-compiler-plugin.version} @@ -318,7 +319,6 @@
- org.apache.maven.plugins maven-enforcer-plugin ${maven-enforcer-plugin.version} @@ -345,6 +345,9 @@ + + ${maven.min.version} + @@ -371,7 +374,6 @@ - org.apache.maven.plugins maven-source-plugin ${maven-source-plugin.version} @@ -385,7 +387,6 @@ - org.apache.maven.plugins maven-javadoc-plugin ${maven-javadoc-plugin.version} @@ -402,7 +403,6 @@ - org.apache.maven.plugins maven-gpg-plugin ${maven-gpg-plugin.version} @@ -417,7 +417,6 @@ - org.apache.maven.plugins maven-project-info-reports-plugin ${maven-project-info-reports-plugin.version} @@ -453,9 +452,13 @@ - org.apache.maven.plugins maven-gpg-plugin + + + maven-enforcer-plugin + + org.sonatype.plugins nexus-staging-maven-plugin diff --git a/yoti-sdk-sandbox/pom.xml b/yoti-sdk-sandbox/pom.xml index ac841ebb8..8d3831c2f 100644 --- a/yoti-sdk-sandbox/pom.xml +++ b/yoti-sdk-sandbox/pom.xml @@ -11,7 +11,7 @@ com.yoti yoti-sdk-parent - 3.8.0 + 3.9.0 ../yoti-sdk-parent @@ -68,7 +68,6 @@ animal-sniffer-maven-plugin - org.apache.maven.plugins maven-enforcer-plugin @@ -76,11 +75,9 @@ ${maven-compiler-plugin.version} - org.apache.maven.plugins maven-source-plugin - org.apache.maven.plugins maven-javadoc-plugin @@ -93,7 +90,6 @@ - org.apache.maven.plugins maven-project-info-reports-plugin diff --git a/yoti-sdk-spring-boot-auto-config/README.md b/yoti-sdk-spring-boot-auto-config/README.md index 9e8e2e16e..3b2c5c561 100644 --- a/yoti-sdk-spring-boot-auto-config/README.md +++ b/yoti-sdk-spring-boot-auto-config/README.md @@ -18,7 +18,7 @@ If you are using Maven, you need to add the following dependencies: com.yoti yoti-sdk-spring-boot-auto-config - 3.8.0 + 3.9.0 ``` @@ -26,7 +26,7 @@ If you are using Maven, you need to add the following dependencies: If you are using Gradle, here is the dependency to add: ``` -compile group: 'com.yoti', name: 'yoti-sdk-spring-boot-auto-config', version: '3.8.0' +compile group: 'com.yoti', name: 'yoti-sdk-spring-boot-auto-config', version: '3.9.0' ``` diff --git a/yoti-sdk-spring-boot-auto-config/pom.xml b/yoti-sdk-spring-boot-auto-config/pom.xml index 49b8800c5..a11b7a451 100644 --- a/yoti-sdk-spring-boot-auto-config/pom.xml +++ b/yoti-sdk-spring-boot-auto-config/pom.xml @@ -12,7 +12,7 @@ com.yoti yoti-sdk-parent - 3.8.0 + 3.9.0 ../yoti-sdk-parent @@ -52,11 +52,9 @@ - org.apache.maven.plugins maven-source-plugin - org.apache.maven.plugins maven-javadoc-plugin @@ -68,7 +66,6 @@ animal-sniffer-maven-plugin - org.apache.maven.plugins maven-enforcer-plugin diff --git a/yoti-sdk-spring-boot-example/README.md b/yoti-sdk-spring-boot-example/README.md index 90b78ceb9..0a7b046d5 100644 --- a/yoti-sdk-spring-boot-example/README.md +++ b/yoti-sdk-spring-boot-example/README.md @@ -17,7 +17,7 @@ Note that: com.yoti yoti-sdk-api - 3.8.0 + 3.9.0 ``` @@ -36,6 +36,7 @@ Note that: * [https://localhost:8443](https://localhost:8443) to initiate a login using Yoti. The Spring demo is listening for the response on `https://localhost:8443/login` * [https://localhost:8443/dynamic-share](https://localhost:8443/dynamic-share) to initiate a dynamic share with location with result displayed in profile page. * [https://localhost:8443/dbs-check](https://localhost:8443/dbs-check) to initiate a BDS standard check with location with result displayed in profile page. + * [https://localhost:8443/advanced-identity-profile-check](https://localhost:8443/advanced-identity-profile-check) to initiate a multi scheme identity profile check (**UK_TFIDA**[DBS, RTW], **YOTI_GLOBAL**[IDENTITY]) with result displayed in profile page. The logic for all the v1 share examples can be found in the `YotiLoginController` diff --git a/yoti-sdk-spring-boot-example/pom.xml b/yoti-sdk-spring-boot-example/pom.xml index ad19a98f8..b3f6c1962 100644 --- a/yoti-sdk-spring-boot-example/pom.xml +++ b/yoti-sdk-spring-boot-example/pom.xml @@ -6,12 +6,12 @@ com.yoti yoti-sdk-spring-boot-example Yoti Spring Boot Example - 3.8.0 + 3.9.0 org.springframework.boot spring-boot-starter-parent - 2.7.16 + 2.7.18 @@ -43,8 +43,14 @@ 1.8 8 - 32.1.1-jre - 4.7.3.4 + 3.8.5 + + 33.0.0-jre + + 4.8.3.1 + 3.4.1 + 1.7.0 + 3.11.0 @@ -97,20 +103,65 @@ - org.apache.maven.plugins maven-compiler-plugin ${maven-compiler-plugin.version} + + + maven-enforcer-plugin + ${maven-enforcer-plugin.version} + + + enforce-bytecode-version + + enforce + + verify + + + + ${supported.java.version} + + + true + + + + enforce-dependency-versions + + enforce + + + + + + ${maven.min.version} + + + + + + + + org.codehaus.mojo + extra-enforcer-rules + ${extra-enforcer-rules.version} + + + + + maven-enforcer-plugin + + org.springframework.boot spring-boot-maven-plugin - org.apache.maven.plugins maven-deploy-plugin true diff --git a/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/IdentityLoginController.java b/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/IdentityLoginController.java index 68438b53a..7df4b7cc7 100644 --- a/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/IdentityLoginController.java +++ b/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/IdentityLoginController.java @@ -71,22 +71,31 @@ public String identityShare(Model model) { public String receipt(@RequestParam("receiptId") String receiptId, Model model) { Receipt receipt = execute(() -> client.fetchShareReceipt(receiptId), model); - if (receipt == null || receipt.getError().isPresent()) { - model.addAttribute("error", receipt.getError().get()); - return "error"; - } - - Receipt.ApplicationContent applicationContent = receipt.getApplicationContent(); + return Optional.ofNullable(receipt) + .map(r -> r.getError() + .map(error -> { + model.addAttribute("error", error); + r.getErrorReason().ifPresent(reason -> + model.addAttribute("errorReason", reason) + ); + return "error"; + }) + .orElseGet(() -> setProfile(receipt, model)) + ) + .orElse("error"); + } - Optional.ofNullable(applicationContent.getProfile()) + private String setProfile(Receipt receipt, Model model) { + Optional.ofNullable(receipt.getApplicationContent().getProfile()) .map(ApplicationProfile::getApplicationLogo) .map(attr -> model.addAttribute("appLogo", attr.getValue().getBase64Content())); - receipt.getProfile().map(HumanProfile::getSelfie) + Optional profile = receipt.getProfile(); + profile.map(HumanProfile::getSelfie) .map(attr -> model.addAttribute("base64Selfie", attr.getValue().getBase64Content())); - receipt.getProfile().map(HumanProfile::getFullName) + profile.map(HumanProfile::getFullName) .map(attr -> model.addAttribute("fullName", attr.getValue())); - receipt.getProfile().map(HumanProfile::getAttributes) + profile.map(HumanProfile::getAttributes) .map(attr -> model.addAttribute("displayAttributes", mapAttributes(attr))); return "profile"; diff --git a/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/IdentitySessionController.java b/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/IdentitySessionController.java index e037e4840..0f596ccdd 100644 --- a/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/IdentitySessionController.java +++ b/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/IdentitySessionController.java @@ -1,7 +1,10 @@ package com.yoti.api.examples.springboot; import java.net.URI; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; import com.yoti.api.client.DigitalIdentityClient; @@ -12,6 +15,8 @@ import com.yoti.api.client.identity.extension.LocationConstraintExtensionBuilder; import com.yoti.api.client.identity.policy.Policy; import com.yoti.api.client.identity.policy.WantedAttribute; +import com.yoti.api.client.shareurl.policy.DynamicPolicy; +import com.yoti.api.examples.springboot.data.Share; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; @@ -36,9 +41,10 @@ public IdentitySessionController(DigitalIdentityClient client) { @GetMapping("/digital-identity-session") public String identityShareSession() { ShareSession session = client.createShareSession( - // forMinimalShare() - forDynamicScenarioShare() + forMinimalShare() + // forDynamicScenarioShare() // forIdentityProfileShare() + // forAdvancedIdentityProfileShare() // forLocationExtensionShare() ); @@ -107,6 +113,69 @@ private static ShareSessionRequest forIdentityProfileShare() { .build(); } + private static ShareSessionRequest forAdvancedIdentityProfileShare() { + // UK_TFIDA + Map dbsScheme = new HashMap<>(); + dbsScheme.put(Share.Policy.Profile.TYPE, "DBS"); + dbsScheme.put(Share.Policy.Profile.LABEL, "LB000"); + dbsScheme.put(Share.Policy.Profile.OBJECTIVE, "BASIC"); + + Map rtwScheme = new HashMap<>(); + rtwScheme.put(Share.Policy.Profile.TYPE, "RTW"); + rtwScheme.put(Share.Policy.Profile.LABEL, "LB001"); + + Map ukTfidaProfile = new HashMap<>(); + ukTfidaProfile.put(Share.Policy.Profile.TRUST_FRAMEWORK, "UK_TFIDA"); + ukTfidaProfile.put(Share.Policy.Profile.SCHEMES, toArray(dbsScheme, rtwScheme)); + + // YOTI_GLOBAL + Map documents = new HashMap<>(); + documents.put(Share.Policy.Profile.COUNTRY_CODES, toArray("GBR")); + documents.put(Share.Policy.Profile.DOCUMENT_TYPES, toArray("PASSPORT", "DRIVING_LICENCE")); + + Map filter = new HashMap<>(); + filter.put(Share.Policy.Profile.TYPE, "DOCUMENT_RESTRICTIONS"); + filter.put(Share.Policy.Profile.INCLUSION, "INCLUDE"); + filter.put(Share.Policy.Profile.DOCUMENTS, toArray(documents)); + + Map config = new HashMap<>(); + config.put(Share.Policy.Profile.FILTER, filter); + + Map identityScheme = new HashMap<>(); + identityScheme.put(Share.Policy.Profile.TYPE, "IDENTITY"); + identityScheme.put(Share.Policy.Profile.LABEL, "LB002"); + identityScheme.put(Share.Policy.Profile.OBJECTIVE, "AL_L1"); + identityScheme.put(Share.Policy.Profile.CONFIG, config); + + Map yotiGlobalProfile = new HashMap<>(); + yotiGlobalProfile.put(Share.Policy.Profile.TRUST_FRAMEWORK, "YOTI_GLOBAL"); + yotiGlobalProfile.put(Share.Policy.Profile.SCHEMES, toArray(identityScheme)); + + Map advancedIdentityProfile = new HashMap<>(); + advancedIdentityProfile.put(Share.Policy.Profile.PROFILES, toArray(ukTfidaProfile, yotiGlobalProfile)); + + Map subject = new HashMap<>(); + subject.put(Share.Subject.SUBJECT_ID, "00000000-1111-2222-3333-444444444444"); + + Policy policy = Policy.builder() + .withAdvancedIdentityProfile(advancedIdentityProfile) + .build(); + + return ShareSessionRequest.builder() + .withPolicy(policy) + .withSubject(subject) + .withRedirectUri(REDIRECT_URI) + .build(); + } + + private static List> toArray(Map... items) { + return new ArrayList<>(Arrays.asList(items)); + } + + private static List toArray(String... items) { + return new ArrayList<>(Arrays.asList(items)); + } + private static ShareSessionRequest forLocationExtensionShare() { Extension locationExtension = new LocationConstraintExtensionBuilder() .withLatitude(51.5074) diff --git a/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/YotiLoginController.java b/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/YotiLoginController.java index 124bef78f..64d8ac63f 100644 --- a/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/YotiLoginController.java +++ b/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/YotiLoginController.java @@ -1,5 +1,7 @@ package com.yoti.api.examples.springboot; +import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -22,6 +24,7 @@ import com.yoti.api.client.shareurl.policy.WantedAttribute; import com.yoti.api.examples.springboot.attribute.AttributeMapper; import com.yoti.api.examples.springboot.attribute.DisplayAttribute; +import com.yoti.api.examples.springboot.data.Share; import com.yoti.api.spring.ClientProperties; import com.yoti.api.spring.YotiProperties; @@ -159,19 +162,19 @@ public String doLogin(@RequestParam("token") final String token, final Model mod @RequestMapping("/dbs-check") public String dbsCheck(final Model model) { Map scheme = new HashMap<>(); - scheme.put("type", "DBS"); - scheme.put("objective", "BASIC"); + scheme.put(Share.Policy.Profile.TYPE, "DBS"); + scheme.put(Share.Policy.Profile.OBJECTIVE, "BASIC"); Map identityProfile = new HashMap<>(); - identityProfile.put("trust_framework", "UK_TFIDA"); - identityProfile.put("scheme", scheme); + identityProfile.put(Share.Policy.Profile.TRUST_FRAMEWORK, "UK_TFIDA"); + identityProfile.put(Share.Policy.Profile.SCHEME, scheme); DynamicPolicy dynamicPolicy = DynamicPolicy.builder() .withIdentityProfile(identityProfile) .build(); Map subject = new HashMap<>(); - subject.put("subject_id", "00000000-1111-2222-3333-444444444444"); + subject.put(Share.Subject.SUBJECT_ID, "00000000-1111-2222-3333-444444444444"); DynamicScenario dynamicScenario = DynamicScenario.builder() .withCallbackEndpoint("/login") @@ -193,4 +196,81 @@ public String dbsCheck(final Model model) { return "dbs-check"; } + @RequestMapping("/advanced-identity-profile-check") + public String advancedDbsCheck(final Model model) { + // UK_TFIDA + Map dbsScheme = new HashMap<>(); + dbsScheme.put(Share.Policy.Profile.TYPE, "DBS"); + dbsScheme.put(Share.Policy.Profile.LABEL, "LB000"); + dbsScheme.put(Share.Policy.Profile.OBJECTIVE, "BASIC"); + + Map rtwScheme = new HashMap<>(); + rtwScheme.put(Share.Policy.Profile.TYPE, "RTW"); + rtwScheme.put(Share.Policy.Profile.LABEL, "LB001"); + + Map ukTfidaProfile = new HashMap<>(); + ukTfidaProfile.put(Share.Policy.Profile.TRUST_FRAMEWORK, "UK_TFIDA"); + ukTfidaProfile.put(Share.Policy.Profile.SCHEMES, toArray(dbsScheme, rtwScheme)); + + // YOTI_GLOBAL + Map documents = new HashMap<>(); + documents.put(Share.Policy.Profile.COUNTRY_CODES, toArray("GBR")); + documents.put(Share.Policy.Profile.DOCUMENT_TYPES, toArray("PASSPORT", "DRIVING_LICENCE")); + + Map filter = new HashMap<>(); + filter.put(Share.Policy.Profile.TYPE, "DOCUMENT_RESTRICTIONS"); + filter.put(Share.Policy.Profile.INCLUSION, "INCLUDE"); + filter.put(Share.Policy.Profile.DOCUMENTS, toArray(documents)); + + Map config = new HashMap<>(); + config.put(Share.Policy.Profile.FILTER, filter); + + Map identityScheme = new HashMap<>(); + identityScheme.put(Share.Policy.Profile.TYPE, "IDENTITY"); + identityScheme.put(Share.Policy.Profile.LABEL, "LB002"); + identityScheme.put(Share.Policy.Profile.OBJECTIVE, "AL_L1"); + identityScheme.put(Share.Policy.Profile.CONFIG, config); + + Map yotiGlobalProfile = new HashMap<>(); + yotiGlobalProfile.put(Share.Policy.Profile.TRUST_FRAMEWORK, "YOTI_GLOBAL"); + yotiGlobalProfile.put(Share.Policy.Profile.SCHEMES, toArray(identityScheme)); + + Map advancedIdentityProfile = new HashMap<>(); + advancedIdentityProfile.put(Share.Policy.Profile.PROFILES, toArray(ukTfidaProfile, yotiGlobalProfile)); + + DynamicPolicy dynamicPolicy = DynamicPolicy.builder() + .withAdvancedIdentityProfile(advancedIdentityProfile) + .build(); + + Map subject = new HashMap<>(); + subject.put(Share.Subject.SUBJECT_ID, "00000000-1111-2222-3333-444444444444"); + + DynamicScenario dynamicScenario = DynamicScenario.builder() + .withCallbackEndpoint("/login") + .withPolicy(dynamicPolicy) + .withSubject(subject) + .build(); + + try { + ShareUrlResult result = client.createShareUrl(dynamicScenario); + + String shareUrl = result.getUrl(); + model.addAttribute("yotiShareUrl", shareUrl); + } catch (DynamicShareException e) { + LOG.error(e.getMessage()); + } + + model.addAttribute("clientSdkId", properties.getClientSdkId()); + + return "dbs-check"; + } + + private static List> toArray(Map... items) { + return new ArrayList<>(Arrays.asList(items)); + } + + private static List toArray(String... items) { + return new ArrayList<>(Arrays.asList(items)); + } + } diff --git a/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/data/Share.java b/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/data/Share.java new file mode 100644 index 000000000..84f7fc199 --- /dev/null +++ b/yoti-sdk-spring-boot-example/src/main/java/com/yoti/api/examples/springboot/data/Share.java @@ -0,0 +1,39 @@ +package com.yoti.api.examples.springboot.data; + +public final class Share { + + public static final class Subject { + + public static final String SUBJECT_ID = "subject_id"; + + } + + public static final class Policy { + + public static final class Profile { + + private Profile() { } + + public static final String TYPE = "type"; + public static final String OBJECTIVE = "objective"; + public static final String TRUST_FRAMEWORK = "trust_framework"; + + // identity profile only + public static final String SCHEME = "scheme"; + + // advanced identity profile only + public static final String LABEL = "label"; + public static final String FILTER = "filter"; + public static final String CONFIG = "config"; + public static final String SCHEMES = "schemes"; + public static final String PROFILES = "profiles"; + public static final String DOCUMENTS = "documents"; + public static final String INCLUSION = "inclusion"; + public static final String COUNTRY_CODES = "country_codes"; + public static final String DOCUMENT_TYPES = "document_types"; + + } + + } + +} diff --git a/yoti-sdk-spring-boot-example/src/main/resources/templates/error.html b/yoti-sdk-spring-boot-example/src/main/resources/templates/error.html index eed82bc96..168507d46 100644 --- a/yoti-sdk-spring-boot-example/src/main/resources/templates/error.html +++ b/yoti-sdk-spring-boot-example/src/main/resources/templates/error.html @@ -18,10 +18,19 @@

Home

Oops, something went wrong.

-

Error:

+

Error:

+ +
+

Reason:

+

+      
+ + diff --git a/yoti-sdk-spring-security/README.md b/yoti-sdk-spring-security/README.md index 01dc188f5..d3bb0513b 100644 --- a/yoti-sdk-spring-security/README.md +++ b/yoti-sdk-spring-security/README.md @@ -25,14 +25,14 @@ If you are using Maven, you need to add the following dependencies: com.yoti yoti-sdk-spring-security - 3.8.0 + 3.9.0 ``` If you are using Gradle, here is the dependency to add: ``` -compile group: 'com.yoti', name: 'yoti-sdk-spring-security', version: '3.8.0' +compile group: 'com.yoti', name: 'yoti-sdk-spring-security', version: '3.9.0' ``` ### Provide a `YotiClient` instance diff --git a/yoti-sdk-spring-security/pom.xml b/yoti-sdk-spring-security/pom.xml index df5776864..42a631616 100644 --- a/yoti-sdk-spring-security/pom.xml +++ b/yoti-sdk-spring-security/pom.xml @@ -12,7 +12,7 @@ com.yoti yoti-sdk-parent - 3.8.0 + 3.9.0 ../yoti-sdk-parent @@ -63,11 +63,9 @@ - org.apache.maven.plugins maven-source-plugin - org.apache.maven.plugins maven-javadoc-plugin @@ -79,7 +77,6 @@ animal-sniffer-maven-plugin - org.apache.maven.plugins maven-enforcer-plugin