Browse Source

for BVC: finish submission of confirmations & final give

kb/add-usage-guide
Trent Larson 9 months ago
parent
commit
2c28913d97
  1. 39
      src/libs/endorserServer.ts
  2. 5
      src/views/ClaimView.vue
  3. 5
      src/views/ProjectViewView.vue
  4. 4
      src/views/QuickActionBvcBeginView.vue
  5. 119
      src/views/QuickActionBvcEndView.vue

39
src/libs/endorserServer.ts

@ -22,7 +22,7 @@ export interface AgreeVerifiableCredential {
"@type": string; "@type": string;
// "any" because arbitrary objects can be subject of agreement // "any" because arbitrary objects can be subject of agreement
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
object: Record<any, any>; object: Record<string, any>;
} }
export interface GiverInputInfo { export interface GiverInputInfo {
@ -46,6 +46,7 @@ export interface ClaimResult {
export interface GenericVerifiableCredential { export interface GenericVerifiableCredential {
"@context": string; "@context": string;
"@type": string; "@type": string;
[key: string]: any; // eslint-disable-line @typescript-eslint/no-explicit-any
} }
export interface GenericServerRecord extends GenericVerifiableCredential { export interface GenericServerRecord extends GenericVerifiableCredential {
@ -54,7 +55,7 @@ export interface GenericServerRecord extends GenericVerifiableCredential {
issuedAt: string; issuedAt: string;
issuer: string; issuer: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
claim: Record<any, any>; claim: Record<string, any>;
claimType?: string; claimType?: string;
} }
export const BLANK_GENERIC_SERVER_RECORD: GenericServerRecord = { export const BLANK_GENERIC_SERVER_RECORD: GenericServerRecord = {
@ -330,7 +331,7 @@ export function addLastClaimOrHandleAsIdIfMissing(
} }
// return clone of object without any nested *VisibleToDids keys // return clone of object without any nested *VisibleToDids keys
// similar logic is found in endorser-mobile // similar code is also contained in endorser-mobile
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
export function removeVisibleToDids(input: any): any { export function removeVisibleToDids(input: any): any {
if (input instanceof Object) { if (input instanceof Object) {
@ -340,7 +341,6 @@ export function removeVisibleToDids(input: any): any {
const result: Record<string, any> = {}; const result: Record<string, any> = {};
for (const key in input) { for (const key in input) {
if (!key.endsWith("VisibleToDids")) { if (!key.endsWith("VisibleToDids")) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
result[key] = removeVisibleToDids(R.clone(input[key])); result[key] = removeVisibleToDids(R.clone(input[key]));
} }
} }
@ -349,7 +349,6 @@ export function removeVisibleToDids(input: any): any {
// it's an array // it's an array
return R.map(removeVisibleToDids, input); return R.map(removeVisibleToDids, input);
} }
return false;
} else { } else {
return input; return input;
} }
@ -518,6 +517,28 @@ export async function createAndSubmitOffer(
); );
} }
// similar logic is found in endorser-mobile
export const createAndSubmitConfirmation = async (
identifier: IIdentifier,
claim: GenericVerifiableCredential,
lastClaimId: string, // used to set the lastClaimId
handleId: string | undefined,
apiServer: string,
axios: Axios,
) => {
const goodClaim = removeSchemaContext(
removeVisibleToDids(
addLastClaimOrHandleAsIdIfMissing(claim, lastClaimId, handleId),
),
);
const confirmationClaim: GenericVerifiableCredential = {
"@context": "https://schema.org",
"@type": "AgreeAction",
object: goodClaim,
};
return createAndSubmitClaim(confirmationClaim, identifier, apiServer, axios);
};
export async function createAndSubmitClaim( export async function createAndSubmitClaim(
vcClaim: GenericVerifiableCredential, vcClaim: GenericVerifiableCredential,
identity: IIdentifier, identity: IIdentifier,
@ -583,7 +604,7 @@ export async function createAndSubmitClaim(
} }
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isAccept = (claim: Record<any, any>) => { export const isAccept = (claim: Record<string, any>) => {
return ( return (
claim && claim &&
claim["@context"] === SCHEMA_ORG_CONTEXT && claim["@context"] === SCHEMA_ORG_CONTEXT &&
@ -592,7 +613,7 @@ export const isAccept = (claim: Record<any, any>) => {
}; };
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
export const isOffer = (claim: Record<any, any>) => { export const isOffer = (claim: Record<string, any>) => {
return ( return (
claim && claim &&
claim["@context"] === SCHEMA_ORG_CONTEXT && claim["@context"] === SCHEMA_ORG_CONTEXT &&
@ -622,7 +643,7 @@ export const capitalizeAndInsertSpacesBeforeCaps = (text: string) => {
similar code is also contained in endorser-mobile similar code is also contained in endorser-mobile
**/ **/
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
const claimSummary = (claim: Record<any, any>) => { const claimSummary = (claim: Record<string, any>) => {
if (!claim) { if (!claim) {
// to differentiate from "something" above // to differentiate from "something" above
return "something"; return "something";
@ -630,7 +651,7 @@ const claimSummary = (claim: Record<any, any>) => {
if (claim.claim) { if (claim.claim) {
// probably a Verified Credential // probably a Verified Credential
// eslint-disable-next-line @typescript-eslint/no-explicit-any // eslint-disable-next-line @typescript-eslint/no-explicit-any
claim = claim.claim as Record<any, any>; claim = claim.claim as Record<string, any>;
} }
if (Array.isArray(claim)) { if (Array.isArray(claim)) {
if (claim.length === 1) { if (claim.length === 1) {

5
src/views/ClaimView.vue

@ -730,10 +730,7 @@ export default class ClaimView extends Vue {
), ),
), ),
); );
const confirmationClaim: serverUtil.GenericVerifiableCredential & { const confirmationClaim: serverUtil.GenericVerifiableCredential = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
object: any;
} = {
"@context": "https://schema.org", "@context": "https://schema.org",
"@type": "AgreeAction", "@type": "AgreeAction",
object: goodClaim, object: goodClaim,

5
src/views/ProjectViewView.vue

@ -800,10 +800,7 @@ export default class ProjectViewView extends Vue {
), ),
), ),
); );
const confirmationClaim: serverUtil.GenericVerifiableCredential & { const confirmationClaim: serverUtil.GenericVerifiableCredential = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
object: any;
} = {
"@context": "https://schema.org", "@context": "https://schema.org",
"@type": "AgreeAction", "@type": "AgreeAction",
object: goodClaim, object: goodClaim,

4
src/views/QuickActionBvcBeginView.vue

@ -125,6 +125,7 @@ export default class QuickActionBvcBeginView extends Vue {
const hoursNum = libsUtil.numberOrZero(this.hoursStr); const hoursNum = libsUtil.numberOrZero(this.hoursStr);
const identity = await libsUtil.getIdentity(activeDid); const identity = await libsUtil.getIdentity(activeDid);
// first send the claim for time given
let timeSuccess = false; let timeSuccess = false;
if (this.gaveTime && hoursNum > 0) { if (this.gaveTime && hoursNum > 0) {
const timeResult = await createAndSubmitGive( const timeResult = await createAndSubmitGive(
@ -156,6 +157,7 @@ export default class QuickActionBvcBeginView extends Vue {
} }
} }
// now send the claim for attendance
let attendedSuccess = false; let attendedSuccess = false;
if (this.attended) { if (this.attended) {
const attendResult = await createAndSubmitClaim( const attendResult = await createAndSubmitClaim(
@ -208,7 +210,7 @@ export default class QuickActionBvcBeginView extends Vue {
group: "alert", group: "alert",
type: "danger", type: "danger",
title: "Error", title: "Error",
text: error.userMessage || "There was an error sending those claims.", text: error.userMessage || "There was an error sending claims.",
}, },
-1, -1,
); );

119
src/views/QuickActionBvcEndView.vue

@ -117,6 +117,7 @@
</template> </template>
<script lang="ts"> <script lang="ts">
import axios from "axios";
import { DateTime } from "luxon"; import { DateTime } from "luxon";
import * as R from "ramda"; import * as R from "ramda";
import { IIdentifier } from "@veramo/core"; import { IIdentifier } from "@veramo/core";
@ -131,10 +132,16 @@ import { Contact } from "@/db/tables/contacts";
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings"; import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
import { accessToken } from "@/libs/crypto"; import { accessToken } from "@/libs/crypto";
import { import {
BVC_MEETUPS_PROJECT_CLAIM_ID,
claimSpecialDescription, claimSpecialDescription,
containsHiddenDid, containsHiddenDid,
createAndSubmitConfirmation,
createAndSubmitGive,
ErrorResult,
GenericServerRecord, GenericServerRecord,
GenericVerifiableCredential,
} from "@/libs/endorserServer"; } from "@/libs/endorserServer";
import * as libsUtil from "@/libs/util";
@Component({ @Component({
methods: { claimSpecialDescription }, methods: { claimSpecialDescription },
@ -246,8 +253,116 @@ export default class QuickActionBvcBeginView extends Vue {
this.$router.push(route); this.$router.push(route);
} }
record() { async record() {
alert("Nope"); try {
const identity = await libsUtil.getIdentity(this.activeDid);
// in parallel, make a confirmation for each selected claim and send them all to the server
const confirmResults = await Promise.allSettled(
this.claimsToConfirmSelected.map(async (jwtId) => {
const record = this.claimsToConfirm.find(
(claim) => claim.id === jwtId,
);
if (!record) {
return { type: "error", error: "Record not found." };
}
const identity = await libsUtil.getIdentity(this.activeDid);
return createAndSubmitConfirmation(
identity,
record.claim as GenericVerifiableCredential,
record.id,
record.handleId,
this.apiServer,
axios,
);
}),
);
// check for any rejected confirmations
const confirmsSucceeded = confirmResults.filter(
(result) =>
result.status === "fulfilled" && result.value.type === "success",
);
if (confirmsSucceeded.length < this.claimsToConfirmSelected.length) {
console.error("Error sending confirmations:", confirmResults);
const howMany = confirmsSucceeded.length === 0 ? "all" : "some";
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: `There was an error sending ${howMany} of the confirmations.`,
},
-1,
);
}
// now send the give for the description
let giveSucceeded = false;
if (this.someoneGave) {
const giveResult = await createAndSubmitGive(
axios,
this.apiServer,
identity,
undefined,
this.activeDid,
this.description,
undefined,
undefined,
BVC_MEETUPS_PROJECT_CLAIM_ID,
);
giveSucceeded = giveResult.type === "success";
if (!giveSucceeded) {
console.error("Error sending give:", giveResult);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text:
(giveResult as ErrorResult)?.error?.userMessage ||
"There was an error sending the give.",
},
-1,
);
}
}
if (confirmsSucceeded.length > 0 || giveSucceeded) {
const confirms =
confirmsSucceeded.length === 1 ? "confirmation" : "confirmations";
const actions =
confirmsSucceeded.length > 0 && giveSucceeded
? `${confirms} and give have been`
: giveSucceeded
? "give has been"
: confirms +
" " +
(confirmsSucceeded.length === 1 ? "has" : "have") +
" been";
this.$notify(
{
group: "alert",
type: "success",
title: "Success",
text: `Your ${actions} recorded.`,
},
-1,
);
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (error: any) {
console.error("Error sending claims.", error);
this.$notify(
{
group: "alert",
type: "danger",
title: "Error",
text: error.userMessage || "There was an error sending claims.",
},
-1,
);
}
} }
} }
</script> </script>

Loading…
Cancel
Save