Defined dates fields depending on vcdm version

This commit is contained in:
Xavi Aracil 2024-03-21 17:23:44 +01:00
parent 169f5a608d
commit f600e5abeb

View File

@ -5,30 +5,35 @@ import static org.oneedtech.inspect.vc.VerifiableCredential.Type.ClrCredential;
import static org.oneedtech.inspect.vc.VerifiableCredential.Type.EndorsementCredential; import static org.oneedtech.inspect.vc.VerifiableCredential.Type.EndorsementCredential;
import static org.oneedtech.inspect.vc.VerifiableCredential.Type.VerifiablePresentation; import static org.oneedtech.inspect.vc.VerifiableCredential.Type.VerifiablePresentation;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableMap;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
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.MimeType; import org.oneedtech.inspect.util.resource.MimeType;
import org.oneedtech.inspect.util.resource.Resource; import org.oneedtech.inspect.util.resource.Resource;
import org.oneedtech.inspect.vc.util.JsonNodeUtil; import org.oneedtech.inspect.vc.util.JsonNodeUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.base.MoreObjects;
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
* and the extracted JSON data plus any other stuff Probes need. * extracted JSON data plus any other stuff Probes need.
*
* @author mgylling * @author mgylling
*/ */
public class VerifiableCredential extends Credential { public class VerifiableCredential extends Credential {
final VerifiableCredential.Type credentialType; final VerifiableCredential.Type credentialType;
protected VerifiableCredential(Resource resource, JsonNode data, String jwt, Map<CredentialEnum, SchemaKey> schemas, String issuedOnPropertyName, String expiresAtPropertyName) { protected VerifiableCredential(
Resource resource,
JsonNode data,
String jwt,
Map<CredentialEnum, SchemaKey> schemas,
String issuedOnPropertyName,
String expiresAtPropertyName) {
super(ID, resource, data, jwt, schemas, issuedOnPropertyName, expiresAtPropertyName); super(ID, resource, data, jwt, schemas, issuedOnPropertyName, expiresAtPropertyName);
JsonNode typeNode = jsonData.get("type"); JsonNode typeNode = jsonData.get("type");
@ -43,43 +48,67 @@ public class VerifiableCredential extends Credential {
return jwt == null ? ProofType.EMBEDDED : ProofType.EXTERNAL; return jwt == null ? ProofType.EMBEDDED : ProofType.EXTERNAL;
} }
private static final Map<CredentialEnum, SchemaKey> schemas = new ImmutableMap.Builder<CredentialEnum, SchemaKey>() private static final Map<CredentialEnum, SchemaKey> schemas =
.put(AchievementCredential, Catalog.OB_30_ACHIEVEMENTCREDENTIAL_JSON) new ImmutableMap.Builder<CredentialEnum, SchemaKey>()
.put(ClrCredential, Catalog.CLR_20_CLRCREDENTIAL_JSON) .put(AchievementCredential, Catalog.OB_30_ANY_ACHIEVEMENTCREDENTIAL_JSON)
.put(VerifiablePresentation, Catalog.CLR_20_CLRCREDENTIAL_JSON) .put(ClrCredential, Catalog.CLR_20_ANY_CLRCREDENTIAL_JSON)
.put(EndorsementCredential, Catalog.OB_30_ENDORSEMENTCREDENTIAL_JSON) .put(VerifiablePresentation, Catalog.CLR_20_ANY_CLRCREDENTIAL_JSON)
.put(EndorsementCredential, Catalog.OB_30_ANY_ENDORSEMENTCREDENTIAL_JSON)
.build(); .build();
private static final Map<Set<VerifiableCredential.Type>, List<String>> contextMap = new ImmutableMap.Builder<Set<VerifiableCredential.Type>, List<String>>() private static final Map<Set<VerifiableCredential.Type>, List<String>> contextMap =
.put(Set.of(Type.OpenBadgeCredential, AchievementCredential, EndorsementCredential), new ImmutableMap.Builder<Set<VerifiableCredential.Type>, List<String>>()
List.of("https://www.w3.org/2018/credentials/v1", .put(
Set.of(Type.OpenBadgeCredential, AchievementCredential, EndorsementCredential),
List.of(
"https://www.w3.org/ns/credentials/v2",
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"))
.put(
Set.of(ClrCredential),
List.of(
"https://www.w3.org/ns/credentials/v2",
"https://purl.imsglobal.org/spec/clr/v2p0/context-2.0.1.json",
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json"))
.build();
private static final Map<String, List<String>> contextAliasesMap =
new ImmutableMap.Builder<String, List<String>>()
.put(
"https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json",
List.of(
"https://purl.imsglobal.org/spec/ob/v3p0/context/ob_v3p0.jsonld",
"https://purl.imsglobal.org/spec/ob/v3p0/context.json")) "https://purl.imsglobal.org/spec/ob/v3p0/context.json"))
.put(Set.of(ClrCredential), .put(
List.of("https://www.w3.org/2018/credentials/v1", "https://purl.imsglobal.org/spec/clr/v2p0/context-2.0.1.json",
"https://purl.imsglobal.org/spec/clr/v2p0/context.json", List.of("https://purl.imsglobal.org/spec/clr/v2p0/context.json"))
"https://purl.imsglobal.org/spec/ob/v3p0/context.json")) .put(
"https://www.w3.org/ns/credentials/v2",
List.of("https://www.w3.org/2018/credentials/v1"))
.build(); .build();
private static final Map<String, List<String>> contextAliasesMap = new ImmutableMap.Builder<String, List<String>>() private static final Map<String, List<String>> contextVersioningPatternMap =
.put("https://purl.imsglobal.org/spec/ob/v3p0/context.json", new ImmutableMap.Builder<String, List<String>>()
List.of("https://purl.imsglobal.org/spec/ob/v3p0/context/ob_v3p0.jsonld")) .put(
.build(); "https://purl.imsglobal.org/spec/ob/v3p0/context-3.0.3.json",
List.of(
private static final Map<String, List<String>> contextVersioningPatternMap = new ImmutableMap.Builder<String, List<String>>() "https:\\/\\/purl\\.imsglobal\\.org\\/spec\\/ob\\/v3p0\\/context(-\\d+\\.\\d+\\.\\d+)*\\.json"))
.put("https://purl.imsglobal.org/spec/ob/v3p0/context.json", .put(
List.of("https:\\/\\/purl\\.imsglobal\\.org\\/spec\\/ob\\/v3p0\\/context(-\\d+\\.\\d+\\.\\d+)*\\.json")) "https://purl.imsglobal.org/spec/clr/v2p0/context-2.0.1.json",
.put("https://purl.imsglobal.org/spec/clr/v2p0/context.json", List.of(
List.of("https:\\/\\/purl\\.imsglobal\\.org\\/spec\\/clr\\/v2p0\\/context(-\\d+\\.\\d+\\.\\d+)*\\.json")) "https:\\/\\/purl\\.imsglobal\\.org\\/spec\\/clr\\/v2p0\\/context(-\\d+\\.\\d+\\.\\d+)*\\.json"))
.build(); .build();
public enum Type implements CredentialEnum { public enum Type implements CredentialEnum {
AchievementCredential(Collections.emptyList()), AchievementCredential(Collections.emptyList()),
OpenBadgeCredential(List.of("OpenBadgeCredential", "AchievementCredential")), //treated as an alias of AchievementCredential OpenBadgeCredential(
List.of(
"OpenBadgeCredential",
"AchievementCredential")), // treated as an alias of AchievementCredential
ClrCredential(List.of("ClrCredential")), ClrCredential(List.of("ClrCredential")),
EndorsementCredential(List.of("EndorsementCredential")), EndorsementCredential(List.of("EndorsementCredential")),
VerifiablePresentation(Collections.emptyList()), VerifiablePresentation(Collections.emptyList()),
VerifiableCredential(List.of("VerifiableCredential")), //this is an underspecifier in our context VerifiableCredential(
List.of("VerifiableCredential")), // this is an underspecifier in our context
Unknown(Collections.emptyList()); Unknown(Collections.emptyList());
private final List<String> allowedTypeValues; private final List<String> allowedTypeValues;
@ -88,17 +117,17 @@ public class VerifiableCredential extends Credential {
this.allowedTypeValues = allowedTypeValues; this.allowedTypeValues = allowedTypeValues;
} }
public static VerifiableCredential.Type valueOf (JsonNode typeNode) { public static VerifiableCredential.Type valueOf(JsonNode typeNode) {
if(typeNode != null) { if (typeNode != null) {
List<String> values = JsonNodeUtil.asStringList(typeNode); List<String> values = JsonNodeUtil.asStringList(typeNode);
for (String value : values) { for (String value : values) {
if(value.equals("AchievementCredential") || value.equals("OpenBadgeCredential")) { if (value.equals("AchievementCredential") || value.equals("OpenBadgeCredential")) {
return AchievementCredential; return AchievementCredential;
} else if(value.equals("ClrCredential")) { } else if (value.equals("ClrCredential")) {
return ClrCredential; return ClrCredential;
} else if(value.equals("VerifiablePresentation")) { } else if (value.equals("VerifiablePresentation")) {
return VerifiablePresentation; return VerifiablePresentation;
} else if(value.equals("EndorsementCredential")) { } else if (value.equals("EndorsementCredential")) {
return EndorsementCredential; return EndorsementCredential;
} }
} }
@ -120,18 +149,21 @@ public class VerifiableCredential extends Credential {
public boolean isAllowedTypeValuesRequired() { public boolean isAllowedTypeValuesRequired() {
return true; return true;
} }
@Override @Override
public List<String> getContextUris() { public List<String> getContextUris() {
return contextMap.get(contextMap.keySet() return contextMap.get(
.stream() contextMap.keySet().stream()
.filter(s->s.contains(this)) .filter(s -> s.contains(this))
.findFirst() .findFirst()
.orElseThrow(()-> new IllegalArgumentException(this.name() + " not recognized"))); .orElseThrow(() -> new IllegalArgumentException(this.name() + " not recognized")));
} }
@Override @Override
public Map<String, List<String>> getContextAliases() { public Map<String, List<String>> getContextAliases() {
return contextAliasesMap; return contextAliasesMap;
} }
@Override @Override
public Map<String, List<String>> getContextVersionPatterns() { public Map<String, List<String>> getContextVersionPatterns() {
return contextVersioningPatternMap; return contextVersioningPatternMap;
@ -154,13 +186,26 @@ public class VerifiableCredential extends Credential {
public static class Builder extends Credential.Builder<VerifiableCredential> { public static class Builder extends Credential.Builder<VerifiableCredential> {
@Override @Override
public VerifiableCredential build() { public VerifiableCredential build() {
return new VerifiableCredential(getResource(), getJsonData(), getJwt(), schemas, ISSUED_ON_PROPERTY_NAME, EXPIRES_AT_PROPERTY_NAME); boolean is2p0VC = JsonNodeUtil.asNodeList(getJsonData().get("@context"))
.stream()
.anyMatch(node -> node.isTextual() && node.asText().equals("https://www.w3.org/ns/credentials/v2"));
return new VerifiableCredential(
getResource(),
getJsonData(),
getJwt(),
schemas,
is2p0VC ? ISSUED_ON_PROPERTY_NAME_V20 : ISSUED_ON_PROPERTY_NAME_V11,
is2p0VC ? EXPIRES_AT_PROPERTY_NAME_V20 : EXPIRES_AT_PROPERTY_NAME_V11);
} }
} }
public static final String ID = VerifiableCredential.class.getCanonicalName(); public static final String ID = VerifiableCredential.class.getCanonicalName();
private static final String ISSUED_ON_PROPERTY_NAME = "issuanceDate"; private static final String ISSUED_ON_PROPERTY_NAME_V11 = "issuanceDate";
private static final String EXPIRES_AT_PROPERTY_NAME = "expirationDate"; private static final String ISSUED_ON_PROPERTY_NAME_V20 = "validFrom";
private static final String EXPIRES_AT_PROPERTY_NAME_V11 = "expirationDate";
private static final String EXPIRES_AT_PROPERTY_NAME_V20 = "validUntil";
public static final String JWT_NODE_NAME = "vc"; public static final String JWT_NODE_NAME = "vc";
public static final List<MimeType> REFRESH_SERVICE_MIME_TYPES = List.of(MimeType.JSON, MimeType.JSON_LD, MimeType.TEXT_PLAIN); public static final List<MimeType> REFRESH_SERVICE_MIME_TYPES =
List.of(MimeType.JSON, MimeType.JSON_LD, MimeType.TEXT_PLAIN);
} }