add @context value check probe
This commit is contained in:
parent
5e6a277185
commit
bbcfac14fc
@ -30,6 +30,8 @@ import org.oneedtech.inspect.util.resource.ResourceType;
|
|||||||
import org.oneedtech.inspect.util.resource.UriResource;
|
import org.oneedtech.inspect.util.resource.UriResource;
|
||||||
import org.oneedtech.inspect.util.resource.context.ResourceContext;
|
import org.oneedtech.inspect.util.resource.context.ResourceContext;
|
||||||
import org.oneedtech.inspect.util.spec.Specification;
|
import org.oneedtech.inspect.util.spec.Specification;
|
||||||
|
import org.oneedtech.inspect.vc.Credential.Type;
|
||||||
|
import org.oneedtech.inspect.vc.probe.ContextPropertyProbe;
|
||||||
import org.oneedtech.inspect.vc.probe.CredentialParseProbe;
|
import org.oneedtech.inspect.vc.probe.CredentialParseProbe;
|
||||||
import org.oneedtech.inspect.vc.probe.ExpirationVerifierProbe;
|
import org.oneedtech.inspect.vc.probe.ExpirationVerifierProbe;
|
||||||
import org.oneedtech.inspect.vc.probe.InlineJsonSchemaProbe;
|
import org.oneedtech.inspect.vc.probe.InlineJsonSchemaProbe;
|
||||||
@ -90,14 +92,15 @@ public class OB30Inspector extends VCInspector {
|
|||||||
//we expect the above to place a generated object in the context
|
//we expect the above to place a generated object in the context
|
||||||
Credential crd = ctx.getGeneratedObject(Credential.ID);
|
Credential crd = ctx.getGeneratedObject(Credential.ID);
|
||||||
|
|
||||||
//TODO check context IRIs? the schema doesnt do this
|
|
||||||
|
|
||||||
//TODO new check: that subject @id or IdentityObject is available (at least one is the req)
|
//TODO new check: that subject @id or IdentityObject is available (at least one is the req)
|
||||||
|
|
||||||
//type property
|
//context and type properties
|
||||||
probeCount++;
|
Credential.Type type = Type.OpenBadgeCredential;
|
||||||
accumulator.add(new TypePropertyProbe(OpenBadgeCredential).run(crd.getJson(), ctx));
|
for(Probe<JsonNode> probe : List.of(new ContextPropertyProbe(type), new TypePropertyProbe(type))) {
|
||||||
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
probeCount++;
|
||||||
|
accumulator.add(probe.run(crd.getJson(), ctx));
|
||||||
|
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
||||||
|
}
|
||||||
|
|
||||||
//canonical schema and inline schemata
|
//canonical schema and inline schemata
|
||||||
SchemaKey schema = crd.getSchemaKey().orElseThrow();
|
SchemaKey schema = crd.getSchemaKey().orElseThrow();
|
||||||
|
@ -0,0 +1,63 @@
|
|||||||
|
package org.oneedtech.inspect.vc.probe;
|
||||||
|
|
||||||
|
import static org.oneedtech.inspect.util.code.Defensives.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
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.util.JsonNodeUtil;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Probe that verifies a credential's context property.
|
||||||
|
*
|
||||||
|
* @author mgylling
|
||||||
|
*/
|
||||||
|
public class ContextPropertyProbe extends Probe<JsonNode> {
|
||||||
|
private final Credential.Type type;
|
||||||
|
|
||||||
|
public ContextPropertyProbe(Credential.Type type) {
|
||||||
|
super(ID);
|
||||||
|
this.type = checkNotNull(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ReportItems run(JsonNode root, RunContext ctx) throws Exception {
|
||||||
|
|
||||||
|
ArrayNode contextNode = (ArrayNode) root.get("@context");
|
||||||
|
if (contextNode == null) {
|
||||||
|
return fatal("No @context property", ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> expected = values.get(type);
|
||||||
|
if(expected == null) {
|
||||||
|
return fatal(type.name() + " not recognized", ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> given = JsonNodeUtil.asStringList(contextNode);
|
||||||
|
int pos = 0;
|
||||||
|
for(String uri : expected) {
|
||||||
|
if((given.size() < pos+1) || !given.get(pos).equals(uri)) {
|
||||||
|
return error("missing required @context uri " + uri + " at position " + (pos+1), ctx);
|
||||||
|
}
|
||||||
|
pos++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return success(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final static Map<Credential.Type, List<String>> values = new ImmutableMap.Builder<Credential.Type, List<String>>()
|
||||||
|
.put(Credential.Type.OpenBadgeCredential,
|
||||||
|
List.of("https://www.w3.org/2018/credentials/v1",
|
||||||
|
"https://imsglobal.github.io/openbadges-specification/context.json")) //TODO will change (https://purl.imsglobal.org/spec/ob/v3p0/context/ob_v3p0.jsonld)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
public static final String ID = ContextPropertyProbe.class.getSimpleName();
|
||||||
|
}
|
@ -10,6 +10,7 @@ import org.oneedtech.inspect.core.Inspector.Behavior;
|
|||||||
import org.oneedtech.inspect.core.probe.json.JsonSchemaProbe;
|
import org.oneedtech.inspect.core.probe.json.JsonSchemaProbe;
|
||||||
import org.oneedtech.inspect.core.report.Report;
|
import org.oneedtech.inspect.core.report.Report;
|
||||||
import org.oneedtech.inspect.test.PrintHelper;
|
import org.oneedtech.inspect.test.PrintHelper;
|
||||||
|
import org.oneedtech.inspect.vc.probe.ContextPropertyProbe;
|
||||||
import org.oneedtech.inspect.vc.probe.ExpirationVerifierProbe;
|
import org.oneedtech.inspect.vc.probe.ExpirationVerifierProbe;
|
||||||
import org.oneedtech.inspect.vc.probe.InlineJsonSchemaProbe;
|
import org.oneedtech.inspect.vc.probe.InlineJsonSchemaProbe;
|
||||||
import org.oneedtech.inspect.vc.probe.IssuanceVerifierProbe;
|
import org.oneedtech.inspect.vc.probe.IssuanceVerifierProbe;
|
||||||
@ -109,6 +110,17 @@ public class OB30Tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testSimpleJsonContextError() {
|
||||||
|
//removed one of the reqd context uris
|
||||||
|
assertDoesNotThrow(()->{
|
||||||
|
Report report = validator.run(Samples.OB30.JSON.SIMPLE_JSON_ERR_CONTEXT.asFileResource());
|
||||||
|
if(verbose) PrintHelper.print(report, true);
|
||||||
|
assertInvalid(report);
|
||||||
|
assertHasProbeID(report, ContextPropertyProbe.ID, true);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testSimpleJsonSchemaError() throws Exception {
|
void testSimpleJsonSchemaError() throws Exception {
|
||||||
//issuer removed
|
//issuer removed
|
||||||
|
@ -17,6 +17,7 @@ public class Samples {
|
|||||||
public final static Sample SIMPLE_JSON_EXPIRED = new Sample("ob30/simple-err-expired.json", false);
|
public final static Sample SIMPLE_JSON_EXPIRED = new Sample("ob30/simple-err-expired.json", false);
|
||||||
public final static Sample SIMPLE_JSON_ISSUED = new Sample("ob30/simple-err-issued.json", false);
|
public final static Sample SIMPLE_JSON_ISSUED = new Sample("ob30/simple-err-issued.json", false);
|
||||||
public final static Sample SIMPLE_JSON_ISSUER = new Sample("ob30/simple-err-issuer.json", false);
|
public final static Sample SIMPLE_JSON_ISSUER = new Sample("ob30/simple-err-issuer.json", false);
|
||||||
|
public final static Sample SIMPLE_JSON_ERR_CONTEXT = new Sample("ob30/simple-err-context.json", false);
|
||||||
}
|
}
|
||||||
public static final class PNG {
|
public static final class PNG {
|
||||||
public final static Sample SIMPLE_JWT_PNG = new Sample("ob30/simple-jwt.png", true);
|
public final static Sample SIMPLE_JWT_PNG = new Sample("ob30/simple-jwt.png", true);
|
||||||
|
35
inspector-vc/src/test/resources/ob30/simple-err-context.json
Normal file
35
inspector-vc/src/test/resources/ob30/simple-err-context.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"@context": [
|
||||||
|
"https://imsglobal.github.io/openbadges-specification/context.json",
|
||||||
|
"https://w3id.org/security/suites/ed25519-2020/v1"
|
||||||
|
],
|
||||||
|
"id": "http://example.edu/credentials/3732",
|
||||||
|
"type": [
|
||||||
|
"VerifiableCredential",
|
||||||
|
"OpenBadgeCredential"
|
||||||
|
],
|
||||||
|
"issuer": {
|
||||||
|
"id": "https://example.edu/issuers/565049",
|
||||||
|
"type": [
|
||||||
|
"Profile"
|
||||||
|
],
|
||||||
|
"name": "Example University"
|
||||||
|
},
|
||||||
|
"issuanceDate": "2010-01-01T00:00:00Z",
|
||||||
|
"name": "Example University Degree",
|
||||||
|
"credentialSubject": {
|
||||||
|
"id": "did:example:ebfeb1f712ebc6f1c276e12ec21",
|
||||||
|
"type": [
|
||||||
|
"AchievementSubject"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"proof": [
|
||||||
|
{
|
||||||
|
"type": "Ed25519Signature2020",
|
||||||
|
"created": "2022-06-28T16:28:36Z",
|
||||||
|
"verificationMethod": "did:key:z6MkkUD3J14nkYzn46QeuaVSnp7dF85QJKwKvJvfsjx79aXj",
|
||||||
|
"proofPurpose": "assertionMethod",
|
||||||
|
"proofValue": "z3MUt2ZuU8Byqivxh6GphEM65AFYyNaGYibm97xLTafM7uGufZQLKvJR8itZwxKskvtFM3CUty46v26DZidMNoQnM"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user