Effective:
@@ -111,14 +121,15 @@ import { isExpired, toTranslationFormat } from "@/utils/entity";
},
})
export default class CredentialItem extends Vue {
- @Prop({}) cred!: ICredentialDisplayType;
+ @Prop({}) credential!: ICredentialDisplayType;
@Prop({ default: "" }) entityType!: string;
@Prop({ default: "" }) authority!: string;
@Prop({ default: "" }) authorityLink!: string;
@Prop({ default: "" }) effectiveDate!: string;
+ @Prop({ default: "" }) credentialId!: number;
@Prop({ default: false }) expired!: boolean;
- @Prop({ default: "" }) credId!: number;
+ @Prop({ default: false }) revoked!: boolean;
@Prop({ default: false }) disableDefaultHeader!: boolean;
@Prop({ default: false }) timeline!: boolean;
@@ -131,25 +142,15 @@ export default class CredentialItem extends Vue {
toTranslationFormate = toTranslationFormat;
$translate = $translate;
- get getAuthorityLink(): string | URL {
- return this.cred ? this.cred.authorityLink : this.authorityLink;
- }
-
get getAuthority(): string {
- return this.cred ? this.cred.authority : this.authority;
+ return this.credential ? this.credential.authority : this.authority;
}
- get getCredRevoked(): boolean {
- return this.cred
- ? this.cred.revoked || !!this.isExpired(this.cred.attributes)
- : this.expired;
- }
-
- get getCredId(): number {
- return this.cred ? this.cred.id : this.credId;
+ get getAuthorityLink(): string | URL {
+ return this.credential ? this.credential.authorityLink : this.authorityLink;
}
- get sourceId(): string {
+ get topicSourceId(): string {
const { sourceId } = this.$route.params;
return sourceId;
}
@@ -160,67 +161,46 @@ export default class CredentialItem extends Vue {
}
get topicName(): string | undefined {
- if (!this.cred) {
+ if (!this.credential) {
return undefined;
}
- let ret = this.cred.value as string | undefined;
- if (this.cred.type !== "entity_name") {
+ let ret = this.credential.value as string | undefined;
+ if (this.credential.type !== "entity_name") {
ret = this.selectedTopic.names[0]?.text;
}
return ret;
}
- getClaimLabel(
- id: number,
- claimLabel: string | undefined
- ): string | undefined {
- const credentialType = selectFirstAttrItem(
- { key: "id", value: id },
- this.credentialTypes
- );
- // TODO: Eventually this should be a translation from OCA
- if (credentialType?.format === "vc_di") {
- return claimLabel;
- } else if (credentialType && claimLabel) {
- return credentialType?.claim_labels?.[claimLabel]?.[i18n.locale];
- }
+ get getCredentialId(): number {
+ return this.credential ? this.credential.id : this.credentialId;
}
- translateValue(
- accessor: string,
- val: string,
- entityType: string
- ): string | TranslateResult {
- // need entity type to properly translate due to LEAR entries
- const res = $translate(
- toTranslationFormat(accessor + "." + val, entityType)
- );
- if (res != toTranslationFormat(accessor + "." + val, entityType)) {
- return res;
- }
- return val;
+ get getCredentialRevoked(): boolean {
+ return this.credential
+ ? this.credential.revoked || !!this.isExpired(this.credential.attributes)
+ : this.expired;
}
- get credTitle(): Record
| undefined {
- if (!this.cred) {
+ get getCredentialTitle(): Record | undefined {
+ if (!this.credential) {
return undefined;
}
let retval: { [index: string]: string | undefined } = {};
- const claimLabel = this.getClaimLabel(
- this.cred.credential_type_id,
- this.cred.credential_title
+ const claimLabel = this.claimLabelFromId(
+ this.credential.credential_type_id,
+ this.credential.credential_title
);
- const default_title = this.cred.rel_id
- ? { "Relationship description": this.cred.rel_id as string }
- : { "Registration number": this.sourceId };
+ const default_title = this.credential.rel_id
+ ? { "Relationship description": this.credential.rel_id as string }
+ : { "Registration number": this.topicSourceId };
if (claimLabel === undefined) {
retval = default_title;
} else {
let value = selectFirstAttrItem(
- { key: "type", value: this.cred.credential_title },
- this.cred.attributes
+ { key: "type", value: this.credential.credential_title },
+ this.credential.attributes
);
if (value?.format === "datetime") {
value.value = value.value as string;
@@ -232,7 +212,9 @@ export default class CredentialItem extends Vue {
retval = default_title;
}
}
- let accessor = this.cred.credential_title ? this.cred.credential_title : "";
+ let accessor = this.credential.credential_title
+ ? this.credential.credential_title
+ : "";
return {
key: Object.keys(retval)[0],
value: retval[Object.keys(retval)[0]] as string,
@@ -240,22 +222,22 @@ export default class CredentialItem extends Vue {
};
}
- get highlightedAttr(): Record[] | undefined {
- if (!this.cred) {
+ get highlightedAttributes(): Record[] | undefined {
+ if (!this.credential) {
return undefined;
}
let retval: Record[] = [];
- if (this.cred.highlighted_attributes) {
- this.cred.highlighted_attributes.forEach((accessor) => {
- const attrLabel = this.getClaimLabel(
- this.cred.credential_type_id,
+ if (this.credential.highlighted_attributes) {
+ this.credential.highlighted_attributes.forEach((accessor) => {
+ const attrLabel = this.claimLabelFromId(
+ this.credential.credential_type_id,
accessor
);
let attrValue = "";
if (attrLabel) {
const match = selectFirstAttrItem(
{ key: "type", value: accessor },
- this.cred.attributes
+ this.credential.attributes
);
if (match?.format === "datetime") {
attrValue = dateFilter(match.value as string) as string;
@@ -275,6 +257,37 @@ export default class CredentialItem extends Vue {
}
return retval;
}
+
+ claimLabelFromId(
+ id: number,
+ claimLabel: string | undefined
+ ): string | undefined {
+ const credentialType = selectFirstAttrItem(
+ { key: "id", value: id },
+ this.credentialTypes
+ );
+ // TODO: Eventually this should be a translation from OCA
+ if (credentialType?.format === "vc_di") {
+ return claimLabel;
+ } else if (credentialType && claimLabel) {
+ return credentialType?.claim_labels?.[claimLabel]?.[i18n.locale];
+ }
+ }
+
+ translateValue(
+ accessor: string,
+ val: string,
+ entityType: string
+ ): string | TranslateResult {
+ // need entity type to properly translate due to LEAR entries
+ const res = $translate(
+ toTranslationFormat(accessor + "." + val, entityType)
+ );
+ if (res != toTranslationFormat(accessor + "." + val, entityType)) {
+ return res;
+ }
+ return val;
+ }
}
diff --git a/src/components/entity/EntityResult.vue b/src/components/entity/EntityResult.vue
index f384ced..9e4fafa 100644
--- a/src/components/entity/EntityResult.vue
+++ b/src/components/entity/EntityResult.vue
@@ -389,7 +389,7 @@
>
diff --git a/src/components/entity/credentialDetail/CredentialDetail.vue b/src/components/entity/credentialDetail/CredentialDetail.vue
index 9ce6f1e..e12738e 100644
--- a/src/components/entity/credentialDetail/CredentialDetail.vue
+++ b/src/components/entity/credentialDetail/CredentialDetail.vue
@@ -1,11 +1,11 @@
-
-
+
+
- {{ errorWording }}
+ {{ errorMessage }}
@@ -14,26 +14,25 @@
- {{
+ {{
mdiShieldCheckOutline
}}
- {{ `${currCredTypeDesc} credential` }} verified claims
+ {{ `${credentialTypeDescription} credential` }} verified claims
-
- {{ `Cryptographically verified ${currDate}` }}
+
+ {{ `Cryptographically verified ${now}` }}
- Issued: {{ currCredIssuedDate | formatDate }} • Effective:
- {{ currCredEffDate | formatDate }}
-
- - {{ credRevokedDate | formatDate }}
+ - {{ revokedDate | formatDate }}
-
+
The following verifications were successfully completed:
The following claims were successfully found:
@@ -43,10 +42,10 @@
{{ mdiCheckBold }}
- Credential issuer is {{ currCredIssuer }}
+ Credential issuer is {{ issuer }}
@@ -54,10 +53,10 @@
{{ mdiCheckBold }}
- Credential is held by {{ entityName }}
+ Credential is held by {{ topicName }}
@@ -65,21 +64,21 @@
{{ mdiCheckBold }}
Credential is validCredential is validexpired
-
+
{{ mdiCheckBold }}
Credential is tamper-free
@@ -89,13 +88,16 @@
-
+
- Claims proven
+ Claims proven
+
{{ mdiCheckBold }}
@@ -120,14 +123,18 @@
-
+
Proof Details
-
+
@@ -144,15 +151,13 @@ import { mapActions, mapGetters } from "vuex";
import { ICredentialSet } from "@/interfaces/api/v2/credential-set.interface";
import { ICredentialProof } from "@/interfaces/api/v3/credential-verified.interface";
import { IFormattedTopic } from "@/interfaces/api/v2/topic.interface";
-import {
- ICredential,
- ICredentialFormatted,
-} from "@/interfaces/api/v4/credential.interface";
+import { ICredentialFormatted } from "@/interfaces/api/v4/credential.interface";
import i18n from "@/i18n/index";
import router from "@/router";
import moment from "moment";
import BackTo from "@/components/shared/BackTo.vue";
import { unwrapTranslations, isExpired } from "@/utils/entity";
+import { ICredentialType } from "@/interfaces/api/v2/credential-type.interface";
interface Data {
headers: Record
[];
@@ -215,69 +220,76 @@ export default class CredentialDetail extends Vue {
};
}
- get currDate(): string {
- return moment(new Date()).format("MMM, DD YYYY [at] hh:mm a");
+ get selectedCredential(): ICredentialFormatted | undefined {
+ return this.getSelectedCredential;
}
- get entityName(): string | undefined {
- return this.selectedTopic.names[0]?.text;
+ get now(): string {
+ return moment(new Date()).format("MMM, DD YYYY [at] hh:mm a");
}
- get entitySourceID(): string | undefined {
+ get topicSourceId(): string | undefined {
return this.sourceId;
}
- get currCredEffDate(): Date | undefined {
- return this.getSelectedCredential?.effective_date;
+ get topicName(): string | undefined {
+ return this.selectedTopic.names[0]?.text;
}
- get currCredIssuedDate(): Date | undefined {
- return this.getSelectedCredential?.create_timestamp;
+ get issuer(): string | undefined {
+ return this.selectedCredential?.credential_type?.issuer?.name;
}
- get currCredIssuer(): string | undefined {
- return this.getSelectedCredential?.credential_type?.issuer?.name;
+ get credentialType(): ICredentialType | undefined {
+ return this.selectedCredential?.credential_type;
}
- get currCredTypeDesc(): string | undefined {
- if (!this.getSelectedCredential) {
+ get credentialTypeDescription(): string | undefined {
+ if (!this.selectedCredential) {
return undefined;
}
- const credentialType = this.getSelectedCredential.credential_type;
- if (credentialType?.format === "vc_di") {
+ if (this.credentialType?.format === "vc_di") {
// TODO: Eventually, this should be a translation from OCA
- return credentialType?.schema?.name;
+ return this.credentialType?.schema?.name;
}
return (
- unwrapTranslations(credentialType.schema_label)?.[i18n.locale]?.label ??
- credentialType.description ??
+ unwrapTranslations(this.credentialType?.schema_label)?.[i18n.locale]
+ ?.label ??
+ this.credentialType?.description ??
""
);
}
-
- get credRevoked(): boolean | undefined {
+ get revoked(): boolean | undefined {
return (
- this.getSelectedCredential?.revoked ||
- !!this.isExpired(this.getSelectedCredential?.attributes)
+ this.selectedCredential?.revoked ||
+ !!this.isExpired(this.selectedCredential?.attributes)
);
}
- get credRevokedDate(): Date | string | undefined {
+ get effectiveDate(): Date | undefined {
+ return this.selectedCredential?.effective_date;
+ }
+
+ get issuedDate(): Date | undefined {
+ return this.selectedCredential?.create_timestamp;
+ }
+
+ get revokedDate(): Date | string | undefined {
return (
- this.getSelectedCredential?.revoked_date ||
- this.isExpired(this.getSelectedCredential?.attributes)
+ this.selectedCredential?.revoked_date ||
+ this.isExpired(this.selectedCredential?.attributes)
);
}
- get errorWording(): string {
- if (!this.credRevoked) {
+ get errorMessage(): string {
+ if (!this.revoked) {
return "";
}
// Credential is expired and has been replaced. It can no longer be verified. (replaced and expired)
// Credential is expired. It can no longer be verified. (expired)
// Credential has been replaced. It can no longer be verified. (replaced)
- const replaced = !!this.getSelectedCredential?.revoked;
- const expired = !!this.isExpired(this.getSelectedCredential?.attributes);
+ const replaced = !!this.selectedCredential?.revoked;
+ const expired = !!this.isExpired(this.selectedCredential?.attributes);
let base = "Credential ";
if (expired) {
base += "is expired";
@@ -293,6 +305,14 @@ export default class CredentialDetail extends Vue {
return base + " It can no longer be verified";
}
+ get proofRaw(): string | undefined {
+ const rawVals = this.getPresentationEX;
+ if (rawVals === undefined) {
+ return rawVals;
+ }
+ return JSON.stringify(rawVals?.result, null, 2);
+ }
+
get proofValues(): Record[] | undefined {
const rawVals =
this.getPresentationEX?.result?.presentation?.requested_proof
@@ -305,16 +325,11 @@ export default class CredentialDetail extends Vue {
});
}
- get proofRaw(): string | undefined {
- const rawVals = this.getPresentationEX;
- if (rawVals === undefined) {
- return rawVals;
+ get rawData(): unknown {
+ if (this.credentialType?.format === "vc_di") {
+ return JSON.stringify(this.selectedCredential?.raw_data || {}, null, 2);
}
- return JSON.stringify(rawVals?.result, null, 2);
- }
-
- isRelationshipCred(cred: ICredential): boolean {
- return cred.credential_type.description === "relationship.registries.ca";
+ return null;
}
// FIXME: Need to fix timing issue in the API first
@@ -344,7 +359,7 @@ export default class CredentialDetail extends Vue {
} else {
router.push("/search");
}
- if (!this.getSelectedCredential || !this.selectedTopic) {
+ if (!this.selectedCredential || !this.selectedTopic) {
// cred or source id invalid, failed to load credential
console.error(
"Invalid credential or source Id. Credential detail not retrieved"
@@ -360,22 +375,28 @@ export default class CredentialDetail extends Vue {
.card {
@include card-raised;
}
+
.wrap {
word-break: break-word;
}
+
.verification-time {
color: $gray;
}
+
.validated {
color: $success-color !important;
}
+
.invisible {
visibility: hidden;
}
+
.progress {
color: $secondary-color;
}
-.proof-raw {
+
+.raw {
overflow: scroll;
}
diff --git a/src/interfaces/api/v4/credential.interface.ts b/src/interfaces/api/v4/credential.interface.ts
index 331b15a..62ddce0 100644
--- a/src/interfaces/api/v4/credential.interface.ts
+++ b/src/interfaces/api/v4/credential.interface.ts
@@ -36,6 +36,7 @@ export interface ICredential extends IApiResource {
names: ICredentialName[];
credential_type: ICredentialType;
attributes: ICredentialAttribute[];
+ raw_data?: unknown;
}
export interface ICredentialDisplayType {
@@ -57,6 +58,7 @@ export interface ICredentialDisplayType {
schema_label?: Record;
attributes?: ICredentialAttribute[];
credential_type_id: number;
+ raw_data?: unknown;
}
export interface ICredentialFormatted {
@@ -74,6 +76,7 @@ export interface ICredentialFormatted {
topic: IFormattedTopic;
related_topics: ITopic[];
credential_set: ICredentialSet;
+ raw_data?: unknown;
}
export interface ICredentialDetailView {
diff --git a/src/utils/entity.ts b/src/utils/entity.ts
index 68a986b..924237a 100644
--- a/src/utils/entity.ts
+++ b/src/utils/entity.ts
@@ -137,6 +137,7 @@ export function credOrRelationshipToDisplay(
display.credential_title = credItem.credential_type.credential_title;
display.attributes = credItem.attributes;
display.credential_type_id = credItem.credential_type.id;
+ display.raw_data = credItem.raw_data;
} else {
const relItem = item as IRelationship;