generic IssuanceProbe

This commit is contained in:
Xavi Aracil 2022-12-01 12:30:34 +01:00
parent 739facfe06
commit ce89968837
9 changed files with 121 additions and 18 deletions

View File

@ -26,8 +26,8 @@ public class Assertion extends Credential {
final Assertion.Type assertionType;
protected Assertion(Resource resource, JsonNode data, String jwt, Map<CredentialEnum, SchemaKey> schemas) {
super(resource.getID(), resource, data, jwt, schemas);
protected Assertion(Resource resource, JsonNode data, String jwt, Map<CredentialEnum, SchemaKey> schemas, String issuedOnPropertyName) {
super(resource.getID(), resource, data, jwt, schemas, issuedOnPropertyName);
JsonNode typeNode = jsonData.get("type");
this.assertionType = Assertion.Type.valueOf(typeNode);
@ -60,7 +60,7 @@ public class Assertion extends Credential {
public Assertion build() {
// transform key of schemas map to string because the type of the key in the base map is generic
// and our specific key is an Enum
return new Assertion(getResource(), getJsonData(), getJwt(), schemas);
return new Assertion(getResource(), getJsonData(), getJwt(), schemas, ISSUED_ON_PROPERTY_NAME);
}
}
@ -300,4 +300,5 @@ public class Assertion extends Credential {
.build();
public static final String ID = Assertion.class.getCanonicalName();
private static final String ISSUED_ON_PROPERTY_NAME = "issuedOn";
}

View File

@ -29,14 +29,16 @@ public abstract class Credential extends GeneratedObject {
final Resource resource;
final JsonNode jsonData;
final String jwt;
final String issuedOnPropertyName;
final Map<CredentialEnum, SchemaKey> schemas;
protected Credential(String id, Resource resource, JsonNode data, String jwt, Map<CredentialEnum, SchemaKey> schemas) {
protected Credential(String id, Resource resource, JsonNode data, String jwt, Map<CredentialEnum, SchemaKey> schemas, String issuedOnPropertyName) {
super(id, GeneratedObject.Type.INTERNAL);
this.resource = checkNotNull(resource);
this.jsonData = checkNotNull(data);
this.jwt = jwt; //may be null
this.schemas = schemas;
this.issuedOnPropertyName = issuedOnPropertyName;
checkTrue(RECOGNIZED_PAYLOAD_TYPES.contains(resource.getType()));
}
@ -53,6 +55,10 @@ public abstract class Credential extends GeneratedObject {
return Optional.ofNullable(jwt);
}
public String getIssuedOnPropertyName() {
return issuedOnPropertyName;
}
/**
* Get the canonical schema for this credential if such exists.
*/

View File

@ -111,7 +111,7 @@ public class EndorsementInspector extends VCInspector implements SubInspector {
}
//revocation, expiration and issuance
for(Probe<VerifiableCredential> probe : List.of(new RevocationListProbe(),
for(Probe<Credential> probe : List.of(new RevocationListProbe(),
new ExpirationProbe(), new IssuanceProbe())) {
probeCount++;
accumulator.add(probe.run(endorsement, ctx));

View File

@ -194,7 +194,7 @@ public class OB30Inspector extends VCInspector implements SubInspector {
}
//revocation, expiration and issuance
for(Probe<VerifiableCredential> probe : List.of(new RevocationListProbe(),
for(Probe<Credential> probe : List.of(new RevocationListProbe(),
new ExpirationProbe(), new IssuanceProbe())) {
probeCount++;
accumulator.add(probe.run(ob, ctx));

View File

@ -28,8 +28,8 @@ import com.google.common.collect.ImmutableMap;
public class VerifiableCredential extends Credential {
final VerifiableCredential.Type credentialType;
protected VerifiableCredential(Resource resource, JsonNode data, String jwt, Map<CredentialEnum, SchemaKey> schemas) {
super(ID, resource, data, jwt, schemas);
protected VerifiableCredential(Resource resource, JsonNode data, String jwt, Map<CredentialEnum, SchemaKey> schemas, String issuedOnPropertyName) {
super(ID, resource, data, jwt, schemas, issuedOnPropertyName);
JsonNode typeNode = jsonData.get("type");
this.credentialType = VerifiableCredential.Type.valueOf(typeNode);
@ -133,9 +133,10 @@ public class VerifiableCredential extends Credential {
public static class Builder extends Credential.Builder<VerifiableCredential> {
@Override
public VerifiableCredential build() {
return new VerifiableCredential(getResource(), getJsonData(), getJwt(), schemas);
return new VerifiableCredential(getResource(), getJsonData(), getJwt(), schemas, ISSUED_ON_PROPERTY_NAME);
}
}
public static final String ID = VerifiableCredential.class.getCanonicalName();
private static final String ISSUED_ON_PROPERTY_NAME = "issuanceDate";
}

View File

@ -5,7 +5,7 @@ import java.time.ZonedDateTime;
import org.oneedtech.inspect.core.probe.Probe;
import org.oneedtech.inspect.core.probe.RunContext;
import org.oneedtech.inspect.core.report.ReportItems;
import org.oneedtech.inspect.vc.VerifiableCredential;
import org.oneedtech.inspect.vc.Credential;
import com.fasterxml.jackson.databind.JsonNode;
@ -13,14 +13,14 @@ import com.fasterxml.jackson.databind.JsonNode;
* A Probe that verifies a credential's expiration status
* @author mgylling
*/
public class ExpirationProbe extends Probe<VerifiableCredential> {
public class ExpirationProbe extends Probe<Credential> {
public ExpirationProbe() {
super(ID);
}
@Override
public ReportItems run(VerifiableCredential crd, RunContext ctx) throws Exception {
public ReportItems run(Credential crd, RunContext ctx) throws Exception {
/*
* If the AchievementCredential or EndorsementCredential has an expirationDate property
* and the expiration date is prior to the current date, the credential has expired.

View File

@ -5,7 +5,7 @@ import java.time.ZonedDateTime;
import org.oneedtech.inspect.core.probe.Probe;
import org.oneedtech.inspect.core.probe.RunContext;
import org.oneedtech.inspect.core.report.ReportItems;
import org.oneedtech.inspect.vc.VerifiableCredential;
import org.oneedtech.inspect.vc.Credential;
import com.fasterxml.jackson.databind.JsonNode;
@ -13,19 +13,19 @@ import com.fasterxml.jackson.databind.JsonNode;
* A Probe that verifies a credential's issuance status
* @author mgylling
*/
public class IssuanceProbe extends Probe<VerifiableCredential> {
public class IssuanceProbe extends Probe<Credential> {
public IssuanceProbe() {
super(ID);
}
@Override
public ReportItems run(VerifiableCredential crd, RunContext ctx) throws Exception {
public ReportItems run(Credential crd, RunContext ctx) throws Exception {
/*
* If the AchievementCredential or EndorsementCredential issuanceDate
* property after the current date, the credential is not yet valid.
*/
JsonNode node = crd.getJson().get("issuanceDate");
JsonNode node = crd.getJson().get(crd.getIssuedOnPropertyName());
if(node != null) {
try {
ZonedDateTime issuanceDate = ZonedDateTime.parse(node.textValue());

View File

@ -10,6 +10,7 @@ import java.util.List;
import org.oneedtech.inspect.core.probe.Probe;
import org.oneedtech.inspect.core.probe.RunContext;
import org.oneedtech.inspect.core.report.ReportItems;
import org.oneedtech.inspect.vc.Credential;
import org.oneedtech.inspect.vc.VerifiableCredential;
import org.oneedtech.inspect.vc.util.JsonNodeUtil;
@ -20,14 +21,14 @@ import com.fasterxml.jackson.databind.ObjectMapper;
* A Probe that verifies a credential's revocation status.
* @author mgylling
*/
public class RevocationListProbe extends Probe<VerifiableCredential> {
public class RevocationListProbe extends Probe<Credential> {
public RevocationListProbe() {
super(ID);
}
@Override
public ReportItems run(VerifiableCredential crd, RunContext ctx) throws Exception {
public ReportItems run(Credential crd, RunContext ctx) throws Exception {
/*
* If the AchievementCredential or EndorsementCredential has a credentialStatus property

View File

@ -0,0 +1,94 @@
package org.oneedtech.inspect.vc.probe.validation;
import java.util.UUID;
import org.oneedtech.inspect.core.probe.RunContext;
import org.oneedtech.inspect.core.probe.RunContext.Key;
import org.oneedtech.inspect.core.report.ReportItems;
import org.oneedtech.inspect.util.resource.UriResource;
import org.oneedtech.inspect.vc.Validation;
import org.oneedtech.inspect.vc.jsonld.JsonLdGeneratedObject;
import org.oneedtech.inspect.vc.jsonld.probe.JsonLDCompactionProve;
import org.oneedtech.inspect.vc.util.PrimitiveValueValidator;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.google.common.io.Resources;
public class ValidationFlattenEmbeddedResourcePropertyProbe extends ValidationPropertyProbe {
public ValidationFlattenEmbeddedResourcePropertyProbe(Validation validation) {
super(validation);
}
public ValidationFlattenEmbeddedResourcePropertyProbe(Validation validation, boolean fullValidate) {
super(validation, fullValidate);
}
@Override
protected ReportItems reportForNonExistentProperty(JsonNode node, RunContext ctx) {
return notRun("Expected property " + validation.getName() + " was missing in node " + node.toString(), ctx);
}
@Override
protected ReportItems validate(JsonNode node, RunContext ctx) {
try {
UriResource uriResource = resolveUriResource(ctx, node.asText());
JsonLdGeneratedObject resolved = (JsonLdGeneratedObject) ctx.getGeneratedObject(JsonLDCompactionProve.getId(uriResource));
ObjectMapper mapper = (ObjectMapper) ctx.get(Key.JACKSON_OBJECTMAPPER);
JsonNode fetchedNode = mapper.readTree(resolved.getJson());
if (fetchedNode.isTextual()) {
return notRun("Property " + validation.getName() + " referenced from " + node.toString() + " is not embedded in need of flattening", ctx);
}
if (!fetchedNode.isObject()) {
return error("Property " + validation.getName() + " referenced from " + node.toString() + " is not a JSON object or string as expected", ctx);
}
JsonNode idNode = fetchedNode.get("id");
if (idNode == null) {
// add a new node to the graph
JsonNode newNode = mapper.readTree(Resources.getResource("contexts/ob-v2p0.json"));
ObjectReader readerForUpdating = mapper.readerForUpdating(newNode);
UUID newId = UUID.randomUUID();
JsonNode merged = readerForUpdating.readValue("{\"id\": \"_:" + newId + "\"}");
ctx.addGeneratedObject(new JsonLdGeneratedObject(JsonLDCompactionProve.getId(newId.toString()), merged.toString()));
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 (/*node_class == Assertion && */ !PrimitiveValueValidator.validateUrl(idNode)) {
/*
if not re.match(URN_REGEX, embedded_node_id, re.IGNORECASE):
actions.append(report_message(
'ID format for {} at {} not in an expected HTTP or URN:UUID scheme'.format(
embedded_node_id, abv_node(node_path=[node_id, prop_name])
)))
new_node = value.copy()
new_node['@context'] = OPENBADGES_CONTEXT_V2_URI
actions.append(add_node(embedded_node_id, data=value))
actions.append(patch_node(node_id, {prop_name: embedded_node_id}))
*/
} else {
/*
actions.append(patch_node(node_id, {prop_name: embedded_node_id}))
if not node_match_exists(state, embedded_node_id) and not filter_tasks(
state, node_id=embedded_node_id, task_type=FETCH_HTTP_NODE):
# fetch
actions.append(add_task(FETCH_HTTP_NODE, url=embedded_node_id))
*/
}
} catch (Throwable t) {
return fatal(t.getMessage(), ctx);
}
return success(ctx);
}
}