Skip to content

Commit

Permalink
[INJICERT-434] add local changes
Browse files Browse the repository at this point in the history
will be reverted

Signed-off-by: Harsh Vardhan <[email protected]>
  • Loading branch information
vharsh committed Sep 27, 2024
1 parent 516c877 commit 7f61379
Show file tree
Hide file tree
Showing 15 changed files with 263 additions and 40 deletions.
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package io.mosip.certify.core.constants;

/**
* SignatureAlg is the constants file of supported VC sign algorithms.
* TODO(later): convert this into a structure such that it enables
* consumers to choose VC sign algos with
*/
public class SignatureAlg {
// LinkedDataSignature Algorithms
public static final String RSA_SIGNATURE_2018 = "RsaSignature2018";
public static final String RSA_SIGNATURE_SUITE = "RsaSignature2018";

// RS256, PS256, ES256
public static final String ED25519_SIGNATURE_SUITE = "Ed25519Signature2018";

// RS256, PS256, ES256 --> JWSAlgorithm.RS256.getName();
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,27 @@

import jakarta.persistence.Entity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.*;
import jakarta.validation.constraints.NotBlank;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.util.Objects;

@Data
@Entity
@NoArgsConstructor
@AllArgsConstructor
@IdClass(TemplateId.class)
public class TemplateData {
@NotBlank(message = "Template is mandatory")
@Getter
@Setter
private String template;
@Id
@Getter
@Setter
private String context;
@Id
@Getter
@Setter
private String credentialType;
}

Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
package io.mosip.certify.core.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.*;

import java.io.Serializable;
import java.util.Objects;

@Data
@AllArgsConstructor
@NoArgsConstructor
@AllArgsConstructor
public class TemplateId implements Serializable {
@Getter
@Setter
private String context;
@Getter
@Setter
private String credentialType;

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,88 @@
package io.mosip.certify.core.templating;

import io.mosip.certify.core.repository.TemplateRepository;
import junit.framework.TestCase;
import lombok.SneakyThrows;
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.junit.Before;
import org.junit.Test;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class VelocityTemplatingEngineImplTest extends TestCase {
private VelocityEngine engine;
private final Map<String, Template> templateCache = new ConcurrentHashMap<>();
@MockBean
private TemplateRepository templateRepository;

@Before
public void setUp() throws Exception {
engine = new VelocityEngine();
engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
engine.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS, "org.apache.velocity.runtime.log.NullLogChute");
engine.setProperty(RuntimeConstants.INPUT_ENCODING, "UTF-8");
engine.setProperty(RuntimeConstants.OUTPUT_ENCODING, "UTF-8");
engine.init();
}

@SneakyThrows
@Test
public void testTemplating() {
// 1. setup template
Template t = engine.getTemplate("SchoolTemplate.vm");
Template t = engine.getTemplate("MockCredential.vm");
assert t != null;
Map<String, Object> templateInput = new HashMap<>();
VelocityContext c = new VelocityContext();
StringWriter writer = new StringWriter();
engine.evaluate(c, writer, "SchoolTemplateTest", t.toString());
String out = writer.toString();

Map<String, Object> res = new RestTemplate().getForObject(
"https://api.dev1.mosip.net/v1/mock-identity-system/identity/34455445765",
HashMap.class);
res = (Map<String, Object>) res.get("response");
Map<String, Object> ret = new HashMap<>();
ret.put("vcVer", "VC-V1");
ret.put("name", res.get("name"));
ret.put("fullName", res.get("fullName"));
ret.put("gender", res.get("gender"));
ret.put("dateOfBirth", res.get("dateOfBirth"));
ret.put("email", res.get("email"));
ret.put("UIN", "34455445765");
ret.put("phone", res.get("phone"));
ret.put("addressLine1", res.get("streetAddress"));
ret.put("province", res.get("locality"));
ret.put("region", res.get("region"));
ret.put("postalCode", res.get("postalCode"));
ret.put("face", res.get("encodedPhoto"));
Map<String, Object> finalTemplate = new HashMap<>();
for (String key : ret.keySet()) {
Object value = ret.get(key);
if (value instanceof List) {
finalTemplate.put(key, new JSONArray((List<String>) value));
} else if (value instanceof JSONArray) {
finalTemplate.put(key, new JSONArray(value));
} else {
finalTemplate.put(key, value);
}
}
VelocityContext context = new VelocityContext(finalTemplate);
InputStream is = new ByteArrayInputStream(t.toString().getBytes(StandardCharsets.UTF_8));
t.merge(context, writer);
}
}
25 changes: 25 additions & 0 deletions certify-core/src/test/resources/MockCredential.vm
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"@context": [
"https://www.w3.org/ns/credentials/v2",
"https://schema.org"
],
"issuer": "${issuer}",
"type": ["VerifiableCredential", "MockVerifiableCredential"],
"validFrom": "${validFrom}",
"validUntil": "${validUntil}",
"credentialSubject": {
"gender": ${gender},
"postalCode": ${postalCode},
"fullName": ${fullName},
"dateOfBirth": "${dateOfBirth}",
"province": ${province},
"phone": "${phone}",
"addressLine1": ${addressLine1},
"region": ${region},
"vcVer": "${vcVer}",
"UIN": ${UIN},
"email": "${email}",
"id": "${id}",
"face": "${face}"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

@EnableAsync
@EnableCaching
@EnableJpaRepositories
@SpringBootApplication(scanBasePackages = "io.mosip.certify,"+
"io.mosip.certify.core.*," +
"io.mosip.kernel.crypto," +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import org.springframework.web.client.RestTemplate;

@Configuration
@EnableJpaRepositories(basePackages = {"io.mosip.kernel.keymanagerservice.repository"})
@EnableJpaRepositories(basePackages = {"io.mosip.kernel.keymanagerservice.repository", "io.mosip.certify.core.repository"})
@EntityScan(basePackages = {"io.mosip.kernel.keymanagerservice.entity, io.mosip.certify.core.entity"})
@Slf4j
public class AppConfig implements ApplicationRunner {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@ public VCResult<JsonLDObject> perform(String templatedVC, Map<String, String> ke
VCResult<JsonLDObject> VC = null;
JsonLDObject j = JsonLDObject.fromJson(templatedVC);
j.setDocumentLoader(null);
// NOTE: other aspects can be configured via keyMgrInput map
Date validFrom = Date
.from(LocalDateTime
.parse((String) j.getJsonObject().get(VCDM2Constants.VALID_FROM),
DateTimeFormatter.ofPattern(Constants.UTC_DATETIME_PATTERN))
.atZone(ZoneId.systemDefault()).toInstant());
LdProof vcLdProof = LdProof.builder().defaultContexts(false).defaultTypes(false).type(SignatureAlg.RSA_SIGNATURE_2018)
LdProof vcLdProof = LdProof.builder().defaultContexts(false).defaultTypes(false).type(SignatureAlg.RSA_SIGNATURE_SUITE)
.created(validFrom).proofPurpose(VCDM2Constants.ASSERTION_METHOD)
.verificationMethod(URI.create("https://vharsh.github.io/DID/mock-public-key.json"))
// ^^ Why is this pointing to JWKS URL of eSignet??
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
package io.mosip.certify.services.templating;

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;

import io.mosip.certify.api.spi.VCFormatter;
import io.mosip.certify.core.constants.VCDM2Constants;
import io.mosip.certify.core.repository.TemplateRepository;
import jakarta.annotation.PostConstruct;
import lombok.SneakyThrows;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.tools.generic.DateTool;
import org.json.JSONArray;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

@Service
Expand All @@ -20,12 +23,8 @@ public class VelocityTemplatingEngineImpl implements VCFormatter {
Map<String, String> templateCache;
@Autowired
TemplateRepository templateRepository;
// DATA to be fetched from DB

@Autowired
public void setTemplateRepository(TemplateRepository templateRepository) {
this.templateRepository = templateRepository;
}
@Value("${mosip.certify.vcformat.vc.expiry:true}")
boolean shouldHaveDates;

@PostConstruct
public void initialize() {
Expand Down Expand Up @@ -54,15 +53,33 @@ public void initialize() {
* internal work such as locating the appropriate template
* @return templated VC as a String
*/
@SneakyThrows
@Override
public String format(Map<String, Object> templateInput, Map<String, Object> defaultSettings) {
// TODO: Isn't template name becoming too complex with VC_CONTEXTS & CREDENTIAL_TYPES both?
String templateName = defaultSettings.get("templateName").toString();
String t = templateCache.get(templateName);
StringWriter writer = new StringWriter();
// 1. Prepare map
Map<String, Object> finalTemplate = new HashMap<>();
for (String key : templateInput.keySet()) {
Object value = templateInput.get(key);
if (value instanceof List) {
// TODO(problem area): handle field values with unescaped JSON
// reserved literals such as " or ,
// (Q) Should Object always be a JSONObject?
finalTemplate.put(key, new JSONArray((List<String>) value));
} else {
finalTemplate.put(key, value);
}
}
if (shouldHaveDates && !(templateInput.containsKey(VCDM2Constants.VALID_FROM)
&& templateInput.containsKey(VCDM2Constants.VALID_UNITL))) {
templateInput.put("_dateTool", new DateTool());
templateInput.put(VCDM2Constants.VALID_FROM, "$now");
templateInput.put(VCDM2Constants.VALID_UNITL, "$now+3");
}
VelocityContext context = new VelocityContext(templateInput);
// TODO: Check config for templateName.* fields and apply those configs as well, e.g. auto-fill validFrom & validUntil
InputStream is = new ByteArrayInputStream(t.toString().getBytes(StandardCharsets.UTF_8));
engine.evaluate(context, writer, /*logTag */ templateName,t.toString());
return writer.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

import io.mosip.certify.api.dto.VCRequestDto;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CredentialUtils {
// returns true for VC 2.0 VCI requests
public static boolean isVC2_0Request(VCRequestDto r) {
Expand All @@ -15,4 +19,19 @@ public static boolean isNextGenPluginRequest(VCRequestDto r) {
// TODO: use the Host header + credential.type
return true;
}

/**
* get the template name for a VCRequest for VCFormatter lib
* @param vcRequestDto
* @return
*/
public static String getTemplateName(VCRequestDto vcRequestDto) {
List<String> c = new ArrayList<>(vcRequestDto.getContext());
List<String> t = new ArrayList<>(vcRequestDto.getType());
Collections.sort(c);
Collections.sort(t);
String contextKey = String.join(",", c);
String typeKey = String.join(",", t);
return String.join(":", typeKey, contextKey);
}
}
Loading

0 comments on commit 7f61379

Please sign in to comment.