Browse Source

feat: enhance GenericVerifiableCredential interface with explicit optional properties

- Add name, description, and agent as optional properties to GenericVerifiableCredential
- Improve type safety and IntelliSense for common claim properties
- Maintain backward compatibility with existing code
- Reduce need for type assertions when accessing claim properties
streamline-attempt
Matthew Raymer 2 weeks ago
parent
commit
2b0e60dfc2
  1. 2
      src/components/FeedFilters.vue
  2. 1
      src/components/GiftedDialog.vue
  3. 1
      src/components/GiftedPrompts.vue
  4. 29
      src/components/ImageMethodDialog.vue
  5. 6
      src/components/MembersList.vue
  6. 1
      src/components/OfferDialog.vue
  7. 1
      src/components/PhotoDialog.vue
  8. 6
      src/components/PushNotificationPermission.vue
  9. 1
      src/components/TopMessage.vue
  10. 1
      src/components/UserNameDialog.vue
  11. 1
      src/components/World/components/objects/landmarks.js
  12. 2
      src/interfaces/index.ts
  13. 15
      src/libs/endorserServer.ts
  14. 2
      src/libs/partnerServer.ts
  15. 9
      src/libs/util.ts
  16. 7
      src/services/platforms/CapacitorPlatformService.ts
  17. 33
      src/views/AccountViewView.vue
  18. 23
      src/views/ClaimAddRawView.vue
  19. 9
      src/views/ClaimReportCertificateView.vue
  20. 1
      src/views/ClaimView.vue
  21. 1
      src/views/ConfirmGiftView.vue
  22. 12
      src/views/ContactAmountsView.vue
  23. 3
      src/views/ContactEditView.vue
  24. 1
      src/views/ContactGiftingView.vue
  25. 25
      src/views/ContactImportView.vue
  26. 3
      src/views/ContactQRScanFullView.vue
  27. 23
      src/views/DiscoverView.vue
  28. 1
      src/views/GiftedDetailsView.vue
  29. 5
      src/views/HelpNotificationsView.vue
  30. 4
      src/views/HelpView.vue
  31. 8
      src/views/HomeView.vue
  32. 6
      src/views/IdentitySwitcherView.vue
  33. 2
      src/views/ImportDerivedAccountView.vue
  34. 10
      src/views/LogView.vue
  35. 20
      src/views/NewEditProjectView.vue
  36. 5
      src/views/OfferDetailsView.vue
  37. 1
      src/views/OnboardMeetingListView.vue
  38. 8
      src/views/OnboardMeetingMembersView.vue
  39. 4
      src/views/OnboardMeetingSetupView.vue
  40. 10
      src/views/ProjectViewView.vue
  41. 11
      src/views/QuickActionBvcEndView.vue
  42. 1
      src/views/RecentOffersToUserView.vue
  43. 1
      src/views/ShareMyContactInfoView.vue
  44. 2
      src/views/SharedPhotoView.vue
  45. 2
      src/views/StartView.vue
  46. 13
      src/views/TestView.vue
  47. 1
      src/views/UserProfileView.vue

2
src/components/FeedFilters.vue

