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.context.ResourceContext;
|
||||
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.ExpirationVerifierProbe;
|
||||
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
|
||||
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)
|
||||
|
||||
//type property
|
||||
probeCount++;
|
||||
accumulator.add(new TypePropertyProbe(OpenBadgeCredential).run(crd.getJson(), ctx));
|
||||
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
||||
//context and type properties
|
||||
Credential.Type type = Type.OpenBadgeCredential;
|
||||
for(Probe<JsonNode> probe : List.of(new ContextPropertyProbe(type), new TypePropertyProbe(type))) {
|
||||
probeCount++;
|
||||
accumulator.add(probe.run(crd.getJson(), ctx));
|
||||
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
||||
}
|
||||
|
||||
//canonical schema and inline schemata
|
||||
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.report.Report;
|
||||
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.InlineJsonSchemaProbe;
|
||||
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
|
||||
void testSimpleJsonSchemaError() throws Exception {
|
||||
//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_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_ERR_CONTEXT = new Sample("ob30/simple-err-context.json", false);
|
||||
}
|
||||
public static final class PNG {
|
||||
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