Added Assertion as a sibling of Credential

This commit is contained in:
Xavi Aracil 2022-11-22 18:03:06 +01:00
parent 21fe60f21b
commit 75d7deffda
3 changed files with 232 additions and 66 deletions

View File

@ -0,0 +1,110 @@
package org.oneedtech.inspect.vc;
import static org.oneedtech.inspect.util.code.Defensives.*;
import static org.oneedtech.inspect.util.resource.ResourceType.*;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import org.oneedtech.inspect.core.probe.GeneratedObject;
import org.oneedtech.inspect.schema.SchemaKey;
import org.oneedtech.inspect.util.resource.Resource;
import org.oneedtech.inspect.util.resource.ResourceType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.base.MoreObjects;
/**
* Base credential class for OB 2.0 Assertions and OB 3.0 and CLR 2.0 Credentials.
* This contains e.g. the origin resource and the extracted JSON data.
* @author xaracil
*/
public abstract class AbstractBaseCredential extends GeneratedObject {
final Resource resource;
final JsonNode jsonData;
final String jwt;
final Map<String, SchemaKey> schemas;
protected AbstractBaseCredential(String id, Resource resource, JsonNode data, String jwt, Map<String, SchemaKey> schemas) {
super(id, GeneratedObject.Type.INTERNAL);
this.resource = checkNotNull(resource);
this.jsonData = checkNotNull(data);
this.jwt = jwt; //may be null
this.schemas = schemas;
checkTrue(RECOGNIZED_PAYLOAD_TYPES.contains(resource.getType()));
}
public Resource getResource() {
return resource;
}
public JsonNode getJson() {
return jsonData;
}
public Optional<String> getJwt() {
return Optional.ofNullable(jwt);
}
/**
* Get the canonical schema for this credential if such exists.
*/
public Optional<SchemaKey> getSchemaKey() {
return Optional.ofNullable(schemas.get(getCredentialType()));
}
public abstract String getCredentialType();
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("resource", resource.getID())
.add("resourceType", resource.getType())
.add("json", jsonData)
.add("jwt", jwt)
.toString();
}
public static final List<ResourceType> RECOGNIZED_PAYLOAD_TYPES = List.of(SVG, PNG, JSON, JWT);
public static final String CREDENTIAL_KEY = "CREDENTIAL_KEY";
public abstract static class Builder<B extends AbstractBaseCredential> {
private Resource resource;
private JsonNode jsonData;
private String jwt;
public abstract B build();
public Builder<B> resource(Resource resource) {
this.resource = resource;
return this;
}
public Builder<B> jsonData(JsonNode node) {
this.jsonData = node;
return this;
}
public Builder<B> jwt(String jwt) {
this.jwt = jwt;
return this;
}
protected Resource getResource() {
return resource;
}
protected JsonNode getJsonData() {
return jsonData;
}
protected String getJwt() {
return jwt;
}
}
}

View File

@ -0,0 +1,81 @@
package org.oneedtech.inspect.vc;
import java.util.Iterator;
import java.util.Map;
import java.util.stream.Collectors;
import org.oneedtech.inspect.schema.Catalog;
import org.oneedtech.inspect.schema.SchemaKey;
import org.oneedtech.inspect.util.resource.Resource;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableMap;
/**
* A wrapper object for a OB 2.0 assertion. This contains e.g. the origin resource
* and the extracted JSON data plus any other stuff Probes need.
* @author xaracil
*/
public class Assertion extends AbstractBaseCredential {
final Assertion.Type assertionType;
protected Assertion(Resource resource, JsonNode data, String jwt, Map<String, SchemaKey> schemas) {
super(ID, resource, data, jwt, schemas);
ArrayNode typeNode = (ArrayNode)jsonData.get("type");
this.assertionType = Assertion.Type.valueOf(typeNode);
}
@Override
public String getCredentialType() {
return assertionType.toString();
}
@Override
public String toString() {
return MoreObjects.toStringHelper(this)
.add("super", super.toString())
.add("assertionType", assertionType)
.toString();
}
private static final Map<Assertion.Type, SchemaKey> schemas = new ImmutableMap.Builder<Assertion.Type, SchemaKey>()
.put(Type.Assertion, Catalog.OB_21_ASSERTION_JSON)
.build();
public static class Builder extends AbstractBaseCredential.Builder<Assertion> {
@Override
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.entrySet().stream().collect(Collectors.toMap(
entry -> entry.getKey().toString(),
entry -> entry.getValue())));
}
}
public enum Type {
Assertion,
Unknown;
public static Assertion.Type valueOf (ArrayNode typeArray) {
if(typeArray != null) {
Iterator<JsonNode> iter = typeArray.iterator();
while(iter.hasNext()) {
String value = iter.next().asText();
if(value.equals("Assertion")) {
return Assertion;
}
}
}
return Unknown;
}
}
public static final String ID = Assertion.class.getCanonicalName();
}

View File

