Set new context keys and use the new credentials builder
This commit is contained in:
parent
6c9485cf02
commit
e56739370f
@ -5,7 +5,7 @@ import static org.oneedtech.inspect.core.Inspector.Behavior.RESET_CACHES_ON_RUN;
|
|||||||
import static org.oneedtech.inspect.core.report.ReportUtil.onProbeException;
|
import static org.oneedtech.inspect.core.report.ReportUtil.onProbeException;
|
||||||
import static org.oneedtech.inspect.util.code.Defensives.*;
|
import static org.oneedtech.inspect.util.code.Defensives.*;
|
||||||
import static org.oneedtech.inspect.util.json.ObjectMapperCache.Config.DEFAULT;
|
import static org.oneedtech.inspect.util.json.ObjectMapperCache.Config.DEFAULT;
|
||||||
import static org.oneedtech.inspect.vc.Credential.CREDENTIAL_KEY;
|
import static org.oneedtech.inspect.vc.AbstractBaseCredential.CREDENTIAL_KEY;
|
||||||
import static org.oneedtech.inspect.vc.Credential.ProofType.EXTERNAL;
|
import static org.oneedtech.inspect.vc.Credential.ProofType.EXTERNAL;
|
||||||
import static org.oneedtech.inspect.vc.payload.PayloadParser.fromJwt;
|
import static org.oneedtech.inspect.vc.payload.PayloadParser.fromJwt;
|
||||||
import static org.oneedtech.inspect.vc.util.JsonNodeUtil.asNodeList;
|
import static org.oneedtech.inspect.vc.util.JsonNodeUtil.asNodeList;
|
||||||
@ -35,6 +35,8 @@ 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.Credential.Type;
|
||||||
|
import org.oneedtech.inspect.vc.payload.PngParser;
|
||||||
|
import org.oneedtech.inspect.vc.payload.SvgParser;
|
||||||
import org.oneedtech.inspect.vc.probe.ContextPropertyProbe;
|
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.CredentialSubjectProbe;
|
import org.oneedtech.inspect.vc.probe.CredentialSubjectProbe;
|
||||||
@ -57,111 +59,118 @@ import com.google.common.collect.ImmutableList;
|
|||||||
*/
|
*/
|
||||||
public class OB30Inspector extends VCInspector implements SubInspector {
|
public class OB30Inspector extends VCInspector implements SubInspector {
|
||||||
protected final List<Probe<Credential>> userProbes;
|
protected final List<Probe<Credential>> userProbes;
|
||||||
|
|
||||||
protected OB30Inspector(OB30Inspector.Builder builder) {
|
protected OB30Inspector(OB30Inspector.Builder builder) {
|
||||||
super(builder);
|
super(builder);
|
||||||
this.userProbes = ImmutableList.copyOf(builder.probes);
|
this.userProbes = ImmutableList.copyOf(builder.probes);
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://docs.google.com/document/d/1_imUl2K-5tMib0AUxwA9CWb0Ap1b3qif0sXydih68J0/edit#
|
//https://docs.google.com/document/d/1_imUl2K-5tMib0AUxwA9CWb0Ap1b3qif0sXydih68J0/edit#
|
||||||
//https://imsglobal.github.io/openbadges-specification/ob_v3p0.html#verificaton-and-validation
|
//https://imsglobal.github.io/openbadges-specification/ob_v3p0.html#verificaton-and-validation
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This inspector supports both standalone openbadge verification, as well as verification of
|
* This inspector supports both standalone openbadge verification, as well as verification of
|
||||||
* AchievementCredentials embedded in e.g. CLR.
|
* AchievementCredentials embedded in e.g. CLR.
|
||||||
*
|
*
|
||||||
* When verifying a standalone AchievementCredential, call the run(Resource) method. When verifying
|
* When verifying a standalone AchievementCredential, call the run(Resource) method. When verifying
|
||||||
* an embedded AchievementCredential, call the run(Resource, Map) method.
|
* an embedded AchievementCredential, call the run(Resource, Map) method.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Report run(Resource resource) {
|
public Report run(Resource resource) {
|
||||||
super.check(resource); //TODO because URIs, this should be a fetch and cache
|
super.check(resource); //TODO because URIs, this should be a fetch and cache
|
||||||
|
|
||||||
if(getBehavior(RESET_CACHES_ON_RUN) == TRUE) {
|
if(getBehavior(RESET_CACHES_ON_RUN) == TRUE) {
|
||||||
JsonSchemaCache.reset();
|
JsonSchemaCache.reset();
|
||||||
CachingDocumentLoader.reset();
|
CachingDocumentLoader.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectMapper mapper = ObjectMapperCache.get(DEFAULT);
|
ObjectMapper mapper = ObjectMapperCache.get(DEFAULT);
|
||||||
JsonPathEvaluator jsonPath = new JsonPathEvaluator(mapper);
|
JsonPathEvaluator jsonPath = new JsonPathEvaluator(mapper);
|
||||||
|
|
||||||
RunContext ctx = new RunContext.Builder()
|
RunContext ctx = new RunContext.Builder()
|
||||||
.put(this)
|
.put(this)
|
||||||
.put(resource)
|
.put(resource)
|
||||||
.put(Key.JACKSON_OBJECTMAPPER, mapper)
|
.put(Key.JACKSON_OBJECTMAPPER, mapper)
|
||||||
.put(Key.JSONPATH_EVALUATOR, jsonPath)
|
.put(Key.JSONPATH_EVALUATOR, jsonPath)
|
||||||
.build();
|
.put(Key.GENERATED_OBJECT_BUILDER, new Credential.Builder())
|
||||||
|
.put(Key.PNG_CREDENTIAL_KEY, PngParser.Keys.OB30)
|
||||||
|
.put(Key.SVG_CREDENTIAL_QNAME, SvgParser.QNames.OB30)
|
||||||
|
.build();
|
||||||
|
|
||||||
List<ReportItems> accumulator = new ArrayList<>();
|
List<ReportItems> accumulator = new ArrayList<>();
|
||||||
int probeCount = 0;
|
int probeCount = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
//detect type (png, svg, json, jwt) and extract json data
|
//detect type (png, svg, json, jwt) and extract json data
|
||||||
probeCount++;
|
probeCount++;
|
||||||
accumulator.add(new CredentialParseProbe().run(resource, ctx));
|
accumulator.add(new CredentialParseProbe().run(resource, ctx));
|
||||||
if(broken(accumulator, true)) return abort(ctx, accumulator, probeCount);
|
if(broken(accumulator, true)) return abort(ctx, accumulator, probeCount);
|
||||||
|
|
||||||
//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 ob = ctx.getGeneratedObject(Credential.ID);
|
Credential ob = ctx.getGeneratedObject(Credential.ID);
|
||||||
|
|
||||||
//call the subinspector method of this
|
//call the subinspector method of this
|
||||||
Report subReport = this.run(resource, Map.of(Credential.CREDENTIAL_KEY, ob));
|
Report subReport = this.run(resource, Map.of(Credential.CREDENTIAL_KEY, ob));
|
||||||
probeCount += subReport.getSummary().getTotalRun();
|
probeCount += subReport.getSummary().getTotalRun();
|
||||||
accumulator.add(subReport);
|
accumulator.add(subReport);
|
||||||
|
|
||||||
//finally, run any user-added probes
|
//finally, run any user-added probes
|
||||||
for(Probe<Credential> probe : userProbes) {
|
for(Probe<Credential> probe : userProbes) {
|
||||||
probeCount++;
|
probeCount++;
|
||||||
accumulator.add(probe.run(ob, ctx));
|
accumulator.add(probe.run(ob, ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
accumulator.add(onProbeException(Probe.ID.NO_UNCAUGHT_EXCEPTIONS, resource, e));
|
accumulator.add(onProbeException(Probe.ID.NO_UNCAUGHT_EXCEPTIONS, resource, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Report(ctx, new ReportItems(accumulator), probeCount);
|
return new Report(ctx, new ReportItems(accumulator), probeCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Report run(Resource resource, Map<String, GeneratedObject> parentObjects) {
|
public Report run(Resource resource, Map<String, GeneratedObject> parentObjects) {
|
||||||
|
|
||||||
Credential ob = checkNotNull((Credential)parentObjects.get(CREDENTIAL_KEY));
|
Credential ob = checkNotNull((Credential)parentObjects.get(CREDENTIAL_KEY));
|
||||||
|
|
||||||
ObjectMapper mapper = ObjectMapperCache.get(DEFAULT);
|
ObjectMapper mapper = ObjectMapperCache.get(DEFAULT);
|
||||||
JsonPathEvaluator jsonPath = new JsonPathEvaluator(mapper);
|
JsonPathEvaluator jsonPath = new JsonPathEvaluator(mapper);
|
||||||
|
Credential.Builder credentialBuilder = new Credential.Builder();
|
||||||
RunContext ctx = new RunContext.Builder()
|
RunContext ctx = new RunContext.Builder()
|
||||||
.put(this)
|
.put(this)
|
||||||
.put(resource)
|
.put(resource)
|
||||||
.put(Key.JACKSON_OBJECTMAPPER, mapper)
|
.put(Key.JACKSON_OBJECTMAPPER, mapper)
|
||||||
.put(Key.JSONPATH_EVALUATOR, jsonPath)
|
.put(Key.JSONPATH_EVALUATOR, jsonPath)
|
||||||
|
.put(Key.GENERATED_OBJECT_BUILDER, credentialBuilder)
|
||||||
|
.put(Key.PNG_CREDENTIAL_KEY, PngParser.Keys.OB30)
|
||||||
|
.put(Key.SVG_CREDENTIAL_QNAME, SvgParser.QNames.OB30)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
List<ReportItems> accumulator = new ArrayList<>();
|
List<ReportItems> accumulator = new ArrayList<>();
|
||||||
int probeCount = 0;
|
int probeCount = 0;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
||||||
//context and type properties
|
//context and type properties
|
||||||
Credential.Type type = Type.OpenBadgeCredential;
|
Credential.Type type = Type.OpenBadgeCredential;
|
||||||
for(Probe<JsonNode> probe : List.of(new ContextPropertyProbe(type), new TypePropertyProbe(type))) {
|
for(Probe<JsonNode> probe : List.of(new ContextPropertyProbe(type), new TypePropertyProbe(type))) {
|
||||||
probeCount++;
|
probeCount++;
|
||||||
accumulator.add(probe.run(ob.getJson(), ctx));
|
accumulator.add(probe.run(ob.getJson(), ctx));
|
||||||
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
//canonical schema and inline schemata
|
//canonical schema and inline schemata
|
||||||
SchemaKey schema = ob.getSchemaKey().orElseThrow();
|
SchemaKey schema = ob.getSchemaKey().orElseThrow();
|
||||||
for(Probe<JsonNode> probe : List.of(new JsonSchemaProbe(schema), new InlineJsonSchemaProbe(schema))) {
|
for(Probe<JsonNode> probe : List.of(new JsonSchemaProbe(schema), new InlineJsonSchemaProbe(schema))) {
|
||||||
probeCount++;
|
probeCount++;
|
||||||
accumulator.add(probe.run(ob.getJson(), ctx));
|
accumulator.add(probe.run(ob.getJson(), ctx));
|
||||||
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
//credentialSubject
|
//credentialSubject
|
||||||
probeCount++;
|
probeCount++;
|
||||||
accumulator.add(new CredentialSubjectProbe().run(ob.getJson(), ctx));
|
accumulator.add(new CredentialSubjectProbe().run(ob.getJson(), ctx));
|
||||||
|
|
||||||
//signatures, proofs
|
//signatures, proofs
|
||||||
probeCount++;
|
probeCount++;
|
||||||
if(ob.getProofType() == EXTERNAL){
|
if(ob.getProofType() == EXTERNAL){
|
||||||
@ -169,57 +178,57 @@ public class OB30Inspector extends VCInspector implements SubInspector {
|
|||||||
accumulator.add(new ExternalProofProbe().run(ob, ctx));
|
accumulator.add(new ExternalProofProbe().run(ob, ctx));
|
||||||
} else {
|
} else {
|
||||||
//The credential not contained in a jwt, must have an internal proof.
|
//The credential not contained in a jwt, must have an internal proof.
|
||||||
accumulator.add(new EmbeddedProofProbe().run(ob, ctx));
|
accumulator.add(new EmbeddedProofProbe().run(ob, ctx));
|
||||||
}
|
}
|
||||||
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
||||||
|
|
||||||
//check refresh service if we are not already refreshed
|
//check refresh service if we are not already refreshed
|
||||||
probeCount++;
|
probeCount++;
|
||||||
if(resource.getContext().get(REFRESHED) != TRUE) {
|
if(resource.getContext().get(REFRESHED) != TRUE) {
|
||||||
Optional<String> newID = checkRefreshService(ob, ctx);
|
Optional<String> newID = checkRefreshService(ob, ctx);
|
||||||
if(newID.isPresent()) {
|
if(newID.isPresent()) {
|
||||||
return this.run(
|
return this.run(
|
||||||
new UriResource(new URI(newID.get()))
|
new UriResource(new URI(newID.get()))
|
||||||
.setContext(new ResourceContext(REFRESHED, TRUE)));
|
.setContext(new ResourceContext(REFRESHED, TRUE)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//revocation, expiration and issuance
|
//revocation, expiration and issuance
|
||||||
for(Probe<Credential> probe : List.of(new RevocationListProbe(),
|
for(Probe<Credential> probe : List.of(new RevocationListProbe(),
|
||||||
new ExpirationProbe(), new IssuanceProbe())) {
|
new ExpirationProbe(), new IssuanceProbe())) {
|
||||||
probeCount++;
|
probeCount++;
|
||||||
accumulator.add(probe.run(ob, ctx));
|
accumulator.add(probe.run(ob, ctx));
|
||||||
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
if(broken(accumulator)) return abort(ctx, accumulator, probeCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
//embedded endorsements
|
//embedded endorsements
|
||||||
EndorsementInspector endorsementInspector = new EndorsementInspector.Builder().build();
|
EndorsementInspector endorsementInspector = new EndorsementInspector.Builder().build();
|
||||||
|
|
||||||
List<JsonNode> endorsements = asNodeList(ob.getJson(), "$..endorsement", jsonPath);
|
List<JsonNode> endorsements = asNodeList(ob.getJson(), "$..endorsement", jsonPath);
|
||||||
for(JsonNode node : endorsements) {
|
for(JsonNode node : endorsements) {
|
||||||
probeCount++;
|
probeCount++;
|
||||||
Credential endorsement = new Credential(resource, node);
|
Credential endorsement = credentialBuilder.resource(resource).jsonData(node).build();
|
||||||
accumulator.add(endorsementInspector.run(resource, Map.of(CREDENTIAL_KEY, endorsement)));
|
accumulator.add(endorsementInspector.run(resource, Map.of(CREDENTIAL_KEY, endorsement)));
|
||||||
}
|
}
|
||||||
|
|
||||||
//embedded jwt endorsements
|
//embedded jwt endorsements
|
||||||
endorsements = asNodeList(ob.getJson(), "$..endorsementJwt", jsonPath);
|
endorsements = asNodeList(ob.getJson(), "$..endorsementJwt", jsonPath);
|
||||||
for(JsonNode node : endorsements) {
|
for(JsonNode node : endorsements) {
|
||||||
probeCount++;
|
probeCount++;
|
||||||
String jwt = node.asText();
|
String jwt = node.asText();
|
||||||
JsonNode vcNode = fromJwt(jwt, ctx);
|
JsonNode vcNode = fromJwt(jwt, ctx);
|
||||||
Credential endorsement = new Credential(resource, vcNode, jwt);
|
Credential endorsement = credentialBuilder.resource(resource).jsonData(node).jwt(jwt).build();
|
||||||
accumulator.add(endorsementInspector.run(resource, Map.of(CREDENTIAL_KEY, endorsement)));
|
accumulator.add(endorsementInspector.run(resource, Map.of(CREDENTIAL_KEY, endorsement)));
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
accumulator.add(onProbeException(Probe.ID.NO_UNCAUGHT_EXCEPTIONS, resource, e));
|
accumulator.add(onProbeException(Probe.ID.NO_UNCAUGHT_EXCEPTIONS, resource, e));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Report(ctx, new ReportItems(accumulator), probeCount);
|
return new Report(ctx, new ReportItems(accumulator), probeCount);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Builder extends VCInspector.Builder<OB30Inspector.Builder> {
|
public static class Builder extends VCInspector.Builder<OB30Inspector.Builder> {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
@ -228,5 +237,5 @@ public class OB30Inspector extends VCInspector implements SubInspector {
|
|||||||
set(ResourceType.OPENBADGE);
|
set(ResourceType.OPENBADGE);
|
||||||
return new OB30Inspector(this);
|
return new OB30Inspector(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user