@ -101,8 +101,6 @@ import {
import { Router } from "vue-router";
import * as databaseUtil from "../db/databaseUtil";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
@Component({
components: {

1
src/components/GiftedDialog.vue

@ -96,7 +96,6 @@ import {
serverMessageForUser,
} from "../libs/endorserServer";
import * as libsUtil from "../libs/util";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveAccountDids } from "../libs/util";

1
src/components/GiftedPrompts.vue

@ -75,7 +75,6 @@ import { Vue, Component } from "vue-facing-decorator";
import { Router } from "vue-router";
import { AppString, NotificationIface } from "../constants/app";
import { db } from "../db/index";
import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import { GiverReceiverInputInfo } from "../libs/util";

29
src/components/ImageMethodDialog.vue

@ -262,30 +262,21 @@ import { Component, Vue } from "vue-facing-decorator";
import VuePictureCropper, { cropper } from "vue-picture-cropper";
import { Capacitor } from "@capacitor/core";
import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "../constants/app";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { accessToken } from "../libs/crypto";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
import * as databaseUtil from "../db/databaseUtil";
import { Prop } from "vue-facing-decorator";
import { Router } from "vue-router";
const inputImageFileNameRef = ref<Blob>();
@Component({
components: { VuePictureCropper },
props: {
isRegistered: {
type: Boolean,
default: true,
},
defaultCameraMode: {
type: String,
default: "environment",
validator: (value: string) => ["environment", "user"].includes(value),
},
},
})
export default class ImageMethodDialog extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
/** Active DID for user authentication */
activeDid = "";
@ -303,7 +294,7 @@ export default class ImageMethodDialog extends Vue {
fileName?: string;
/** Callback function to set image URL after upload */
imageCallback: (imageUrl?: string) => void = () => {};
imageCallback: (imageUrl: string) => void = () => {};
/** URL for image input */
imageUrl?: string;
@ -351,6 +342,14 @@ export default class ImageMethodDialog extends Vue {
cameraStateMessage?: string;
error: string | null = null;
// Props
@Prop({ default: true }) isRegistered!: boolean;
@Prop({
default: "environment",
validator: (value: string) => ["environment", "user"].includes(value),
})
defaultCameraMode!: string;
/**
* Lifecycle hook: Initializes component and retrieves user settings
* @throws {Error} When settings retrieval fails
@ -411,7 +410,7 @@ export default class ImageMethodDialog extends Vue {
type: file.type,
});
this.blob = blob;
this.fileName = file.name;
this.fileName = (file as File).name;
this.showRetry = false;
}
};
@ -442,7 +441,7 @@ export default class ImageMethodDialog extends Vue {
);
}
} else {
this.imageCallback(this.imageUrl);
this.imageCallback(this.imageUrl as string);
this.close();
}
}

6
src/components/MembersList.vue

@ -159,11 +159,7 @@
<script lang="ts">
import { Component, Vue, Prop } from "vue-facing-decorator";
import {
logConsoleAndDb,
retrieveSettingsForActiveAccount,
db,
} from "../db/index";
import { logConsoleAndDb } from "../db/index";
import {
errorStringForLog,
getHeaders,

1
src/components/OfferDialog.vue

@ -86,7 +86,6 @@ import { NotificationIface } from "../constants/app";
import { createAndSubmitOffer } from "../libs/endorserServer";
import * as libsUtil from "../libs/util";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { logger } from "../utils/logger";
@Component

1
src/components/PhotoDialog.vue

@ -121,7 +121,6 @@ import { Component, Vue } from "vue-facing-decorator";
import VuePictureCropper, { cropper } from "vue-picture-cropper";
import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { accessToken } from "../libs/crypto";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory";

6
src/components/PushNotificationPermission.vue

@ -104,11 +104,7 @@ import { Component, Vue } from "vue-facing-decorator";
import { DEFAULT_PUSH_SERVER, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import {
logConsoleAndDb,
retrieveSettingsForActiveAccount,
secretDB,
} from "../db/index";
import { logConsoleAndDb, secretDB } from "../db/index";
import { MASTER_SECRET_KEY } from "../db/tables/secret";
import { urlBase64ToUint8Array } from "../libs/crypto/vc/util";
import * as libsUtil from "../libs/util";

1
src/components/TopMessage.vue

@ -17,7 +17,6 @@ import { Component, Vue, Prop } from "vue-facing-decorator";
import { AppString, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
@Component
export default class TopMessage extends Vue {

1
src/components/UserNameDialog.vue

@ -38,7 +38,6 @@
import { Vue, Component, Prop } from "vue-facing-decorator";
import { NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import * as databaseUtil from "../db/databaseUtil";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";

1
src/components/World/components/objects/landmarks.js

@ -4,7 +4,6 @@ import { GLTFLoader } from "three/addons/loaders/GLTFLoader";
import * as SkeletonUtils from "three/addons/utils/SkeletonUtils";
import * as TWEEN from "@tweenjs/tween.js";
import * as databaseUtil from "../../../../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../../../../db";
import { getHeaders } from "../../../../libs/endorserServer";
import { logger } from "../../../../utils/logger";

2
src/interfaces/index.ts

@ -32,3 +32,5 @@ export type {
export * from "./limits";
export * from "./deepLinks";
export * from "./common";
export * from "./claims-result";
export * from "./records";

15
src/libs/endorserServer.ts

@ -29,7 +29,6 @@ import {
} from "../constants/app";
import { Contact } from "../db/tables/contacts";
import { accessToken, deriveAddress, nextDerivationPath } from "../libs/crypto";
import { NonsensitiveDexie } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil";
import {
retrieveAccountMetadata,
@ -689,6 +688,7 @@ export function hydrateGive(
if (amount && !isNaN(amount)) {
const quantitativeValue: QuantitativeValue = {
"@type": "QuantitativeValue",
amountOfThisGood: amount,
unitCode: unitCode || "HUR",
};
@ -999,11 +999,12 @@ export async function createAndSubmitClaim(
axios: Axios,
): Promise<CreateAndSubmitClaimResult> {
try {
const vcPayload = {
const vcPayload: { vc: VerifiableCredentialClaim } = {
vc: {
"@context": ["https://www.w3.org/2018/credentials/v1"],
"@context": "https://www.w3.org/2018/credentials/v1",
"@type": "VerifiableCredential",
type: ["VerifiableCredential"],
credentialSubject: vcClaim,
credentialSubject: vcClaim as unknown as ClaimObject, // Type assertion needed due to object being string
},
};
@ -1330,7 +1331,8 @@ export async function createEndorserJwtVcFromClaim(
// Make a payload for the claim
const vcPayload = {
vc: {
"@context": ["https://www.w3.org/2018/credentials/v1"],
"@context": "https://www.w3.org/2018/credentials/v1",
"@type": "VerifiableCredential",
type: ["VerifiableCredential"],
credentialSubject: claim,
},
@ -1367,7 +1369,7 @@ export async function createInviteJwt(
// Make a payload for the claim
const vcPayload: { vc: VerifiableCredentialClaim } = {
vc: {
"@context": ["https://www.w3.org/2018/credentials/v1"],
"@context": "https://www.w3.org/2018/credentials/v1",
"@type": "VerifiableCredential",
type: ["VerifiableCredential"],
credentialSubject: vcClaim as unknown as ClaimObject, // Type assertion needed due to object being string
@ -1431,7 +1433,6 @@ export async function setVisibilityUtil(
activeDid: string,
apiServer: string,
axios: Axios,
db: NonsensitiveDexie,
contact: Contact,
visibility: boolean,
) {

2
src/libs/partnerServer.ts

@ -4,6 +4,6 @@ export interface UserProfile {
locLon?: number;
locLat2?: number;
locLon2?: number;
issuerDid: string;
issuerDid?: string;
rowId?: string; // set on profile retrieved from server
}

9
src/libs/util.ts

@ -6,12 +6,6 @@ import * as R from "ramda";
import { useClipboard } from "@vueuse/core";
import { DEFAULT_PUSH_SERVER, NotificationIface } from "../constants/app";
import {
accountsDBPromise,
retrieveSettingsForActiveAccount,
updateAccountSettings,
updateDefaultSettings,
} from "../db/index";
import { Account, AccountEncrypted } from "../db/tables/accounts";
import { Contact, ContactWithJsonStrings } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
@ -38,9 +32,8 @@ import { createPeerDid } from "../libs/crypto/vc/didPeer";
import { registerCredential } from "../libs/crypto/vc/passkeyDidPeer";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { sha256 } from "ethereum-cryptography/sha256";
import { IIdentifier } from "@veramo/core";
import { insertDidSpecificSettings, parseJsonField } from "../db/databaseUtil";
import { parseJsonField } from "../db/databaseUtil";
import { DEFAULT_ROOT_DERIVATION_PATH } from "./crypto";
export interface GiverReceiverInputInfo {

7
src/services/platforms/CapacitorPlatformService.ts

@ -42,7 +42,7 @@ interface QueuedOperation {
*/
export class CapacitorPlatformService implements PlatformService {
/** Current camera direction */
private currentDirection: CameraDirection = "BACK";
private currentDirection: CameraDirection = CameraDirection.Rear;
private sqlite: SQLiteConnection;
private db: SQLiteDBConnection | null = null;
@ -702,7 +702,10 @@ export class CapacitorPlatformService implements PlatformService {
* @returns Promise that resolves when the camera is rotated
*/
async rotateCamera(): Promise<void> {
this.currentDirection = this.currentDirection === "BACK" ? "FRONT" : "BACK";
this.currentDirection =
this.currentDirection === CameraDirection.Rear
? CameraDirection.Front
: CameraDirection.Rear;
logger.debug(`Camera rotated to ${this.currentDirection} camera`);
}

33
src/views/AccountViewView.vue

@ -357,12 +357,7 @@
<l-map
ref="profileMap"
class="!z-40 rounded-md"
@click="
(event: LeafletMouseEvent) => {
userProfileLatitude = event.latlng.lat;
userProfileLongitude = event.latlng.lng;
}
"
@click="onProfileMapClick"
@ready="onMapReady"
>
<l-tile-layer
@ -437,7 +432,7 @@
You have done
<b
>{{ endorserLimits?.doneClaimsThisWeek ?? "?" }} claim{{
endorserLimits?.doneClaimsThisWeek === 1 ? "" : "s"
Number(endorserLimits?.doneClaimsThisWeek || 0) === 1 ? "" : "s"
}}</b
>
out of <b>{{ endorserLimits?.maxClaimsPerWeek ?? "?" }}</b> for this
@ -453,7 +448,9 @@
endorserLimits?.doneRegistrationsThisMonth ?? "?"
}}
registration{{
endorserLimits?.doneRegistrationsThisMonth === 1 ? "" : "s"
Number(endorserLimits?.doneRegistrationsThisMonth || 0) === 1
? ""
: "s"
}}</b
>
out of
@ -469,13 +466,13 @@
You have uploaded
<b
>{{ imageLimits?.doneImagesThisWeek ?? "?" }} image{{
imageLimits?.doneImagesThisWeek === 1 ? "" : "s"
Number(imageLimits?.doneImagesThisWeek || 0) === 1 ? "" : "s"
}}</b
>
out of <b>{{ imageLimits?.maxImagesPerWeek ?? "?" }}</b> for this
week. Your image counter resets at
<b class="whitespace-nowrap">{{
readableDate(imageLimits?.nextWeekBeginDateTime)
readableDate(imageLimits?.nextWeekBeginDateTime || "")
}}</b>
</p>
</div>
@ -1037,7 +1034,10 @@ const inputImportFileNameRef = ref<Blob>();
// Type guard for API errors
function isApiError(error: unknown): error is {
response?: { data?: { error?: { message?: string } | string } };
response?: {
data?: { error?: { message?: string } | string };
status?: number;
};
} {
return typeof error === "object" && error !== null && "response" in error;
}
@ -1172,7 +1172,7 @@ export default class AccountViewView extends Vue {
throw Error("Unable to load profile.");
}
} catch (error) {
if (error.status === 404) {
if (isApiError(error) && error.response?.status === 404) {
// this is ok: the profile is not yet created
} else {
databaseUtil.logConsoleAndDb(
@ -1610,7 +1610,9 @@ export default class AccountViewView extends Vue {
}
async uploadImportFile(event: Event) {
inputImportFileNameRef.value = (event.target as EventTarget).files[0];
inputImportFileNameRef.value = (
event.target as HTMLInputElement
).files?.[0];
}
showContactImport() {
@ -2093,5 +2095,10 @@ export default class AccountViewView extends Vue {
this.$router.push({ name: "contact-qr" });
}
}
onProfileMapClick(event: LeafletMouseEvent) {
this.userProfileLatitude = event.latlng.lat;
this.userProfileLongitude = event.latlng.lng;
}
}
</script>

23
src/views/ClaimAddRawView.vue

@ -30,12 +30,11 @@
<script lang="ts">
import { Component, Vue } from "vue-facing-decorator";
import { AxiosInstance } from "axios";
import { AxiosResponse, AxiosStatic } from "axios";
import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil";
import * as serverUtil from "../libs/endorserServer";
import * as libsUtil from "../libs/util";
@ -43,6 +42,16 @@ import { errorStringForLog } from "../libs/endorserServer";
import { Router, RouteLocationNormalizedLoaded } from "vue-router";
import { logger } from "../utils/logger";
// Type guard for API responses
function isApiResponse(response: unknown): response is AxiosResponse {
return (
typeof response === "object" &&
response !== null &&
"status" in response &&
"data" in response
);
}
/**
* View component for adding or editing raw claim data
* Allows direct JSON editing of claim data with validation and submission
@ -54,7 +63,7 @@ export default class ClaimAddRawView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
axios!: AxiosInstance;
axios!: AxiosStatic; // Using any to avoid type conflicts with Vue's axios property
accountIdentityStr: string = "null";
activeDid = "";
@ -145,17 +154,19 @@ export default class ClaimAddRawView extends Vue {
* Format successful claim response data
*/
private formatClaimResponse(response: unknown, claimJwtId: string) {
if (response.status === 200) {
if (isApiResponse(response) && response.status === 200) {
const claim = response.data?.claim;
claim.lastClaimId = serverUtil.stripEndorserPrefix(claimJwtId);
this.claimStr = JSON.stringify(claim, null, 2);
} else {
throw {
message: "Got an error loading that claim.",
response: {
response: isApiResponse(response)
? {
status: response.status,
statusText: response.statusText,
},
}
: { status: 0, statusText: "Unknown response type" },
};
}
}

9
src/views/ClaimReportCertificateView.vue

@ -12,9 +12,12 @@ import { nextTick } from "vue";
import QRCode from "qrcode";
import { APP_SERVER, NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import * as databaseUtil from "../db/databaseUtil";
import * as endorserServer from "../libs/endorserServer";
import {
GenericCredWrapper,
GenericVerifiableCredential,
} from "../interfaces/common";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Contact } from "@/db/tables/contacts";
@ -66,9 +69,7 @@ export default class ClaimReportCertificateView extends Vue {
}
}
async drawCanvas(
claimData: endorserServer.GenericCredWrapper<endorserServer.GenericVerifiableCredential>,
) {
async drawCanvas(claimData: GenericCredWrapper<GenericVerifiableCredential>) {
const platformService = PlatformServiceFactory.getInstance();
const dbAllContacts = await platformService.dbQuery(
"SELECT * FROM contacts",

1
src/views/ClaimView.vue

@ -559,7 +559,6 @@ import GiftedDialog from "../components/GiftedDialog.vue";
import QuickNav from "../components/QuickNav.vue";
import { APP_SERVER, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil";
import { Contact } from "../db/tables/contacts";
import * as serverUtil from "../libs/endorserServer";

1
src/views/ConfirmGiftView.vue

@ -437,7 +437,6 @@ import { useClipboard } from "@vueuse/core";
import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue";
import { APP_SERVER, NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import * as serverUtil from "../libs/endorserServer";

12
src/views/ContactAmountsView.vue

@ -48,7 +48,7 @@
<tbody>
<tr
v-for="record in giveRecords"
:key="record.id"
:key="record.jwtId"
class="border-b border-slate-300"
>
<td class="p-1 text-xs sm:text-sm text-left text-slate-500">
@ -118,14 +118,10 @@ import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import {
AgreeVerifiableCredential,
GiveSummaryRecord,
GiveActionClaim,
} from "../interfaces";
import { GiveSummaryRecord, GiveActionClaim } from "../interfaces";
import { AgreeActionClaim } from "../interfaces/claims";
import {
createEndorserJwtVcFromClaim,
displayAmount,
@ -274,7 +270,7 @@ export default class ContactAmountssView extends Vue {
delete origClaim["@context"];
}
origClaim["identifier"] = record.handleId;
const vcClaim: AgreeVerifiableCredential = {
const vcClaim: AgreeActionClaim = {
"@context": SCHEMA_ORG_CONTEXT,
"@type": "AgreeAction",
object: origClaim,

3
src/views/ContactEditView.vue

@ -12,7 +12,7 @@
>
<font-awesome icon="chevron-left" class="fa-fw" />
</button>
{{ contact.name || AppString.NO_CONTACT_NAME }}
{{ contact?.name || AppString.NO_CONTACT_NAME }}
</h1>
</div>
@ -141,7 +141,6 @@ import TopMessage from "../components/TopMessage.vue";
import { NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { parseJsonField } from "../db/databaseUtil";
import { db } from "../db/index";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
import { Contact, ContactMethod } from "../db/tables/contacts";
import { AppString } from "../constants/app";

1
src/views/ContactGiftingView.vue

@ -77,7 +77,6 @@ import GiftedDialog from "../components/GiftedDialog.vue";
import QuickNav from "../components/QuickNav.vue";
import EntityIcon from "../components/EntityIcon.vue";
import { NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import { GiverReceiverInputInfo } from "../libs/util";

25
src/views/ContactImportView.vue

@ -201,14 +201,9 @@ import QuickNav from "../components/QuickNav.vue";
import EntityIcon from "../components/EntityIcon.vue";
import OfferDialog from "../components/OfferDialog.vue";
import { APP_SERVER, AppString, NotificationIface } from "../constants/app";
import {
db,
logConsoleAndDb,
retrieveSettingsForActiveAccount,
} from "../db/index";
import { logConsoleAndDb } from "../db/index";
import { Contact, ContactMethod } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";
import { parseJsonField } from "../db/databaseUtil";
import * as libsUtil from "../libs/util";
import {
capitalizeAndInsertSpacesBeforeCaps,
@ -272,23 +267,6 @@ function contactToDbRecord(contact: Contact): ContactDbRecord {
};
}
/**
* Converts a ContactDbRecord back to a Contact object
* @param record The database record to convert
* @returns A Contact object with parsed contactMethods array
*/
function dbRecordToContact(record: ContactDbRecord): Contact {
return {
...record,
name: safeString(record.name),
notes: safeString(record.notes),
profileImageUrl: safeString(record.profileImageUrl),
publicKeyBase64: safeString(record.publicKeyBase64),
nextPubKeyHashB64: safeString(record.nextPubKeyHashB64),
contactMethods: parseJsonField(record.contactMethods, []),
};
}
/**
* Contact Import View Component
* @author Matthew Raymer
@ -632,7 +610,6 @@ export default class ContactImportView extends Vue {
this.activeDid,
this.apiServer,
this.axios,
db,
contact,
true,
);

3
src/views/ContactQRScanFullView.vue

@ -114,12 +114,10 @@ import { logger } from "../utils/logger";
import { QRScannerFactory } from "../services/QRScanner/QRScannerFactory";
import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app";
import { db } from "../db/index";
import { Contact } from "../db/tables/contacts";
import { getContactJwtFromJwtUrl } from "../libs/crypto";
import { decodeEndorserJwt, ETHR_DID_PREFIX } from "../libs/crypto/vc";
import * as libsUtil from "../libs/util";
import { retrieveSettingsForActiveAccount } from "../db/index";
import * as databaseUtil from "../db/databaseUtil";
import {
CONTACT_CSV_HEADER,
@ -444,7 +442,6 @@ export default class ContactQRScanFull extends Vue {
this.activeDid,
this.apiServer,
this.axios,
db,
contact,
visibility,
);

23
src/views/DiscoverView.vue

@ -324,20 +324,12 @@ import {
NotificationIface,
DEFAULT_PARTNER_API_SERVER,
} from "../constants/app";
import {
db,
logConsoleAndDb,
retrieveSettingsForActiveAccount,
} from "../db/index";
import { logConsoleAndDb } from "../db/index";
import { Contact } from "../db/tables/contacts";
import { BoundingBox } from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil";
import { PlanData } from "../interfaces";
import {
didInfo,
errorStringForLog,
getHeaders,
} from "../libs/endorserServer";
import { didInfo, errorStringForLog, getHeaders } from "../libs/endorserServer";
import { OnboardPage, retrieveAccountDids } from "../libs/util";
import { logger } from "../utils/logger";
import { UserProfile } from "@/libs/partnerServer";
@ -396,7 +388,6 @@ export default class DiscoverView extends Vue {
didInfo = didInfo;
async mounted() {
this.searchTerms = this.$route.query["searchText"]?.toString() || "";
const searchPeople = !!this.$route.query["searchPeople"];
@ -410,7 +401,9 @@ export default class DiscoverView extends Vue {
const platformService = PlatformServiceFactory.getInstance();
const dbContacts = await platformService.dbQuery("SELECT * FROM contacts");
this.allContacts = databaseUtil.mapQueryResultToValues(dbContacts) as unknown as Contact[];
this.allContacts = databaseUtil.mapQueryResultToValues(
dbContacts,
) as unknown as Contact[];
this.allMyDids = await retrieveAccountDids();
@ -504,7 +497,8 @@ export default class DiscoverView extends Vue {
} else {
throw JSON.stringify(results);
}
} else { // people search must be active
} else {
// people search must be active
this.projects = [];
const profiles: UserProfile[] = results.data;
if (profiles) {
@ -707,7 +701,8 @@ export default class DiscoverView extends Vue {
this.clearMarkers();
const results = await response.json();
if (results.data?.tiles?.length > 0) {
for (const tile: Tile of results.data.tiles) {
for (const t of results.data.tiles) {
const tile: Tile = t;
const pinLat = (tile.minFoundLat + tile.maxFoundLat) / 2;
const pinLon = (tile.minFoundLon + tile.maxFoundLon) / 2;
const numberIcon = L.divIcon({

1
src/views/GiftedDetailsView.vue

@ -262,7 +262,6 @@ import ImageMethodDialog from "../components/ImageMethodDialog.vue";
import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue";
import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import * as databaseUtil from "../db/databaseUtil";
import { GenericCredWrapper, GiveActionClaim } from "../interfaces";
import {

5
src/views/HelpNotificationsView.vue

@ -311,8 +311,6 @@ import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app";
import { DIRECT_PUSH_TITLE, sendTestThroughPushServer } from "../libs/util";
import PushNotificationPermission from "../components/PushNotificationPermission.vue";
import { db } from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil";
import { Router } from "vue-router";
import { logger } from "../utils/logger";
@ -322,6 +320,9 @@ export default class HelpNotificationsView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
subscriptionJSON?: PushSubscriptionJSON;
notifyingReminder = false;
notifyingReminderMessage = "";
notifyingReminderTime = "";
async mounted() {
try {

4
src/views/HelpView.vue

@ -603,10 +603,6 @@ import * as Package from "../../package.json";
import QuickNav from "../components/QuickNav.vue";
import { APP_SERVER, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import {
retrieveSettingsForActiveAccount,
updateAccountSettings,
} from "../db/index";
@Component({ components: { QuickNav } })
export default class HelpView extends Vue {

8
src/views/HomeView.vue

@ -321,11 +321,7 @@ import {
} from "../constants/app";
import { logConsoleAndDb } from "../db/index";
import { Contact } from "../db/tables/contacts";
import {
BoundingBox,
checkIsAnyFeedFilterOn,
MASTER_SETTINGS_KEY,
} from "../db/tables/settings";
import { BoundingBox, checkIsAnyFeedFilterOn } from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil";
import {
contactForDid,
@ -1729,7 +1725,7 @@ export default class HomeView extends Vue {
* @param event Event object
* @param imageUrl URL of image to cache
*/
async cacheImageData(event: Event, imageUrl: string) {
async cacheImageData(_event: Event, imageUrl: string) {
try {
// For images that might fail CORS, just store the URL
// The Web Share API will handle sharing the URL appropriately

6
src/views/IdentitySwitcherView.vue

@ -106,12 +106,6 @@ import { Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app";
import {
accountsDBPromise,
db,
retrieveSettingsForActiveAccount,
} from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveAllAccountsMetadata } from "../libs/util";
import { logger } from "../utils/logger";

2
src/views/ImportDerivedAccountView.vue

@ -80,8 +80,6 @@ import {
nextDerivationPath,
} from "../libs/crypto";
import * as databaseUtil from "../db/databaseUtil";
import { db } from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import {
retrieveAllAccountsMetadata,
retrieveFullyDecryptedAccount,

10
src/views/LogView.vue

@ -58,12 +58,15 @@ import { Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue";
import { db } from "../db/index";
import { Log } from "../db/tables/logs";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
import * as databaseUtil from "../db/databaseUtil";
interface Log {
date: string;
message: string;
}
@Component({
components: {
QuickNav,
@ -74,8 +77,8 @@ export default class LogView extends Vue {
$router!: Router;
loading = true;
logs: Log[] = [];
error: string | null = null;
logs: Log[] = [];
memoryLogs: string[] = [];
async mounted() {
@ -87,7 +90,6 @@ export default class LogView extends Vue {
this.error = null; // Clear any previous errors
this.memoryLogs = databaseUtil.memoryLogs;
const allLogs: Log[] = [];
const platformService = PlatformServiceFactory.getInstance();
const queryResult = await platformService.dbQuery(
"SELECT * FROM logs ORDER BY date DESC",

20
src/views/NewEditProjectView.vue

@ -154,12 +154,7 @@
v-model:zoom="zoom"
:center="[0, 0]"
class="!z-40 rounded-md"
@click="
(event) => {
latitude = event.latlng.lat;
longitude = event.latlng.lng;
}
"
@click="onMapClick"
>
<l-tile-layer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
@ -230,6 +225,7 @@ import {
import { Component, Vue } from "vue-facing-decorator";
import { LMap, LMarker, LTileLayer } from "@vue-leaflet/vue-leaflet";
import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import { LeafletMouseEvent } from "leaflet";
import ImageMethodDialog from "../components/ImageMethodDialog.vue";
import QuickNav from "../components/QuickNav.vue";
@ -239,8 +235,7 @@ import {
NotificationIface,
} from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { PlanVerifiableCredential } from "../interfaces";
import { PlanActionClaim } from "../interfaces/claims";
import {
createEndorserJwtVcFromClaim,
getHeaders,
@ -277,7 +272,7 @@ export default class NewEditProjectView extends Vue {
endDateInput?: string;
endTimeInput?: string;
errorMessage = "";
fullClaim: PlanVerifiableCredential = {
fullClaim: PlanActionClaim = {
"@context": "https://schema.org",
"@type": "PlanAction",
name: "",
@ -445,7 +440,7 @@ export default class NewEditProjectView extends Vue {
private async saveProject() {
// Make a claim
const vcClaim: PlanVerifiableCredential = this.fullClaim;
const vcClaim: PlanActionClaim = this.fullClaim;
if (this.projectId) {
vcClaim.lastClaimId = this.lastClaimJwtId;
}
@ -823,5 +818,10 @@ export default class NewEditProjectView extends Vue {
7000,
);
}
onMapClick(event: LeafletMouseEvent) {
this.latitude = event.latlng.lat;
this.longitude = event.latlng.lng;
}
}
</script>

5
src/views/OfferDetailsView.vue

@ -181,7 +181,6 @@ import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue";
import { NotificationIface } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { GenericCredWrapper, OfferClaim } from "../interfaces";
import {
createAndSubmitOffer,
@ -314,7 +313,9 @@ export default class OfferDetailsView extends Vue {
group: "alert",
type: "danger",
title: "Error",
text: err.message || "There was an error loading the offer details.",
text:
(err as Error)?.message ||
"There was an error loading the offer details.",
},
5000,
);

1
src/views/OnboardMeetingListView.vue

@ -90,7 +90,6 @@ import { Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil";
import {
errorStringForLog,

8
src/views/OnboardMeetingMembersView.vue

@ -123,7 +123,9 @@ export default class OnboardMeetingMembersView extends Vue {
const member = response.data?.data;
if (!member) {
if (!this.firstName) {
this.$refs.userNameDialog.open(this.addMemberToMeeting);
(this.$refs.userNameDialog as UserNameDialog).open(
this.addMemberToMeeting,
);
// addMemberToMeeting sets isLoading to false
} else {
await this.addMemberToMeeting(this.firstName);
@ -136,7 +138,9 @@ export default class OnboardMeetingMembersView extends Vue {
} else {
// must be already in the right meeting
if (!this.firstName) {
this.$refs.userNameDialog.open(this.updateMemberInMeeting);
(this.$refs.userNameDialog as UserNameDialog).open(
this.updateMemberInMeeting,
);
// updateMemberInMeeting sets isLoading to false
} else {
await this.updateMemberInMeeting(this.firstName);

4
src/views/OnboardMeetingSetupView.vue

@ -271,12 +271,12 @@
<script lang="ts">
import { Component, Vue } from "vue-facing-decorator";
import { useClipboard } from "@vueuse/core";
import { RouteLocationNormalizedLoaded, Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue";
import MembersList from "../components/MembersList.vue";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil";
import {
errorStringForLog,
@ -315,6 +315,8 @@ export default class OnboardMeetingView extends Vue {
notification: { group: string; type: string; title: string; text: string },
timeout?: number,
) => void;
$route!: RouteLocationNormalizedLoaded;
$router!: Router;
currentMeeting: ServerMeeting | null = null;
newOrUpdatedMeetingInputs: MeetingSetupInputs | null = null;

10
src/views/ProjectViewView.vue

@ -447,7 +447,7 @@
<ul class="mt-2 text-sm border-t border-slate-300">
<li
v-for="give in givesToThis"
:key="give.id"
:key="give.jwtId"
class="py-1.5 border-b border-slate-300"
>
<div class="flex justify-between gap-4">
@ -644,11 +644,7 @@ import EntityIcon from "../components/EntityIcon.vue";
import ProjectIcon from "../components/ProjectIcon.vue";
import { APP_SERVER, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import {
db,
logConsoleAndDb,
retrieveSettingsForActiveAccount,
} from "../db/index";
import { logConsoleAndDb } from "../db/index";
import { Contact } from "../db/tables/contacts";
import * as libsUtil from "../libs/util";
import * as serverUtil from "../libs/endorserServer";
@ -1476,7 +1472,7 @@ export default class ProjectViewView extends Vue {
} else {
logger.error("Got error submitting the confirmation:", result);
const message =
(result.error?.error as string) ||
(result.error as string) ||
"There was a problem submitting the confirmation.";
this.$notify(
{

11
src/views/QuickActionBvcEndView.vue

@ -146,11 +146,6 @@ import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue";
import { NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import {
accountsDBPromise,
db,
retrieveSettingsForActiveAccount,
} from "../db/index";
import { Contact } from "../db/tables/contacts";
import {
GenericCredWrapper,
@ -175,8 +170,9 @@ import { retrieveAllAccountsMetadata } from "@/libs/util";
TopMessage,
},
})
export default class QuickActionBvcBeginView extends Vue {
export default class QuickActionBvcEndView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
$router!: Router;
activeDid = "";
allContacts: Array<Contact> = [];
@ -191,6 +187,9 @@ export default class QuickActionBvcBeginView extends Vue {
someoneGave = false;
supplyGiftDetails = false;
// Method used in template
claimSpecialDescription = claimSpecialDescription;
async created() {
this.loadingConfirms = true;

1
src/views/RecentOffersToUserView.vue

@ -78,7 +78,6 @@ import InfiniteScroll from "../components/InfiniteScroll.vue";
import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { Contact } from "../db/tables/contacts";
import { OfferSummaryRecord } from "../interfaces";
import {

1
src/views/ShareMyContactInfoView.vue

@ -48,7 +48,6 @@ import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue";
import { NotificationIface, APP_SERVER } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { retrieveFullyDecryptedAccount } from "../libs/util";
import { generateEndorserJwtUrlForAccount } from "../libs/endorserServer";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";

2
src/views/SharedPhotoView.vue

@ -80,8 +80,6 @@ import {
NotificationIface,
} from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { accessToken } from "../libs/crypto";
import { base64ToBlob, SHARED_PHOTO_BASE64_KEY } from "../libs/util";
import { logger } from "../utils/logger";

2
src/views/StartView.vue

@ -105,7 +105,7 @@ import { Router } from "vue-router";
import { AppString, PASSKEYS_ENABLED } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import {
registerSaveAndActivatePasskey,
retrieveAccountCount,

13
src/views/TestView.vue

@ -341,7 +341,6 @@ import { Router } from "vue-router";
import QuickNav from "../components/QuickNav.vue";
import { AppString, NotificationIface } from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import * as vcLib from "../libs/crypto/vc";
import * as cryptoLib from "../libs/crypto";
@ -352,7 +351,6 @@ import {
verifyJwtWebCrypto,
} from "../libs/crypto/vc/passkeyDidPeer";
import {
AccountKeyInfo,
blobToBase64,
retrieveAccountMetadata,
registerAndSavePasskey,
@ -361,6 +359,7 @@ import {
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Temp } from "@/db/tables/temp";
import { Account } from "../db/tables/accounts";
const inputFileNameRef = ref<Blob>();
const TEST_PAYLOAD = {
@ -498,7 +497,7 @@ export default class Help extends Vue {
}
public async createJwtSimplewebauthn() {
const account: AccountKeyInfo | undefined = await retrieveAccountMetadata(
const account: Account | undefined = await retrieveAccountMetadata(
this.activeDid || "",
);
if (!vcLib.isFromPasskey(account)) {
@ -515,7 +514,7 @@ export default class Help extends Vue {
}
public async createJwtNavigator() {
const account: AccountKeyInfo | undefined = await retrieveAccountMetadata(
const account: Account | undefined = await retrieveAccountMetadata(
this.activeDid || "",
);
if (!vcLib.isFromPasskey(account)) {
@ -533,11 +532,9 @@ export default class Help extends Vue {
public async verifyP256() {
const decoded = await verifyJwtP256(
this.credIdHex as string,
this.activeDid as string,
this.peerSetup?.authenticatorData as ArrayBuffer,
this.peerSetup?.challenge as Uint8Array,
this.peerSetup?.clientDataJsonBase64Url as Base64URLString,
this.peerSetup?.signature as Base64URLString,
);
logger.log("decoded", decoded);
@ -557,11 +554,9 @@ export default class Help extends Vue {
public async verifyWebCrypto() {
const decoded = await verifyJwtWebCrypto(
this.credIdHex as string,
this.activeDid as string,
this.peerSetup?.authenticatorData as ArrayBuffer,
this.peerSetup?.challenge as Uint8Array,
this.peerSetup?.clientDataJsonBase64Url as Base64URLString,
this.peerSetup?.signature as Base64URLString,
);
logger.log("decoded", decoded);
@ -583,11 +578,9 @@ export default class Help extends Vue {
const challenge = clientData.challenge;
const signatureB64URL = pieces[2];
const decoded = await verifyJwtWebCrypto(
this.credIdHex as string,
did,
authData,
challenge,
payload["ClientDataJSONB64URL"],
signatureB64URL,
);
logger.log("decoded", decoded);

1
src/views/UserProfileView.vue

@ -112,7 +112,6 @@ import {
NotificationIface,
} from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db } from "../db/index";
import { Contact } from "../db/tables/contacts";
import { didInfo, getHeaders } from "../libs/endorserServer";
import { UserProfile } from "../libs/partnerServer";

Loading…
Cancel
Save