From d1a4c8bd013d7ee9fb2eca9ff43eaae171d8cf64 Mon Sep 17 00:00:00 2001 From: Mohd Kaif Siddique Date: Thu, 4 Jan 2024 13:21:35 +0530 Subject: [PATCH 1/4] added sunbirdrcVciIssuancePlugin Signed-off-by: Mohd Kaif Siddique --- .../service/MockVCIssuancePlugin.java | 36 --- .../service/SunbirdRCVCIssuancePlugin.java | 260 ++++++++++++++++++ 2 files changed, 260 insertions(+), 36 deletions(-) delete mode 100644 sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/MockVCIssuancePlugin.java create mode 100644 sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java diff --git a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/MockVCIssuancePlugin.java b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/MockVCIssuancePlugin.java deleted file mode 100644 index 7cdab70..0000000 --- a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/MockVCIssuancePlugin.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - */ -package io.mosip.esignet.sunbirdrc.integration.service; - - -import java.util.Map; -import io.mosip.esignet.api.exception.VCIExchangeException; -import io.mosip.esignet.api.util.ErrorConstants; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.stereotype.Component; -import foundation.identity.jsonld.JsonLDObject; -import io.mosip.esignet.api.dto.VCRequestDto; -import io.mosip.esignet.api.dto.VCResult; -import io.mosip.esignet.api.spi.VCIssuancePlugin; -import lombok.extern.slf4j.Slf4j; - - -@ConditionalOnProperty(value = "mosip.esignet.integration.vci-plugin", havingValue = "SunbirdRCVCIssuancePlugin") -@Component -@Slf4j -public class MockVCIssuancePlugin implements VCIssuancePlugin { - - - @Override - public VCResult getVerifiableCredentialWithLinkedDataProof(VCRequestDto vcRequestDto, String holderId, Map identityDetails) throws VCIExchangeException { - throw new VCIExchangeException(ErrorConstants.NOT_IMPLEMENTED); - } - - @Override - public VCResult getVerifiableCredential(VCRequestDto vcRequestDto, String holderId, Map identityDetails) throws VCIExchangeException { - throw new VCIExchangeException(ErrorConstants.NOT_IMPLEMENTED); - } -} diff --git a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java new file mode 100644 index 0000000..4a85c38 --- /dev/null +++ b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java @@ -0,0 +1,260 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + */ +package io.mosip.esignet.sunbirdrc.integration.service; + + +import java.io.StringWriter; +import java.util.*; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import io.mosip.esignet.api.exception.VCIExchangeException; +import io.mosip.esignet.api.util.ErrorConstants; +import io.mosip.kernel.signature.service.SignatureService; +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.runtime.RuntimeConstants; +import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; +import org.json.JSONArray; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.core.ParameterizedTypeReference; +import org.springframework.core.env.Environment; +import org.springframework.http.MediaType; +import org.springframework.http.RequestEntity; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Component; +import foundation.identity.jsonld.JsonLDObject; +import io.mosip.esignet.api.dto.VCRequestDto; +import io.mosip.esignet.api.dto.VCResult; +import io.mosip.esignet.api.spi.VCIssuancePlugin; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +import javax.annotation.PostConstruct; + + +@ConditionalOnProperty(value = "mosip.esignet.integration.vci-plugin", havingValue = "SunbirdRCVCIssuancePlugin") +@Component +@Slf4j +public class SunbirdRCVCIssuancePlugin implements VCIssuancePlugin { + + public static final String PROPERTY_CONSTANT="mosip.esignet.vciplugin.sunbird-rc.credential-type"; + + public static final String FORMAT="ldp_vc"; + + public static final String TEMPLATE_URL = "template-url"; + + public static final String REGISTRY_GET_URL = "registry-get-url"; + + public static final String CRED_SCHEMA_ID = "cred-schema-id"; + + public static final String CRED_SCHEMA_VESRION = "cred-schema-version"; + + public static final String STATIC_VALUE_MAP_ISSUER_ID = "static-value-map.issuerId"; + + @Autowired + Environment env; + + @Autowired + ObjectMapper mapper; + + @Autowired + private RestTemplate restTemplate; + + @Value("${mosip.esignet.vciplugin.sunbird-rc.issue-credential-url}") + String issueCredentialUri; + + @Value("${mosip.esignet.vciplugin.sunbird-rc.supported-credential-types}") + String supportedCredentialTypes; + + @Value("${mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.registry-get-url}") + String registryUrl; + + + + private final Map credentialTypeTemplates = new HashMap<>(); + + private final Map> credentialTypeConfigMap = new HashMap<>(); + + private VelocityEngine vEngine; + + + @PostConstruct + public void validateProperties() throws VCIExchangeException { + + vEngine = new VelocityEngine(); + vEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); + vEngine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); + vEngine.init(); + //Validate all the supported VC + String[] credentialTypes = supportedCredentialTypes.split(","); + for (String credentialType : credentialTypes) { + validatePropertyForCredentialType(credentialType.trim()); + } + } + + @Override + public VCResult getVerifiableCredentialWithLinkedDataProof(VCRequestDto vcRequestDto, String holderId, Map identityDetails) throws VCIExchangeException { + if (vcRequestDto == null || vcRequestDto.getType() == null) { + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); + } + List types = vcRequestDto.getType(); + if (types.isEmpty() || !types.get(0).equals("VerifiableCredential")) { + log.error("Invalid request: first item in type is not VerifiableCredential"); + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); + } + types.remove(0); + String requestedCredentialType = String.join("-", types); + //Check if the key is in the supported-credential-types + List supportedTypes = Arrays.asList(supportedCredentialTypes.split(",")); + if (!supportedTypes.contains(requestedCredentialType)) { + log.error("Credential type is not supported"); + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); + } + //todo validate context of vcrequestdto with template + List contextList=vcRequestDto.getContext(); + for(String supportedType:supportedTypes){ + Template template=credentialTypeTemplates.get(supportedType); + validateContextUrl(template,contextList); + } + String osid=(String)identityDetails.get("sub"); + RequestEntity requestEntity = RequestEntity + .get(UriComponentsBuilder.fromUriString(registryUrl+osid).build().toUri()).build(); + ResponseEntity> responseEntity = restTemplate.exchange(requestEntity, + new ParameterizedTypeReference>() {}); + if (responseEntity.getStatusCode().is2xxSuccessful() && responseEntity.getBody() != null) { + Map responseMap = responseEntity.getBody(); + Map credentialRequestMap = createCredentialIssueRequest(requestedCredentialType,responseMap,vcRequestDto,holderId); + try{ + String requestBody=mapper.writeValueAsString(credentialRequestMap); + RequestEntity requestEntity2 = RequestEntity + .post(UriComponentsBuilder.fromUriString(issueCredentialUri).build().toUri()) + .contentType(MediaType.APPLICATION_JSON_UTF8) + .body(requestBody); + ResponseEntity> responseEntity2 = restTemplate.exchange(requestEntity2, + new ParameterizedTypeReference>(){}); + if (responseEntity2.getStatusCode().is2xxSuccessful() && responseEntity2.getBody() != null){ + //TODO This need to be removed since it can contain PII + log.debug("getting response {}", responseEntity); + Map vcResponseMap =responseEntity2.getBody(); + //casting it to JsonLD object + VCResult vcResult = new VCResult(); + JsonLDObject vcJsonLdObject = JsonLDObject.fromJsonObject(vcResponseMap); + vcResult.setCredential(vcJsonLdObject); + vcResult.setFormat(FORMAT); + return vcResult; + }else{ + log.error("Sunbird service is not running. Status Code: " ,responseEntity.getStatusCode()); + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); + } + }catch (Exception e){ + log.error("Unable to parse the Registry Object :{}",credentialRequestMap); + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); + } + }else { + log.error("Sunbird service is not running. Status Code: " ,responseEntity.getStatusCode()); + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); + } + } + + @Override + public VCResult getVerifiableCredential(VCRequestDto vcRequestDto, String holderId, Map identityDetails) throws VCIExchangeException { + return null; + } + + private Map createCredentialIssueRequest(String requestedCredentialType,Map responseMap,VCRequestDto vcRequestDto,String holderId) { + + Template template=credentialTypeTemplates.get(requestedCredentialType); + Map configMap=credentialTypeConfigMap.get(requestedCredentialType); + StringWriter wrt = new StringWriter(); + VelocityContext context = new VelocityContext(); + Map requestMap=new HashMap<>(); + + try{ + context.put("issuerId", configMap.get(STATIC_VALUE_MAP_ISSUER_ID)); + context.put("calNowPlus30Days", calculateNowPlus30Days()); + context.put("id",holderId); + for (Map.Entry entry : responseMap.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + if (value instanceof List) { + JSONArray jsonArray = new JSONArray((List) value); + context.put(key, jsonArray); + } else { + context.put(key, value); + } + } + }catch (Exception e){} + template.merge(context, wrt); + try{ + Map tempMap=mapper.readValue(wrt.toString(),Map.class); + requestMap.put("credential",tempMap); + requestMap.put("credentialSchemaId",configMap.get(CRED_SCHEMA_ID)); + requestMap.put("credentialSchemaVersion",configMap.get(CRED_SCHEMA_VESRION)); + requestMap.put("tags",new ArrayList<>()); + }catch (Exception e){ + } + //TODO This need to be removed since it can contain PII + log.info("VC requset is {}",requestMap); + return requestMap; + } + + private void validatePropertyForCredentialType(String credentialType) throws VCIExchangeException { + Map configMap=new HashMap<>(); + validateProperty(PROPERTY_CONSTANT + "." + credentialType + "." + TEMPLATE_URL,TEMPLATE_URL,configMap); + validateProperty(PROPERTY_CONSTANT + "." + credentialType + "." + REGISTRY_GET_URL,REGISTRY_GET_URL,configMap); + validateProperty(PROPERTY_CONSTANT + "." + credentialType + "." + CRED_SCHEMA_ID,CRED_SCHEMA_ID,configMap); + validateProperty(PROPERTY_CONSTANT + "." + credentialType + "." + CRED_SCHEMA_VESRION,CRED_SCHEMA_VESRION,configMap); + validateProperty(PROPERTY_CONSTANT + "." + credentialType + "." + STATIC_VALUE_MAP_ISSUER_ID,STATIC_VALUE_MAP_ISSUER_ID,configMap); + + String templateUrl = env.getProperty(PROPERTY_CONSTANT +"." + credentialType + "." + TEMPLATE_URL); + validateAndCacheTemplate(templateUrl,credentialType); + // cache configuration with their credential type + credentialTypeConfigMap.put(credentialType,configMap); + } + + private void validateProperty(String propertyName,String credentialProp,Map configMap) throws VCIExchangeException { + String propertyValue = env.getProperty(propertyName); + if (propertyValue == null || propertyValue.isEmpty()) { + throw new VCIExchangeException("Property " + propertyName + " is not set Properly."); + } + configMap.put(credentialProp,propertyValue); + } + + private void validateAndCacheTemplate(String templateUrl, String credentialType){ + Template t = vEngine.getTemplate(templateUrl); + //Todo Validate if all the templates are valid JSON-LD documents + credentialTypeTemplates.put(credentialType,t); + } + private void validateContextUrl(Template template,List vcRequestContextList) throws VCIExchangeException { + try{ + StringWriter wrt = new StringWriter(); + template.merge(new VelocityContext(),wrt); + Map tempMap= mapper.readValue(wrt.toString(),Map.class); + List contextList=(List)tempMap.get("@context"); + for(String contextUrl:contextList){ + if(!vcRequestContextList.contains(contextUrl)){ + log.error("ContextUrl is not supported"); + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); + } + } + }catch ( JsonProcessingException e){ + log.error("Error while parsing the templete ",e); + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); + } + } + + private static Date calculateNowPlus30Days() { + // Implement your logic to calculate current date + 30 days + Calendar calendar = Calendar.getInstance(); + calendar.add(Calendar.DAY_OF_MONTH, 30); + return calendar.getTime(); + } +} From 57e93f9cac0501dd24650d2c8753858380efa48e Mon Sep 17 00:00:00 2001 From: Mohd Kaif Siddique Date: Mon, 8 Jan 2024 17:25:44 +0530 Subject: [PATCH 2/4] review changes Signed-off-by: Mohd Kaif Siddique --- .../service/SunbirdRCVCIssuancePlugin.java | 205 +++++++++--------- 1 file changed, 106 insertions(+), 99 deletions(-) diff --git a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java index 4a85c38..6caf0b2 100644 --- a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java +++ b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java @@ -7,18 +7,18 @@ import java.io.StringWriter; +import java.time.LocalDateTime; import java.util.*; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import io.mosip.esignet.api.exception.VCIExchangeException; import io.mosip.esignet.api.util.ErrorConstants; -import io.mosip.kernel.signature.service.SignatureService; import org.apache.velocity.Template; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.RuntimeConstants; -import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; +import org.apache.velocity.runtime.resource.loader.URLResourceLoader; import org.json.JSONArray; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -45,19 +45,19 @@ @Slf4j public class SunbirdRCVCIssuancePlugin implements VCIssuancePlugin { - public static final String PROPERTY_CONSTANT="mosip.esignet.vciplugin.sunbird-rc.credential-type"; + private static final String CREDENTIAL_TYPE_PROPERTY_PREFIX ="mosip.esignet.vciplugin.sunbird-rc.credential-type"; - public static final String FORMAT="ldp_vc"; + private static final String LINKED_DATA_PROOF_VC_FORMAT ="ldp_vc"; - public static final String TEMPLATE_URL = "template-url"; + private static final String TEMPLATE_URL = "template-url"; - public static final String REGISTRY_GET_URL = "registry-get-url"; + private static final String REGISTRY_GET_URL = "registry-get-url"; - public static final String CRED_SCHEMA_ID = "cred-schema-id"; + private static final String CRED_SCHEMA_ID = "cred-schema-id"; - public static final String CRED_SCHEMA_VESRION = "cred-schema-version"; + private static final String CRED_SCHEMA_VESRION = "cred-schema-version"; - public static final String STATIC_VALUE_MAP_ISSUER_ID = "static-value-map.issuerId"; + private static final String STATIC_VALUE_MAP_ISSUER_ID = "static-value-map.issuerId"; @Autowired Environment env; @@ -69,15 +69,10 @@ public class SunbirdRCVCIssuancePlugin implements VCIssuancePlugin { private RestTemplate restTemplate; @Value("${mosip.esignet.vciplugin.sunbird-rc.issue-credential-url}") - String issueCredentialUri; - - @Value("${mosip.esignet.vciplugin.sunbird-rc.supported-credential-types}") - String supportedCredentialTypes; - - @Value("${mosip.esignet.vciplugin.sunbird-rc.credential-type.InsuranceCredential.registry-get-url}") - String registryUrl; - + String issueCredentialUrl; + @Value("#{'${mosip.esignet.vciplugin.sunbird-rc.supported-credential-types}'.split(',')}") + List supportedCredentialTypes; private final Map credentialTypeTemplates = new HashMap<>(); @@ -87,16 +82,15 @@ public class SunbirdRCVCIssuancePlugin implements VCIssuancePlugin { @PostConstruct - public void validateProperties() throws VCIExchangeException { + public void initialize() throws VCIExchangeException { vEngine = new VelocityEngine(); - vEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath"); - vEngine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName()); + vEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "url"); + vEngine.setProperty("url.resource.loader.class", URLResourceLoader.class.getName()); vEngine.init(); //Validate all the supported VC - String[] credentialTypes = supportedCredentialTypes.split(","); - for (String credentialType : credentialTypes) { - validatePropertyForCredentialType(credentialType.trim()); + for (String credentialType : supportedCredentialTypes) { + validateAndCachePropertiesForCredentialType(credentialType.trim()); } } @@ -113,114 +107,126 @@ public VCResult getVerifiableCredentialWithLinkedDataProof(VCReque types.remove(0); String requestedCredentialType = String.join("-", types); //Check if the key is in the supported-credential-types - List supportedTypes = Arrays.asList(supportedCredentialTypes.split(",")); - if (!supportedTypes.contains(requestedCredentialType)) { + if (!supportedCredentialTypes.contains(requestedCredentialType)) { log.error("Credential type is not supported"); throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); } - //todo validate context of vcrequestdto with template + //Validate context of vcrequestdto with template List contextList=vcRequestDto.getContext(); - for(String supportedType:supportedTypes){ + for(String supportedType:supportedCredentialTypes){ Template template=credentialTypeTemplates.get(supportedType); validateContextUrl(template,contextList); } - String osid=(String)identityDetails.get("sub"); + String osid = (identityDetails.containsKey("sub")) ? (String) identityDetails.get("sub") : null; + if (osid == null) { + log.error("Invalid request: osid is null"); + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); + } + String registryUrl=credentialTypeConfigMap.get(requestedCredentialType).get(REGISTRY_GET_URL); + Map responseRegistryMap =fetchRegistryObject(registryUrl+osid); + Map credentialRequestMap = createCredentialIssueRequest(requestedCredentialType, responseRegistryMap,vcRequestDto,holderId); + Map vcResponseMap =sendCredentialIssueRequest(credentialRequestMap); + + VCResult vcResult = new VCResult(); + JsonLDObject vcJsonLdObject = JsonLDObject.fromJsonObject(vcResponseMap); + vcResult.setCredential(vcJsonLdObject); + vcResult.setFormat(LINKED_DATA_PROOF_VC_FORMAT); + return vcResult; + } + + + @Override + public VCResult getVerifiableCredential(VCRequestDto vcRequestDto, String holderId, Map identityDetails) throws VCIExchangeException { + throw new VCIExchangeException(ErrorConstants.NOT_IMPLEMENTED); + } + + private Map fetchRegistryObject(String entityUrl) throws VCIExchangeException { RequestEntity requestEntity = RequestEntity - .get(UriComponentsBuilder.fromUriString(registryUrl+osid).build().toUri()).build(); + .get(UriComponentsBuilder.fromUriString(entityUrl).build().toUri()).build(); ResponseEntity> responseEntity = restTemplate.exchange(requestEntity, new ParameterizedTypeReference>() {}); if (responseEntity.getStatusCode().is2xxSuccessful() && responseEntity.getBody() != null) { - Map responseMap = responseEntity.getBody(); - Map credentialRequestMap = createCredentialIssueRequest(requestedCredentialType,responseMap,vcRequestDto,holderId); - try{ - String requestBody=mapper.writeValueAsString(credentialRequestMap); - RequestEntity requestEntity2 = RequestEntity - .post(UriComponentsBuilder.fromUriString(issueCredentialUri).build().toUri()) - .contentType(MediaType.APPLICATION_JSON_UTF8) - .body(requestBody); - ResponseEntity> responseEntity2 = restTemplate.exchange(requestEntity2, - new ParameterizedTypeReference>(){}); - if (responseEntity2.getStatusCode().is2xxSuccessful() && responseEntity2.getBody() != null){ - //TODO This need to be removed since it can contain PII - log.debug("getting response {}", responseEntity); - Map vcResponseMap =responseEntity2.getBody(); - //casting it to JsonLD object - VCResult vcResult = new VCResult(); - JsonLDObject vcJsonLdObject = JsonLDObject.fromJsonObject(vcResponseMap); - vcResult.setCredential(vcJsonLdObject); - vcResult.setFormat(FORMAT); - return vcResult; - }else{ - log.error("Sunbird service is not running. Status Code: " ,responseEntity.getStatusCode()); - throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); - } - }catch (Exception e){ - log.error("Unable to parse the Registry Object :{}",credentialRequestMap); - throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); - } + return responseEntity.getBody(); }else { log.error("Sunbird service is not running. Status Code: " ,responseEntity.getStatusCode()); throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); } } - @Override - public VCResult getVerifiableCredential(VCRequestDto vcRequestDto, String holderId, Map identityDetails) throws VCIExchangeException { - return null; - } - - private Map createCredentialIssueRequest(String requestedCredentialType,Map responseMap,VCRequestDto vcRequestDto,String holderId) { + private Map createCredentialIssueRequest(String requestedCredentialType, Map registryObjectMap, VCRequestDto vcRequestDto, String holderId) throws VCIExchangeException { Template template=credentialTypeTemplates.get(requestedCredentialType); Map configMap=credentialTypeConfigMap.get(requestedCredentialType); - StringWriter wrt = new StringWriter(); + StringWriter writer = new StringWriter(); VelocityContext context = new VelocityContext(); Map requestMap=new HashMap<>(); - - try{ - context.put("issuerId", configMap.get(STATIC_VALUE_MAP_ISSUER_ID)); - context.put("calNowPlus30Days", calculateNowPlus30Days()); - context.put("id",holderId); - for (Map.Entry entry : responseMap.entrySet()) { - String key = entry.getKey(); - Object value = entry.getValue(); - if (value instanceof List) { - JSONArray jsonArray = new JSONArray((List) value); - context.put(key, jsonArray); - } else { - context.put(key, value); - } + context.put("currentDate", LocalDateTime.now()); + context.put("issuerId", configMap.get(STATIC_VALUE_MAP_ISSUER_ID)); + context.put("id",holderId); + for (Map.Entry entry : registryObjectMap.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + if (value instanceof List) { + JSONArray jsonArray = new JSONArray((List) value); + context.put(key, jsonArray); + } else { + context.put(key, value); } - }catch (Exception e){} - template.merge(context, wrt); + } + template.merge(context, writer); try{ - Map tempMap=mapper.readValue(wrt.toString(),Map.class); - requestMap.put("credential",tempMap); + Map credentialObject =mapper.readValue(writer.toString(),Map.class); + requestMap.put("credential", credentialObject); requestMap.put("credentialSchemaId",configMap.get(CRED_SCHEMA_ID)); requestMap.put("credentialSchemaVersion",configMap.get(CRED_SCHEMA_VESRION)); requestMap.put("tags",new ArrayList<>()); - }catch (Exception e){ + }catch (JsonProcessingException e){ + log.error("Error while parsing the templete ",e); + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); } //TODO This need to be removed since it can contain PII log.info("VC requset is {}",requestMap); return requestMap; } - private void validatePropertyForCredentialType(String credentialType) throws VCIExchangeException { + private Map sendCredentialIssueRequest(Map credentialRequestMap) throws VCIExchangeException { + try{ + String requestBody=mapper.writeValueAsString(credentialRequestMap); + RequestEntity requestEntity = RequestEntity + .post(UriComponentsBuilder.fromUriString(issueCredentialUrl).build().toUri()) + .contentType(MediaType.APPLICATION_JSON_UTF8) + .body(requestBody); + ResponseEntity> responseEntity = restTemplate.exchange(requestEntity, + new ParameterizedTypeReference>(){}); + if (responseEntity.getStatusCode().is2xxSuccessful() && responseEntity.getBody() != null){ + //TODO This need to be removed since it can contain PII + log.debug("getting response {}", responseEntity); + return responseEntity.getBody(); + }else{ + log.error("Sunbird service is not running. Status Code: " , responseEntity.getStatusCode()); + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); + } + }catch (Exception e){ + log.error("Unable to parse the Registry Object :{}",credentialRequestMap); + throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); + } + } + + private void validateAndCachePropertiesForCredentialType(String credentialType) throws VCIExchangeException { Map configMap=new HashMap<>(); - validateProperty(PROPERTY_CONSTANT + "." + credentialType + "." + TEMPLATE_URL,TEMPLATE_URL,configMap); - validateProperty(PROPERTY_CONSTANT + "." + credentialType + "." + REGISTRY_GET_URL,REGISTRY_GET_URL,configMap); - validateProperty(PROPERTY_CONSTANT + "." + credentialType + "." + CRED_SCHEMA_ID,CRED_SCHEMA_ID,configMap); - validateProperty(PROPERTY_CONSTANT + "." + credentialType + "." + CRED_SCHEMA_VESRION,CRED_SCHEMA_VESRION,configMap); - validateProperty(PROPERTY_CONSTANT + "." + credentialType + "." + STATIC_VALUE_MAP_ISSUER_ID,STATIC_VALUE_MAP_ISSUER_ID,configMap); + validateAndLoadProperty(CREDENTIAL_TYPE_PROPERTY_PREFIX + "." + credentialType + "." + TEMPLATE_URL,TEMPLATE_URL,configMap); + validateAndLoadProperty(CREDENTIAL_TYPE_PROPERTY_PREFIX + "." + credentialType + "." + REGISTRY_GET_URL,REGISTRY_GET_URL,configMap); + validateAndLoadProperty(CREDENTIAL_TYPE_PROPERTY_PREFIX + "." + credentialType + "." + CRED_SCHEMA_ID,CRED_SCHEMA_ID,configMap); + validateAndLoadProperty(CREDENTIAL_TYPE_PROPERTY_PREFIX + "." + credentialType + "." + CRED_SCHEMA_VESRION,CRED_SCHEMA_VESRION,configMap); + validateAndLoadProperty(CREDENTIAL_TYPE_PROPERTY_PREFIX + "." + credentialType + "." + STATIC_VALUE_MAP_ISSUER_ID,STATIC_VALUE_MAP_ISSUER_ID,configMap); - String templateUrl = env.getProperty(PROPERTY_CONSTANT +"." + credentialType + "." + TEMPLATE_URL); + String templateUrl = env.getProperty(CREDENTIAL_TYPE_PROPERTY_PREFIX +"." + credentialType + "." + TEMPLATE_URL); validateAndCacheTemplate(templateUrl,credentialType); // cache configuration with their credential type credentialTypeConfigMap.put(credentialType,configMap); } - private void validateProperty(String propertyName,String credentialProp,Map configMap) throws VCIExchangeException { + private void validateAndLoadProperty(String propertyName, String credentialProp, Map configMap) throws VCIExchangeException { String propertyValue = env.getProperty(propertyName); if (propertyValue == null || propertyValue.isEmpty()) { throw new VCIExchangeException("Property " + propertyName + " is not set Properly."); @@ -229,24 +235,25 @@ private void validateProperty(String propertyName,String credentialProp,Map vcRequestContextList) throws VCIExchangeException { try{ - StringWriter wrt = new StringWriter(); - template.merge(new VelocityContext(),wrt); - Map tempMap= mapper.readValue(wrt.toString(),Map.class); + StringWriter writer = new StringWriter(); + template.merge(new VelocityContext(),writer); + Map tempMap= mapper.readValue(writer.toString(),Map.class); List contextList=(List)tempMap.get("@context"); - for(String contextUrl:contextList){ - if(!vcRequestContextList.contains(contextUrl)){ + for(String contextUrl:vcRequestContextList){ + if(!contextList.contains(contextUrl)){ log.error("ContextUrl is not supported"); throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); } } }catch ( JsonProcessingException e){ - log.error("Error while parsing the templete ",e); + log.error("Error while parsing the template ",e); throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); } } From 8046063f42859b0520eaf333a32c7fcb6b6bc8fc Mon Sep 17 00:00:00 2001 From: Mohd Kaif Siddique Date: Mon, 8 Jan 2024 18:32:05 +0530 Subject: [PATCH 3/4] review changes Signed-off-by: Mohd Kaif Siddique --- .../integration/service/SunbirdRCVCIssuancePlugin.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java index 6caf0b2..b893ef6 100644 --- a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java +++ b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java @@ -18,6 +18,7 @@ import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.RuntimeConstants; +import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; import org.apache.velocity.runtime.resource.loader.URLResourceLoader; import org.json.JSONArray; import org.springframework.beans.factory.annotation.Autowired; @@ -162,7 +163,6 @@ private Map createCredentialIssueRequest(String requestedCredenti Map requestMap=new HashMap<>(); context.put("currentDate", LocalDateTime.now()); context.put("issuerId", configMap.get(STATIC_VALUE_MAP_ISSUER_ID)); - context.put("id",holderId); for (Map.Entry entry : registryObjectMap.entrySet()) { String key = entry.getKey(); Object value = entry.getValue(); @@ -176,6 +176,7 @@ private Map createCredentialIssueRequest(String requestedCredenti template.merge(context, writer); try{ Map credentialObject =mapper.readValue(writer.toString(),Map.class); + ((Map) credentialObject.get("credentialSubject")).put("id", holderId); requestMap.put("credential", credentialObject); requestMap.put("credentialSchemaId",configMap.get(CRED_SCHEMA_ID)); requestMap.put("credentialSchemaVersion",configMap.get(CRED_SCHEMA_VESRION)); From cd6f370a27232fe7612344eae76cdeb51e7469cf Mon Sep 17 00:00:00 2001 From: Mohd Kaif Siddique Date: Mon, 8 Jan 2024 23:01:21 +0530 Subject: [PATCH 4/4] review changes Signed-off-by: Mohd Kaif Siddique --- .../integration/service/SunbirdRCVCIssuancePlugin.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java index b893ef6..40280be 100644 --- a/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java +++ b/sunbird-rc-esignet-integration-impl/src/main/java/io/mosip/esignet/sunbirdrc/integration/service/SunbirdRCVCIssuancePlugin.java @@ -18,7 +18,6 @@ import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.RuntimeConstants; -import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; import org.apache.velocity.runtime.resource.loader.URLResourceLoader; import org.json.JSONArray; import org.springframework.beans.factory.annotation.Autowired; @@ -182,7 +181,7 @@ private Map createCredentialIssueRequest(String requestedCredenti requestMap.put("credentialSchemaVersion",configMap.get(CRED_SCHEMA_VESRION)); requestMap.put("tags",new ArrayList<>()); }catch (JsonProcessingException e){ - log.error("Error while parsing the templete ",e); + log.error("Error while parsing the template ",e); throw new VCIExchangeException(ErrorConstants.VCI_EXCHANGE_FAILED); } //TODO This need to be removed since it can contain PII @@ -245,8 +244,8 @@ private void validateContextUrl(Template template,List vcRequestContextL try{ StringWriter writer = new StringWriter(); template.merge(new VelocityContext(),writer); - Map tempMap= mapper.readValue(writer.toString(),Map.class); - List contextList=(List)tempMap.get("@context"); + Map templateMap = mapper.readValue(writer.toString(),Map.class); + List contextList=(List) templateMap.get("@context"); for(String contextUrl:vcRequestContextList){ if(!contextList.contains(contextUrl)){ log.error("ContextUrl is not supported");