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 43a4668f..59cca450 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 @@ -33,16 +33,16 @@ 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() { @@ -94,6 +94,15 @@ public Object getIdentityProfile() { return identityProfile; } + /** + * Defines a required advanced identity profile. + * + * @return AdvancedIdentityProfile + */ + public Object getAdvancedIdentityProfile() { + return advancedIdentityProfile; + } + public static class Builder { private static final int SELFIE_AUTH_TYPE = 1; @@ -104,6 +113,7 @@ public static class Builder { private boolean wantedRememberMe; private boolean wantedRememberMeOptional; private Object identityProfile; + private Object advancedIdentityProfile; private Builder() { } @@ -114,7 +124,7 @@ public Builder withWantedAttribute(WantedAttribute wantedAttribute) { key += "-" + wantedAttribute.getConstraints().hashCode(); } - this.wantedAttributes.put(key, wantedAttribute); + wantedAttributes.put(key, wantedAttribute); return this; } @@ -245,11 +255,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 +269,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 +290,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 +309,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/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 eeeb99d7..7c19fa6f 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,7 +22,10 @@ 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; @@ -295,11 +297,15 @@ 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(Property.IDENTITY_PROFILE_REQUIREMENTS); - assertThat(json.get(Property.TRUST_FRAMEWORK).asText(), is(equalTo(identityProfile.getFramework()))); + assertThat(identityProfileJson.get(Property.TRUST_FRAMEWORK).asText(), is(equalTo(identityProfile.getFramework()))); - JsonNode schemeJsonNode = json.get(Property.SCHEME); + JsonNode schemeJsonNode = identityProfileJson.get(Property.SCHEME); assertThat(schemeJsonNode.get(Property.TYPE).asText(), is(equalTo(scheme.getType()))); assertThat(schemeJsonNode.get(Property.OBJECTIVE).asText(), is(equalTo(scheme.getObjective()))); } @@ -314,24 +320,81 @@ public void buildWithIdentityProfileMap() throws IOException { identityProfile.put(Property.TRUST_FRAMEWORK, "A_FRAMEWORK"); identityProfile.put(Property.SCHEME, scheme); - JsonNode json = toDynamicPolicyJson(identityProfile); + JsonNode identityProfileJson = parse( + DynamicPolicy.builder() + .withIdentityProfile(identityProfile) + .build() + ).get(Property.IDENTITY_PROFILE_REQUIREMENTS); assertThat( - json.get(Property.TRUST_FRAMEWORK).asText(), + identityProfileJson.get(Property.TRUST_FRAMEWORK).asText(), is(equalTo(identityProfile.get(Property.TRUST_FRAMEWORK))) ); - JsonNode schemeJsonNode = json.get(Property.SCHEME); + JsonNode schemeJsonNode = identityProfileJson.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)))); } - private static JsonNode toDynamicPolicyJson(Object obj) throws IOException { - DynamicPolicy policy = DynamicPolicy.builder() - .withIdentityProfile(obj) - .build(); + @Test + public void buildWithAdvancedIdentityProfileMap() throws IOException { + Map scheme1 = new HashMap<>(); + scheme1.put(Property.TYPE, "A_TYPE_1"); + scheme1.put(Property.LABEL, "A_LABEL_1"); + scheme1.put(Property.OBJECTIVE, "AN_OBJECTIVE_1"); + + Map scheme2 = new HashMap<>(); + scheme2.put(Property.TYPE, "A_TYPE_2"); + scheme2.put(Property.LABEL, "A_LABEL_2"); + + Map aProfile = new HashMap<>(); + aProfile.put(Property.TRUST_FRAMEWORK, "A_FRAMEWORK_1"); + aProfile.put(Property.SCHEMES, toArray(scheme1, scheme2)); + + Map documents = new HashMap<>(); + documents.put(Property.COUNTRY_CODES, toArray("GBR")); + documents.put(Property.DOCUMENT_TYPES, toArray("PASSPORT", "DRIVING_LICENCE")); + + Map filter = new HashMap<>(); + filter.put(Property.TYPE, "DOCUMENT_RESTRICTIONS"); + filter.put(Property.INCLUSION, "INCLUDE"); + filter.put(Property.DOCUMENTS, toArray(documents)); + + Map config = new HashMap<>(); + config.put(Property.FILTER, filter); + + Map anotherProfileScheme = new HashMap<>(); + anotherProfileScheme.put(Property.TYPE, "A_TYPE_3"); + anotherProfileScheme.put(Property.LABEL, "A_LABEL_3"); + anotherProfileScheme.put(Property.OBJECTIVE, "AN_OBJECTIVE_3"); + anotherProfileScheme.put(Property.CONFIG, config); + + Map anotherProfile = new HashMap<>(); + anotherProfile.put(Property.TRUST_FRAMEWORK, "A_FRAMEWORK_2"); + anotherProfile.put(Property.SCHEMES, toArray(anotherProfileScheme)); + + Map advancedIdentityProfile = new HashMap<>(); + advancedIdentityProfile.put(Property.PROFILES, toArray(aProfile, anotherProfile)); + + JsonNode advancedIdentityProfileJson = parse( + DynamicPolicy.builder() + .withAdvancedIdentityProfile(advancedIdentityProfile) + .build() + ).get(Property.ADVANCED_IDENTITY_PROFILE_REQUIREMENTS); + + assertTrue(advancedIdentityProfileJson.equals(parse(advancedIdentityProfile))); + } + + private static List> toArray(Map... items) { + return new ArrayList<>(Arrays.asList(items)); + } - return MAPPER.readTree(MAPPER.writeValueAsString(policy.getIdentityProfile()).getBytes(DEFAULT_CHARSET)); + 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 final class Property { @@ -339,10 +402,25 @@ private static final class Property { private Property() { } 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"; + // identity profile only + private static final String SCHEME = "scheme"; + private static final String IDENTITY_PROFILE_REQUIREMENTS = "identity_profile_requirements"; + + // advanced identity profile only + private static final String LABEL = "label"; + private static final String FILTER = "filter"; + private static final String CONFIG = "config"; + private static final String SCHEMES = "schemes"; + private static final String PROFILES = "profiles"; + private static final String DOCUMENTS = "documents"; + private static final String INCLUSION = "inclusion"; + private static final String COUNTRY_CODES = "country_codes"; + private static final String DOCUMENT_TYPES = "document_types"; + private static final String ADVANCED_IDENTITY_PROFILE_REQUIREMENTS = "advanced_identity_profile_requirements"; + } private static class WantedAttributeMatcher extends TypeSafeDiagnosingMatcher { 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 124bef78..b1577270 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; @@ -193,4 +195,81 @@ public String dbsCheck(final Model model) { return "dbs-check"; } + @RequestMapping("/advanced-dbs-check") + public String advancedDbsCheck(final Model model) { + // UK_TFIDA + Map dbsScheme = new HashMap<>(); + dbsScheme.put("type", "DBS"); + dbsScheme.put("label", "LB000"); + dbsScheme.put("objective", "BASIC"); + + Map rtwScheme = new HashMap<>(); + rtwScheme.put("type", "RTW"); + rtwScheme.put("label", "LB001"); + + Map ukTfidaProfile = new HashMap<>(); + ukTfidaProfile.put("trust_framework", "UK_TFIDA"); + ukTfidaProfile.put("schemes", toArray(dbsScheme, rtwScheme)); + + // YOTI_GLOBAL + Map documents = new HashMap<>(); + documents.put("country_codes", toArray("GBR")); + documents.put("document_types", toArray("PASSPORT", "DRIVING_LICENCE")); + + Map filter = new HashMap<>(); + filter.put("type", "DOCUMENT_RESTRICTIONS"); + filter.put("inclusion", "INCLUDE"); + filter.put("documents", toArray(documents)); + + Map config = new HashMap<>(); + config.put("filter", filter); + + Map identityScheme = new HashMap<>(); + identityScheme.put("type", "IDENTITY"); + identityScheme.put("label", "LB002"); + identityScheme.put("objective", "AL_L1"); + identityScheme.put("config", config); + + Map yotiGlobalProfile = new HashMap<>(); + yotiGlobalProfile.put("trust_framework", "YOTI_GLOBAL"); + yotiGlobalProfile.put("schemes", toArray(identityScheme)); + + Map advancedIdentityProfile = new HashMap<>(); + advancedIdentityProfile.put("profiles", toArray(ukTfidaProfile, yotiGlobalProfile)); + + DynamicPolicy dynamicPolicy = DynamicPolicy.builder() + .withAdvancedIdentityProfile(advancedIdentityProfile) + .build(); + + Map subject = new HashMap<>(); + subject.put("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)); + } + }