@ -1,19 +1,17 @@
package org.oneedtech.inspect.vc; package org.oneedtech.inspect.vc;
import static org.oneedtech.inspect.util.code.Defensives.*; import static org.oneedtech.inspect.vc.Credential.Type.AchievementCredential;
import static org.oneedtech.inspect.util.resource.ResourceType.*; import static org.oneedtech.inspect.vc.Credential.Type.ClrCredential;
import static org.oneedtech.inspect.vc.Credential.Type.*; import static org.oneedtech.inspect.vc.Credential.Type.EndorsementCredential;
import static org.oneedtech.inspect.vc.Credential.Type.VerifiablePresentation;
import java.util.Iterator; import java.util.Iterator;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.stream.Collectors;
import org.oneedtech.inspect.core.probe.GeneratedObject;
import org.oneedtech.inspect.schema.Catalog; import org.oneedtech.inspect.schema.Catalog;
import org.oneedtech.inspect.schema.SchemaKey; import org.oneedtech.inspect.schema.SchemaKey;
import org.oneedtech.inspect.util.resource.Resource; import org.oneedtech.inspect.util.resource.Resource;
import org.oneedtech.inspect.util.resource.ResourceType;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ArrayNode;
@ -21,76 +19,45 @@ import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMap;
/** /**
* A wrapper object for a verifiable credential. This contains e.g. the origin resource * A wrapper object for a verifiable credential. This contains e.g. the origin resource
* and the extracted JSON data plus any other stuff Probes need. * and the extracted JSON data plus any other stuff Probes need.
* @author mgylling * @author mgylling
*/ */
public class Credential extends GeneratedObject { public class Credential extends AbstractBaseCredential {
final Resource resource;
final JsonNode jsonData;
final Credential.Type credentialType; final Credential.Type credentialType;
final String jwt;
protected Credential(Resource resource, JsonNode data, String jwt, Map<String, SchemaKey> schemas) {
public Credential(Resource resource, JsonNode data, String jwt) { super(ID, resource, data, jwt, schemas);
super(ID, GeneratedObject.Type.INTERNAL);
this.resource = checkNotNull(resource);
this.jsonData = checkNotNull(data);
this.jwt = jwt; //may be null
checkTrue(RECOGNIZED_PAYLOAD_TYPES.contains(resource.getType()));
ArrayNode typeNode = (ArrayNode)jsonData.get("type"); ArrayNode typeNode = (ArrayNode)jsonData.get("type");
this.credentialType = Credential.Type.valueOf(typeNode); this.credentialType = Credential.Type.valueOf(typeNode);
} }
public Credential(Resource resource, JsonNode data) { public String getCredentialType() {
this(resource, data, null); return credentialType.toString();
}
public Resource getResource() {
return resource;
}
public JsonNode getJson() {
return jsonData;
} }
public Credential.Type getCredentialType() {
return credentialType;
}
public Optional<String> getJwt() {
return Optional.ofNullable(jwt);
}
public ProofType getProofType() { public ProofType getProofType() {
return jwt == null ? ProofType.EMBEDDED : ProofType.EXTERNAL; return jwt == null ? ProofType.EMBEDDED : ProofType.EXTERNAL;
} }
private static final Map<Credential.Type, SchemaKey> schemas = new ImmutableMap.Builder<Credential.Type, SchemaKey>() private static final Map<Credential.Type, SchemaKey> schemas = new ImmutableMap.Builder<Credential.Type, SchemaKey>()
.put(AchievementCredential, Catalog.OB_30_ACHIEVEMENTCREDENTIAL_JSON) .put(AchievementCredential, Catalog.OB_30_ACHIEVEMENTCREDENTIAL_JSON)
.put(ClrCredential, Catalog.CLR_20_CLRCREDENTIAL_JSON) .put(ClrCredential, Catalog.CLR_20_CLRCREDENTIAL_JSON)
.put(VerifiablePresentation, Catalog.CLR_20_CLRCREDENTIAL_JSON) .put(VerifiablePresentation, Catalog.CLR_20_CLRCREDENTIAL_JSON)
.put(EndorsementCredential, Catalog.OB_30_ENDORSEMENTCREDENTIAL_JSON) .put(EndorsementCredential, Catalog.OB_30_ENDORSEMENTCREDENTIAL_JSON)
.build(); .build();
/**
* Get the canonical schema for this credential if such exists.
*/
public Optional<SchemaKey> getSchemaKey() {
return Optional.ofNullable(schemas.get(credentialType));
}
public enum Type { public enum Type {
AchievementCredential, AchievementCredential,
OpenBadgeCredential, //treated as an alias of AchievementCredential OpenBadgeCredential, //treated as an alias of AchievementCredential
ClrCredential, ClrCredential,
EndorsementCredential, EndorsementCredential,
VerifiablePresentation, VerifiablePresentation,
VerifiableCredential, //this is an underspecifier in our context VerifiableCredential, //this is an underspecifier in our context
Unknown; Unknown;
public static Credential.Type valueOf (ArrayNode typeArray) { public static Credential.Type valueOf (ArrayNode typeArray) {
if(typeArray != null) { if(typeArray != null) {
Iterator<JsonNode> iter = typeArray.iterator(); Iterator<JsonNode> iter = typeArray.iterator();
@ -110,24 +77,32 @@ public class Credential extends GeneratedObject {
return Unknown; return Unknown;
} }
} }
public enum ProofType { public enum ProofType {
EXTERNAL, EXTERNAL,
EMBEDDED EMBEDDED
} }
@Override @Override
public String toString() { public String toString() {
return MoreObjects.toStringHelper(this) return MoreObjects.toStringHelper(this)
.add("resource", resource.getID()) .add("super", super.toString())
.add("resourceType", resource.getType())
.add("credentialType", credentialType) .add("credentialType", credentialType)
.add("json", jsonData)
.toString(); .toString();
} }
public static class Builder extends AbstractBaseCredential.Builder<Credential> {
@Override
public Credential 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 Credential(getResource(), getJsonData(), getJwt(),
schemas.entrySet().stream().collect(Collectors.toMap(
entry -> entry.getKey().toString(),
entry -> entry.getValue())));
}
}
public static final String ID = Credential.class.getCanonicalName(); public static final String ID = Credential.class.getCanonicalName();
public static final List<ResourceType> RECOGNIZED_PAYLOAD_TYPES = List.of(SVG, PNG, JSON, JWT);
public static final String CREDENTIAL_KEY = "CREDENTIAL_KEY";
} }