Merge pull request #67 from imsglc/feature/open-badges-20

Feature/open badges 20
This commit is contained in:
Xavi Aracil 2022-12-21 09:50:32 +01:00 committed by GitHub
commit d6a85ad00d
3 changed files with 64 additions and 51 deletions

View File

@ -115,11 +115,11 @@ public class Assertion extends Credential {
return found; return found;
} }
} }
}
// check external type // check external type
if (validateIri(typeNode)) { if (validateIri(typeNode)) {
return External; return External;
}
} }
return Unknown; return Unknown;

View File

@ -3,7 +3,6 @@ package org.oneedtech.inspect.vc.jsonld.probe;
import static org.oneedtech.inspect.vc.Assertion.ValueType.DATA_URI_OR_URL; import static org.oneedtech.inspect.vc.Assertion.ValueType.DATA_URI_OR_URL;
import java.io.IOException; import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.net.URL; import java.net.URL;
import java.util.List; import java.util.List;
@ -27,7 +26,6 @@ import org.oneedtech.inspect.vc.Validation;
import org.oneedtech.inspect.vc.jsonld.JsonLdGeneratedObject; import org.oneedtech.inspect.vc.jsonld.JsonLdGeneratedObject;
import org.oneedtech.inspect.vc.probe.CredentialParseProbe; import org.oneedtech.inspect.vc.probe.CredentialParseProbe;
import org.oneedtech.inspect.vc.resource.UriResourceFactory; import org.oneedtech.inspect.vc.resource.UriResourceFactory;
import org.oneedtech.inspect.vc.util.CachingDocumentLoader;
import org.oneedtech.inspect.vc.util.JsonNodeUtil; import org.oneedtech.inspect.vc.util.JsonNodeUtil;
import org.oneedtech.inspect.vc.util.PrimitiveValueValidator; import org.oneedtech.inspect.vc.util.PrimitiveValueValidator;
@ -38,8 +36,6 @@ import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.ObjectReader;
import com.google.common.io.Resources; import com.google.common.io.Resources;
import foundation.identity.jsonld.ConfigurableDocumentLoader;
/** /**
* Probe for fetching all elements in the graph for Open Badges 2.0 validation * Probe for fetching all elements in the graph for Open Badges 2.0 validation
* Contains the fetch part of "VALIDATE_TYPE_PROPERTY" task in python implementation, as well as the "FLATTEN_EMBEDDED_RESOURCE" task * Contains the fetch part of "VALIDATE_TYPE_PROPERTY" task in python implementation, as well as the "FLATTEN_EMBEDDED_RESOURCE" task
@ -72,47 +68,10 @@ public class GraphFetcherProbe extends Probe<JsonNode> {
// flatten embeded resource // flatten embeded resource
if (validation.isAllowFlattenEmbeddedResource()) { if (validation.isAllowFlattenEmbeddedResource()) {
if (!node.isTextual()) { result = flatten(ctx, result, root, node, validation);
if (!node.isObject()) {
return error("Property " + validation.getName() + " referenced from " + assertion.getJson().toString() + " is not a JSON object or string as expected", ctx);
}
JsonNode idNode = node.get("id");
if (idNode == null) {
// add a new node to the graph
UUID newId = UUID.randomUUID();
JsonNode merged = createNewJson(ctx, "{\"id\": \"_:" + newId + "\"}");
ctx.addGeneratedObject(new JsonLdGeneratedObject(JsonLDCompactionProve.getId(newId.toString()), merged.toString()));
// update existing node with new id
updateNode(validation, idNode, ctx);
return warning("Node id missing at " + node.toString() + ". A blank node ID has been assigned", ctx);
} else if (!idNode.isTextual() || !PrimitiveValueValidator.validateIri(idNode)) {
return error("Embedded JSON object at " + node.asText() + " has no proper assigned id.", ctx);
} else if (assertion.getCredentialType() == Type.Assertion && !PrimitiveValueValidator.validateUrl(idNode)) {
if (!isUrn(idNode)) {
logger.info("ID format for " + idNode.toString() + " at " + assertion.getCredentialType() + " not in an expected HTTP or URN:UUID scheme");
}
// add a new node to the graph
JsonNode merged = createNewJson(ctx, node);
ctx.addGeneratedObject(new JsonLdGeneratedObject(JsonLDCompactionProve.getId(idNode.asText().strip()), merged.toString()));
// update existing node with new id
updateNode(validation, idNode, ctx);
} else {
// update existing node with new id
updateNode(validation, idNode, ctx);
// fetch node and add it to the graph
result = fetchNode(ctx, result, idNode);
}
}
} }
// fetch
List<JsonNode> nodeList = JsonNodeUtil.asNodeList(node); List<JsonNode> nodeList = JsonNodeUtil.asNodeList(node);
for (JsonNode childNode : nodeList) { for (JsonNode childNode : nodeList) {
if (shouldFetch(childNode, validation)) { if (shouldFetch(childNode, validation)) {
@ -125,6 +84,60 @@ public class GraphFetcherProbe extends Probe<JsonNode> {
return success(ctx); return success(ctx);
} }
private ReportItems flatten(RunContext ctx, ReportItems result, JsonNode parentNode, JsonNode node, Validation validation) throws URISyntaxException, Exception {
if (!node.isTextual()) {
if (!node.isObject()) {
result = new ReportItems(List.of(result, error("Property " + validation.getName() + " referenced from " + assertion.getJson().toString() + " is not a JSON object or string as expected", ctx)));
}
JsonNode idNode = node.get("id");
if (idNode == null) {
// add a new node to the graph
UUID newId = UUID.randomUUID();
JsonNode merged = createNewJson(ctx, "{\"id\": \"_:" + newId + "\"}");
ctx.addGeneratedObject(new JsonLdGeneratedObject(JsonLDCompactionProve.getId(newId.toString()), merged.toString()));
// update existing node with new id
updateNode(validation, parentNode.get("id").asText().strip(), idNode, ctx);
return warning("Node id missing at " + node.toString() + ". A blank node ID has been assigned", ctx);
} else if (!idNode.isTextual() || !PrimitiveValueValidator.validateIri(idNode)) {
return new ReportItems(List.of(result, error("Embedded JSON object at " + node.asText() + " has no proper assigned id.", ctx)));
} else { // if (assertion.getCredentialType() == Type.Assertion && !PrimitiveValueValidator.validateUrl(idNode)) {
if (!isUrn(idNode)) {
logger.info("ID format for " + idNode.toString() + " at " + assertion.getCredentialType() + " not in an expected HTTP or URN:UUID scheme");
}
// add a new node to the graph
JsonNode merged = createNewJson(ctx, node);
ctx.addGeneratedObject(new JsonLdGeneratedObject(JsonLDCompactionProve.getId(idNode.asText().strip()), merged.toString()));
// update existing node with new id
updateNode(validation, parentNode.get("id").asText().strip(), idNode, ctx);
// } else {
// // update existing node with new id
// updateNode(validation, idNode, ctx);
// // fetch node and add it to the graph
// result = new ReportItems(List.of(result, fetchNode(ctx, result, idNode)));
}
// recursive call
List<Validation> flattenValidations = Type.valueOf(node.get("type")).getValidations().stream()
.filter(val -> val.getType() == ValueType.ID && val.isAllowFlattenEmbeddedResource())
.filter(val -> node.hasNonNull(val.getName()))
.collect(Collectors.toList());
for (Validation val : flattenValidations) {
if (node.hasNonNull(val.getName())) {
result = new ReportItems(List.of(result, flatten(ctx, result, node, node.get(val.getName()), val)));
}
}
}
return result;
}
private ReportItems fetchNode(RunContext ctx, ReportItems result, JsonNode idNode) private ReportItems fetchNode(RunContext ctx, ReportItems result, JsonNode idNode)
throws URISyntaxException, Exception, JsonProcessingException, JsonMappingException { throws URISyntaxException, Exception, JsonProcessingException, JsonMappingException {
System.out.println("fetchNode " + idNode.asText().strip()); System.out.println("fetchNode " + idNode.asText().strip());
@ -165,8 +178,8 @@ public class GraphFetcherProbe extends Probe<JsonNode> {
(validation.isAllowDataUri() || ValueType.IRI.getValidationFunction().apply(node)); (validation.isAllowDataUri() || ValueType.IRI.getValidationFunction().apply(node));
} }
private void updateNode(Validation validation, JsonNode idNode, RunContext ctx) throws IOException { private void updateNode(Validation validation, String parentId, JsonNode idNode, RunContext ctx) throws IOException {
JsonLdGeneratedObject jsonLdGeneratedObject = ctx.getGeneratedObject(JsonLDCompactionProve.getId(assertion)); JsonLdGeneratedObject jsonLdGeneratedObject = ctx.getGeneratedObject(JsonLDCompactionProve.getId(parentId));
JsonNode merged = createNewJson(ctx, jsonLdGeneratedObject.getJson(), "{\"" + validation.getName() + "\": \"" + idNode.asText().strip() + "\"}"); JsonNode merged = createNewJson(ctx, jsonLdGeneratedObject.getJson(), "{\"" + validation.getName() + "\": \"" + idNode.asText().strip() + "\"}");
jsonLdGeneratedObject.setJson(merged.toString()); jsonLdGeneratedObject.setJson(merged.toString());

View File

@ -26,7 +26,7 @@ public class ExpirationProbe extends Probe<Credential> {
* and the expiration date is prior to the current date, the credential has expired. * and the expiration date is prior to the current date, the credential has expired.
*/ */
JsonNode node = crd.getJson().get(crd.getExpiresAtPropertyName()); JsonNode node = crd.getJson().get(crd.getExpiresAtPropertyName());
if(node != null) { if(node != null && !node.isNull()) {
try { try {
ZonedDateTime expirationDate = ZonedDateTime.parse(node.textValue()); ZonedDateTime expirationDate = ZonedDateTime.parse(node.textValue());
if (ZonedDateTime.now().isAfter(expirationDate)) { if (ZonedDateTime.now().isAfter(expirationDate)) {