Skip to content

Commit

Permalink
Merge pull request #10 from ase-101/develop
Browse files Browse the repository at this point in the history
ES-842 ES-1127
  • Loading branch information
ckm007 authored Jul 9, 2024
2 parents 16b4609 + 2bf59ae commit 5789d7c
Show file tree
Hide file tree
Showing 9 changed files with 114 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import org.springframework.stereotype.Component;


@ConditionalOnProperty(value = "signup.integration.profile-registry-plugin", havingValue = "MockProfileRegistry")
@ConditionalOnProperty(value = "mosip.signup.integration.profile-registry-plugin", havingValue = "MockProfileRegistryPluginImpl")
@Slf4j
@Component
public class MockProfileRegistryPluginImpl implements ProfileRegistryPlugin {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,8 @@
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Base64;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
Expand Down Expand Up @@ -282,4 +281,19 @@ protected static String generateHash(String value) {
return value;
}

//Converts an array of two-letter language codes to their corresponding ISO 639-2/T language codes.
protected List<String> convertLangCodesToISO3LanguageCodes(String[] langCodes) {
if(langCodes == null || langCodes.length == 0)
return List.of();
return Arrays.stream(langCodes)
.map(langCode -> {
try {
return new Locale(langCode).getISO3Language();
} catch (MissingResourceException ex) {}
return null;
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
*/
package io.esignet.plugin.mosipid.service;

import java.util.Arrays;
import java.util.List;
import java.util.*;

import io.mosip.esignet.api.dto.*;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -164,7 +163,7 @@ public KycExchangeResult doKycExchange(String relyingPartyId, String clientId, K
} else {
idaKycExchangeRequest.setConsentObtained(List.of("sub"));
}
idaKycExchangeRequest.setLocales(Arrays.asList(kycExchangeDto.getClaimsLocales()));
idaKycExchangeRequest.setLocales(helperService.convertLangCodesToISO3LanguageCodes(kycExchangeDto.getClaimsLocales()));
idaKycExchangeRequest.setRespType(kycExchangeDto.getUserInfoResponseType()); //may be either JWT or JWE
idaKycExchangeRequest.setIndividualId(kycExchangeDto.getIndividualId());

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,9 +148,10 @@ public KeyBindingResult doKeyBinding(String individualId, List<AuthChallenge> ch
ErrorConstants.KEY_BINDING_FAILED : responseWrapper.getErrors().get(0).getErrorCode());
}

log.debug("Binding-Auth-status : {}", responseWrapper.getResponse().isBindingAuthStatus());
if(!responseWrapper.getResponse().isBindingAuthStatus()) {
log.error("Binding-Auth-status : {}", responseWrapper.getResponse().isBindingAuthStatus());
throw new KeyBindingException(ErrorConstants.BINDING_AUTH_FAILED);
throw new KeyBindingException(CollectionUtils.isEmpty(responseWrapper.getErrors()) ?
ErrorConstants.BINDING_AUTH_FAILED : responseWrapper.getErrors().get(0).getErrorCode());
}

KeyBindingResult keyBindingResult = new KeyBindingResult();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.stream.Collectors;

import javax.crypto.Cipher;

Expand Down Expand Up @@ -117,7 +116,7 @@ public VCResult<JsonLDObject> getVerifiableCredentialWithLinkedDataProof(VCReque
idaVciExchangeRequest.setIndividualId(individualId);
idaVciExchangeRequest.setCredSubjectId(holderId);
idaVciExchangeRequest.setVcFormat(vcRequestDto.getFormat());
idaVciExchangeRequest.setLocales(convertLangCodesToISO3LanguageCodes(transaction.getClaimsLocales()));
idaVciExchangeRequest.setLocales(helperService.convertLangCodesToISO3LanguageCodes(transaction.getClaimsLocales()));
vciCred.setCredentialSubject(vcRequestDto.getCredentialSubject());
vciCred.setType(vcRequestDto.getType());
vciCred.setContext(vcRequestDto.getContext());
Expand Down Expand Up @@ -200,19 +199,4 @@ private String getKeyAlias(String keyAppId, String keyRefId) throws Exception {
private byte[] b64Decode(String value) {
return urlSafeDecoder.decode(value);
};

//Converts an array of two-letter language codes to their corresponding ISO 639-2/T language codes.
private List<String> convertLangCodesToISO3LanguageCodes(String[] langCodes) {
if(langCodes == null || langCodes.length == 0)
return List.of("eng");
return Arrays.stream(langCodes)
.map(langCode -> {
try {
return new Locale(langCode).getISO3Language();
} catch (MissingResourceException ex) {}
return null;
})
.filter(Objects::nonNull)
.collect(Collectors.toList());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.signup.plugin.mosipid.dto;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;

import java.util.List;

@JsonIgnoreProperties(ignoreUnknown = true)
@Data
public class SchemaFieldValidator {

private String type;
private String validator;
private List<String> arguments;
private String langCode;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package io.signup.plugin.mosipid.dto;

import lombok.Data;

@Data
public class SimpleType {

private String value;
private String language;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.node.TextNode;
import io.micrometer.core.annotation.Timed;
Expand All @@ -26,6 +25,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
Expand All @@ -48,6 +48,7 @@

@Slf4j
@Component
@ConditionalOnProperty(value = "mosip.signup.integration.profile-registry-plugin", havingValue = "MOSIPProfileRegistryPluginImpl")
public class IdrepoProfileRegistryPluginImpl implements ProfileRegistryPlugin {

private static final String ID_SCHEMA_VERSION_FIELD_ID = "IDSchemaVersion";
Expand Down Expand Up @@ -108,43 +109,6 @@ public class IdrepoProfileRegistryPluginImpl implements ProfileRegistryPlugin {
@Autowired
private ProfileCacheService profileCacheService;

private void checkRegexValidator(JsonNode validator, JsonNode valueNode) {
String value = valueNode.get("value").textValue();
if (validator.get("type").textValue().equals("regex") &&
!value.matches(validator.get("validator").textValue())) {
log.error("Regex of {} does not match value of {}", validator.get("validator").textValue(), value);
throw new InvalidProfileException(ErrorConstants.INVALID_INPUT);
}
}

private void validateEntryFields(Iterator<Map.Entry<String, JsonNode>> itr, JsonNode fields) {
while (itr.hasNext()) {
Map.Entry<String, JsonNode> entry = itr.next();
log.info("TODO - Need to validate field {} >> {}", entry.getKey(), entry.getValue());
JsonNode validateField = fields.get(entry.getKey());

if (validateField == null) {
log.error("Null value found in key field {}", entry.getKey());
throw new InvalidProfileException(ErrorConstants.INVALID_INPUT);
}

JsonNode validators = validateField.get("validators");
if (validators == null) continue;

JsonNode validator = validators.get(0);
if (entry.getValue().getClass().equals(TextNode.class)) {
checkRegexValidator(validator, entry.getValue());
} else if (entry.getValue().getClass().equals(ArrayNode.class)) {
for (JsonNode valueNode: entry.getValue()) {
JsonNode language = valueNode.get("language");
JsonNode langCode = validator.get("langCode");
if ((language == null) || (langCode != null && language.textValue().equals(langCode.textValue()))) {
checkRegexValidator(validator, valueNode);
}
}
}
}
}

@Override
public void validate(String action, ProfileDto profileDto) throws InvalidProfileException {
Expand All @@ -160,10 +124,11 @@ public void validate(String action, ProfileDto profileDto) throws InvalidProfile
// check if any required field is missing during the "create" action.
JsonNode requiredFieldIds = schemaResponse.getParsedSchemaJson().at("/properties/identity/required");
if (action.equals("CREATE")) {
for (JsonNode requiredFieldId : requiredFieldIds) {
if (inputJson.get(requiredFieldId.textValue()) == null) {
log.error("Null value found in the required field of {}", requiredFieldId);
throw new InvalidProfileException(ErrorConstants.INVALID_INPUT);
Iterator itr = requiredFieldIds.iterator();
while (itr.hasNext()) {
if (inputJson.get((String)itr.next()) == null) {
log.error("Null value found in the required field of {}", requiredFieldIds);
throw new InvalidProfileException(ErrorConstants.INVALID_INPUT); //TODO we should add exception message
}
}
}
Expand Down Expand Up @@ -428,4 +393,60 @@ private String getUTCDateTime() {
.now(ZoneOffset.UTC)
.format(DateTimeFormatter.ofPattern(UTC_DATETIME_PATTERN));
}

private void validateValue(String keyName, SchemaFieldValidator validator, String value) {
if(value == null || value.isEmpty())
throw new InvalidProfileException(ErrorConstants.INVALID_INPUT);

if( validator != null && "regex".equalsIgnoreCase(validator.getType()) && !value.matches(validator.getValidator()) ) {
log.error("Regex of {} does not match value of {}", validator.getValidator(), value);
throw new InvalidProfileException("invalid_".concat(keyName.toLowerCase()));
}
}

private void validateEntryFields(Iterator<Map.Entry<String, JsonNode>> input, JsonNode schemaFields) {
while (input.hasNext()) {
Map.Entry<String, JsonNode> entry = input.next();
log.debug("validate field {} --> {}", entry.getKey(), entry.getValue());
JsonNode schemaField = schemaFields.get(entry.getKey());

if (schemaField == null) {
log.error("No field found in the schema with this field name : {}", entry.getKey());
throw new InvalidProfileException(ErrorConstants.UNKNOWN_FIELD);
}

if(!schemaField.hasNonNull("validators"))
continue;

SchemaFieldValidator[] validators = objectMapper.convertValue(schemaField.get("validators"), SchemaFieldValidator[].class);
if(validators == null || validators.length == 0) continue;

String datatype = schemaField.get("type") == null ? schemaField.get("$ref").textValue() : schemaField.get("type").textValue();
switch (datatype) {
case "string" :
validateValue(entry.getKey(), validators[0], entry.getValue().textValue());
break;
case "#/definitions/simpleType":
SimpleType[] values = objectMapper.convertValue(entry.getValue(), SimpleType[].class);
Optional<SimpleType> mandatoryLangValue = Arrays.stream(values).filter( v -> mandatoryLanguages.contains(v.getLanguage())).findFirst();
if(mandatoryLangValue.isEmpty())
throw new InvalidProfileException(MANDATORY_LANGUAGE_MISSING);

for(SimpleType value : values) {
validateLanguage(value.getLanguage());
Optional<SchemaFieldValidator> result = Arrays.stream(validators)
.filter(v-> value.getLanguage().equals(v.getLangCode()) || v.getLangCode() == null).findFirst();
result.ifPresent(schemaFieldValidator -> validateValue(entry.getKey(), schemaFieldValidator, value.getValue()));
}
break;
default:
log.error("Unhandled datatype found : {}", datatype);
}
}
}

private void validateLanguage(String language) {
if(!mandatoryLanguages.contains(language) && (optionalLanguages != null && !optionalLanguages.contains(language)))
throw new InvalidProfileException("invalid_language");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ public class ErrorConstants {
public static final String UNKNOWN_FIELD = "unknown_field";
public static final String MISSING_FIELD = "missing_field";
public static final String DATATYPE_MISMATCH = "datatype_mismatch";
public static final String MANDATORY_LANGUAGE_MISSING = "mandatory_language_missing";

}

0 comments on commit 5789d7c

Please sign in to comment.