Check required values for type attribute
added attributes for required type and achievement return error instead of notRun
This commit is contained in:
@@ -188,8 +188,8 @@ public class EndorsementInspector extends VCInspector implements SubInspector {
|
||||
|
||||
//credentialSubject
|
||||
probeCount++;
|
||||
accumulator.add(new CredentialSubjectProbe().run(endorsement.getJson(), ctx));
|
||||
|
||||
accumulator.add(new CredentialSubjectProbe("EndorsementSubject").run(endorsement.getJson(), ctx));
|
||||
|
||||
//signatures, proofs
|
||||
probeCount++;
|
||||
if(endorsement.getProofType() == EXTERNAL){
|
||||
|
||||
@@ -170,7 +170,7 @@ public class OB30Inspector extends VCInspector implements SubInspector {
|
||||
|
||||
//credentialSubject
|
||||
probeCount++;
|
||||
accumulator.add(new CredentialSubjectProbe().run(ob.getJson(), ctx));
|
||||
accumulator.add(new CredentialSubjectProbe("AchievementSubject", true).run(ob.getJson(), ctx));
|
||||
|
||||
//signatures, proofs
|
||||
probeCount++;
|
||||
|
||||
+96
-13
@@ -1,21 +1,36 @@
|
||||
package org.oneedtech.inspect.vc.probe;
|
||||
|
||||
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.util.JsonNodeUtil;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
|
||||
/**
|
||||
* A Probe that checks credential subject specifics not capturable by schemata.
|
||||
*
|
||||
*
|
||||
* @author mgylling
|
||||
*/
|
||||
public class CredentialSubjectProbe extends Probe<JsonNode> {
|
||||
|
||||
public CredentialSubjectProbe() {
|
||||
|
||||
/**
|
||||
* Required type to be present.
|
||||
*/
|
||||
private final String requiredType;
|
||||
private boolean achivementRequired;
|
||||
|
||||
public CredentialSubjectProbe(String requiredType) {
|
||||
this(requiredType, false);
|
||||
}
|
||||
|
||||
public CredentialSubjectProbe(String requiredType, boolean achivementRequired) {
|
||||
super(ID);
|
||||
this.requiredType = requiredType;
|
||||
this.achivementRequired = achivementRequired;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -24,18 +39,86 @@ public class CredentialSubjectProbe extends Probe<JsonNode> {
|
||||
JsonNode subject = root.get("credentialSubject");
|
||||
if(subject == null) return notRun("no credentialSubject node found", ctx); //error reported by schema
|
||||
|
||||
/*
|
||||
* Check that we have either .id or .identifier populated
|
||||
/**
|
||||
* Check that type contains AchievementSubject
|
||||
*/
|
||||
if (!JsonNodeUtil.asStringList(subject.get("type")).contains(requiredType)) {
|
||||
return error("credentialSubject is not of type \"" + requiredType + "\"", ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that we have either .id or .identifier populated
|
||||
*/
|
||||
if (idAndIdentifierEmpty(subject)) {
|
||||
return error("no id in credentialSubject", ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* if .identifier is provider, check its type
|
||||
*/
|
||||
if (subject.hasNonNull("identifier")) {
|
||||
List<JsonNode> identifiers = JsonNodeUtil.asNodeList(subject.get("identifier"));
|
||||
for (JsonNode identifier : identifiers) {
|
||||
// check that type contains "IdentityObject"
|
||||
if (!JsonNodeUtil.asStringList(identifier.get("type")).contains("IdentityObject")) {
|
||||
return error("identifier in credentialSubject is not of type \"IdentityObject\"", ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check results
|
||||
*/
|
||||
if (subject.hasNonNull("result")) {
|
||||
List<JsonNode> results = JsonNodeUtil.asNodeList(subject.get("result"));
|
||||
for (JsonNode result : results) {
|
||||
// check that type contains "Result"
|
||||
if (!JsonNodeUtil.asStringList(result.get("type")).contains("Result")) {
|
||||
return error("result in credentialSubject is not of type \"Result\"", ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Check achievement result description
|
||||
*/
|
||||
if (subject.hasNonNull("achievement")) {
|
||||
JsonNode achievement = subject.get("achievement");
|
||||
if (achievement.hasNonNull("resultDescription")) {
|
||||
List<JsonNode> resultDescriptions = JsonNodeUtil.asNodeList(achievement.get("resultDescription"));
|
||||
for (JsonNode resultDescription : resultDescriptions) {
|
||||
// check that type contains "ResultDescription"
|
||||
if (!JsonNodeUtil.asStringList(resultDescription.get("type")).contains("ResultDescription")) {
|
||||
return error("resultDescription in achievement of credentialSubject is not of type \"ResultDescription\"", ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (achivementRequired) {
|
||||
return error("missing required achievement in credentialSubject", ctx);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check that source type contains "Profile"
|
||||
*/
|
||||
if (subject.hasNonNull("source")) {
|
||||
JsonNode source = subject.get("source");
|
||||
// check that type contains "Profile"
|
||||
if (!JsonNodeUtil.asStringList(source.get("type")).contains("Profile")) {
|
||||
return error("source in credentialSubject is not of type \"Profile\"", ctx);
|
||||
}
|
||||
}
|
||||
return success(ctx);
|
||||
}
|
||||
|
||||
private boolean idAndIdentifierEmpty(JsonNode root) {
|
||||
JsonNode id = root.get("id");
|
||||
if (id != null && id.textValue().strip().length() > 0) return success(ctx);
|
||||
|
||||
JsonNode identifier = root.get("identifier");
|
||||
if(identifier != null && identifier instanceof ArrayNode
|
||||
&& ((ArrayNode)identifier).size() > 0) return success(ctx);
|
||||
|
||||
return error("no id in credentialSubject", ctx);
|
||||
|
||||
if (id != null && id.textValue().strip().length() > 0) return false;
|
||||
|
||||
JsonNode identifier = root.get("identifier");
|
||||
if(identifier != null && identifier instanceof ArrayNode
|
||||
&& ((ArrayNode)identifier).size() > 0) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static final String ID = CredentialSubjectProbe.class.getSimpleName();
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
package org.oneedtech.inspect.vc.probe;
|
||||
|
||||
import java.net.URI;
|
||||
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.util.resource.UriResource;
|
||||
import org.oneedtech.inspect.vc.util.JsonNodeUtil;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
|
||||
public class IssuerProbe extends Probe<JsonNode> {
|
||||
public IssuerProbe() {
|
||||
super(ID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ReportItems run(JsonNode root, RunContext ctx) throws Exception {
|
||||
JsonNode issuer = root.get("issuer");
|
||||
if(issuer == null) return error("no issuer node found", ctx);
|
||||
|
||||
// check that type contains "Profile"
|
||||
if (!JsonNodeUtil.asStringList(issuer.get("type")).contains("Profile")) {
|
||||
return error("issuer is not of type \"Profile\"", ctx);
|
||||
}
|
||||
|
||||
// check url is accessible
|
||||
if (issuer.hasNonNull("url")) {
|
||||
try {
|
||||
UriResource urlResource = new UriResource(new URI(issuer.get("url").asText().strip()));
|
||||
if (!urlResource.exists()) {
|
||||
return warning("url \"" + issuer.get("url").asText().strip() + "\" in issuer is not accessible", ctx);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return warning("url \"" + issuer.get("url").asText().strip() + "\" in issuer is not accessible", ctx);
|
||||
}
|
||||
}
|
||||
|
||||
// check other identifier
|
||||
if (issuer.hasNonNull("otherIdentifier")) {
|
||||
List<JsonNode> otherIdentifiers = JsonNodeUtil.asNodeList(issuer.get("otherIdentifier"));
|
||||
for (JsonNode otherIdentifier : otherIdentifiers) {
|
||||
// check that type contains "IdentityObject"
|
||||
if (!JsonNodeUtil.asStringList(otherIdentifier.get("type")).contains("IdentityObject")) {
|
||||
return error("otherIdentifier in issuer is not of type \"IdentityObject\"", ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check parent issuer
|
||||
if (issuer.hasNonNull("parentOrg")) {
|
||||
JsonNode parentOrg = issuer.get("parentOrg");
|
||||
// check that type contains "Profile"
|
||||
if (!JsonNodeUtil.asStringList(parentOrg.get("type")).contains("Profile")) {
|
||||
return error("parentOrg in issuer is not of type \"Profile\"", ctx);
|
||||
}
|
||||
}
|
||||
|
||||
return success(ctx);
|
||||
}
|
||||
|
||||
public static final String ID = IssuerProbe.class.getSimpleName();
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user