cache the passkey JWANT access token for multiple signatures
This commit is contained in:
@@ -26,6 +26,7 @@ export type Settings = {
|
|||||||
lastName?: string; // deprecated - put all names in firstName
|
lastName?: string; // deprecated - put all names in firstName
|
||||||
lastNotifiedClaimId?: string;
|
lastNotifiedClaimId?: string;
|
||||||
lastViewedClaimId?: string;
|
lastViewedClaimId?: string;
|
||||||
|
passkeyExpirationMinutes?: number; // passkey access token time-to-live in minutes
|
||||||
profileImageUrl?: string;
|
profileImageUrl?: string;
|
||||||
reminderTime?: number; // Time in milliseconds since UNIX epoch for reminders
|
reminderTime?: number; // Time in milliseconds since UNIX epoch for reminders
|
||||||
reminderOn?: boolean; // Toggle to enable or disable reminders
|
reminderOn?: boolean; // Toggle to enable or disable reminders
|
||||||
@@ -46,7 +47,7 @@ export type Settings = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function isAnyFeedFilterOn(settings: Settings): boolean {
|
export function isAnyFeedFilterOn(settings: Settings): boolean {
|
||||||
return !!(settings.filterFeedByNearby || settings.filterFeedByVisible);
|
return !!(settings?.filterFeedByNearby || settings?.filterFeedByVisible);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -60,3 +61,5 @@ export const SettingsSchema = {
|
|||||||
* Constants.
|
* Constants.
|
||||||
*/
|
*/
|
||||||
export const MASTER_SETTINGS_KEY = 1;
|
export const MASTER_SETTINGS_KEY = 1;
|
||||||
|
|
||||||
|
export const DEFAULT_PASSKEY_EXPIRATION_MINUTES = 15;
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ export const generateSeed = (): string => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retreive an access token
|
* Retrieve an access token, or "" if no DID is provided.
|
||||||
*
|
*
|
||||||
* @return {*}
|
* @return {*}
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ import * as R from "ramda";
|
|||||||
import { DEFAULT_IMAGE_API_SERVER } from "@/constants/app";
|
import { DEFAULT_IMAGE_API_SERVER } from "@/constants/app";
|
||||||
import { Contact } from "@/db/tables/contacts";
|
import { Contact } from "@/db/tables/contacts";
|
||||||
import { accessToken } from "@/libs/crypto";
|
import { accessToken } from "@/libs/crypto";
|
||||||
import { NonsensitiveDexie } from "@/db/index";
|
import { db, NonsensitiveDexie } from "@/db/index";
|
||||||
import { getAccount } from "@/libs/util";
|
import { getAccount, getPasskeyExpirationSeconds } from "@/libs/util";
|
||||||
import { createEndorserJwtForKey, KeyMeta } from "@/libs/crypto/vc";
|
import { createEndorserJwtForKey, KeyMeta } from "@/libs/crypto/vc";
|
||||||
|
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
||||||
|
|
||||||
export const SCHEMA_ORG_CONTEXT = "https://schema.org";
|
export const SCHEMA_ORG_CONTEXT = "https://schema.org";
|
||||||
// the object in RegisterAction claims
|
// the object in RegisterAction claims
|
||||||
@@ -447,12 +448,57 @@ export function didInfo(
|
|||||||
return didInfoForContact(did, activeDid, contact, allMyDids).displayName;
|
return didInfoForContact(did, activeDid, contact, allMyDids).displayName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let passkeyAccessToken: string = "";
|
||||||
|
let passkeyTokenExpirationEpochSeconds: number = 0;
|
||||||
|
|
||||||
|
export function clearPasskeyToken() {
|
||||||
|
passkeyAccessToken = "";
|
||||||
|
passkeyTokenExpirationEpochSeconds = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function tokenExpiryTimeDescription() {
|
||||||
|
if (
|
||||||
|
!passkeyAccessToken ||
|
||||||
|
passkeyTokenExpirationEpochSeconds < new Date().getTime() / 1000
|
||||||
|
) {
|
||||||
|
return "Token has expired";
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
"Token expires at " +
|
||||||
|
new Date(passkeyTokenExpirationEpochSeconds * 1000).toLocaleString()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the headers for a request, potentially including Authorization
|
||||||
|
*/
|
||||||
export async function getHeaders(did?: string) {
|
export async function getHeaders(did?: string) {
|
||||||
const headers: { "Content-Type": string; Authorization?: string } = {
|
const headers: { "Content-Type": string; Authorization?: string } = {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
};
|
};
|
||||||
if (did) {
|
if (did) {
|
||||||
const token = await accessToken(did);
|
let token;
|
||||||
|
const account = await getAccount(did);
|
||||||
|
if (account?.passkeyCredIdHex) {
|
||||||
|
if (
|
||||||
|
passkeyAccessToken &&
|
||||||
|
passkeyTokenExpirationEpochSeconds > Date.now() / 1000
|
||||||
|
) {
|
||||||
|
// there's an active current passkey token
|
||||||
|
token = passkeyAccessToken;
|
||||||
|
} else {
|
||||||
|
// there's no current passkey token or it's expired
|
||||||
|
token = await accessToken(did);
|
||||||
|
|
||||||
|
passkeyAccessToken = token;
|
||||||
|
const passkeyExpirationSeconds = await getPasskeyExpirationSeconds();
|
||||||
|
passkeyTokenExpirationEpochSeconds =
|
||||||
|
Date.now() / 1000 + passkeyExpirationSeconds;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
token = await accessToken(did);
|
||||||
|
}
|
||||||
headers["Authorization"] = "Bearer " + token;
|
headers["Authorization"] = "Bearer " + token;
|
||||||
} else {
|
} else {
|
||||||
// it's often OK to request without auth; we assume necessary checks are done earlier
|
// it's often OK to request without auth; we assume necessary checks are done earlier
|
||||||
|
|||||||
@@ -1,21 +1,20 @@
|
|||||||
// many of these are also found in endorser-mobile utility.ts
|
// many of these are also found in endorser-mobile utility.ts
|
||||||
|
|
||||||
import axios, { AxiosResponse } from "axios";
|
import axios, { AxiosResponse } from "axios";
|
||||||
import { IIdentifier } from "@veramo/core";
|
|
||||||
import { useClipboard } from "@vueuse/core";
|
import { useClipboard } from "@vueuse/core";
|
||||||
|
|
||||||
import { DEFAULT_PUSH_SERVER } from "@/constants/app";
|
import { DEFAULT_PUSH_SERVER } from "@/constants/app";
|
||||||
import { accountsDB, db } from "@/db/index";
|
import { accountsDB, db } from "@/db/index";
|
||||||
import { Account } from "@/db/tables/accounts";
|
import { Account } from "@/db/tables/accounts";
|
||||||
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
import {DEFAULT_PASSKEY_EXPIRATION_MINUTES, MASTER_SETTINGS_KEY} from "@/db/tables/settings";
|
||||||
import { deriveAddress, generateSeed, newIdentifier } from "@/libs/crypto";
|
import { deriveAddress, generateSeed, newIdentifier } from "@/libs/crypto";
|
||||||
import { GenericCredWrapper, containsHiddenDid } from "@/libs/endorserServer";
|
import { GenericCredWrapper, containsHiddenDid } from "@/libs/endorserServer";
|
||||||
import * as serverUtil from "@/libs/endorserServer";
|
import * as serverUtil from "@/libs/endorserServer";
|
||||||
import { registerCredential } from "@/libs/crypto/vc/passkeyDidPeer";
|
import { registerCredential } from "@/libs/crypto/vc/passkeyDidPeer";
|
||||||
|
|
||||||
import { Buffer } from "buffer";
|
import { Buffer } from "buffer";
|
||||||
import {KeyMeta} from "@/libs/crypto/vc";
|
import { KeyMeta } from "@/libs/crypto/vc";
|
||||||
import {createPeerDid} from "@/libs/crypto/vc/didPeer";
|
import { createPeerDid } from "@/libs/crypto/vc/didPeer";
|
||||||
|
|
||||||
export const PRIVACY_MESSAGE =
|
export const PRIVACY_MESSAGE =
|
||||||
"The data you send will be visible to the world -- except: your IDs and the IDs of anyone you tag will stay private, only visible to them and others you explicitly allow.";
|
"The data you send will be visible to the world -- except: your IDs and the IDs of anyone you tag will stay private, only visible to them and others you explicitly allow.";
|
||||||
@@ -273,6 +272,15 @@ export const registerSaveAndActivatePasskey = async (
|
|||||||
return account;
|
return account;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getPasskeyExpirationSeconds = async (): Promise<number> => {
|
||||||
|
await db.open();
|
||||||
|
const settings = await db.settings.get(MASTER_SETTINGS_KEY);
|
||||||
|
const passkeyExpirationSeconds =
|
||||||
|
(settings?.passkeyExpirationMinutes ?? DEFAULT_PASSKEY_EXPIRATION_MINUTES) *
|
||||||
|
60;
|
||||||
|
return passkeyExpirationSeconds;
|
||||||
|
};
|
||||||
|
|
||||||
export const sendTestThroughPushServer = async (
|
export const sendTestThroughPushServer = async (
|
||||||
subscriptionJSON: PushSubscriptionJSON,
|
subscriptionJSON: PushSubscriptionJSON,
|
||||||
skipFilter: boolean,
|
skipFilter: boolean,
|
||||||
|
|||||||
@@ -152,7 +152,7 @@
|
|||||||
|
|
||||||
<div class="text-blue-500 text-sm font-bold">
|
<div class="text-blue-500 text-sm font-bold">
|
||||||
<router-link :to="{ path: '/did/' + encodeURIComponent(activeDid) }">
|
<router-link :to="{ path: '/did/' + encodeURIComponent(activeDid) }">
|
||||||
Activity
|
Your Activity
|
||||||
</router-link>
|
</router-link>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -216,7 +216,6 @@
|
|||||||
<div class="mb-2 font-bold">Location</div>
|
<div class="mb-2 font-bold">Location</div>
|
||||||
<router-link
|
<router-link
|
||||||
:to="{ name: 'search-area' }"
|
:to="{ name: 'search-area' }"
|
||||||
v-if="activeDid"
|
|
||||||
class="block w-full text-center text-m bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mb-2 mt-6"
|
class="block w-full text-center text-m bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mb-2 mt-6"
|
||||||
>
|
>
|
||||||
Set Search Area…
|
Set Search Area…
|
||||||
@@ -622,6 +621,26 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-between">
|
||||||
|
<span>
|
||||||
|
<span class="text-slate-500 text-sm font-bold mb-2">
|
||||||
|
Passkey Expiration Minutes
|
||||||
|
</span>
|
||||||
|
<br />
|
||||||
|
<span class="text-sm ml-2">
|
||||||
|
{{ passkeyExpirationDescription }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
<div class="relative ml-2">
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
class="border border-slate-400 rounded px-2 py-2 text-center w-20"
|
||||||
|
v-model="passkeyExpirationMinutes"
|
||||||
|
@change="updatePasskeyExpiration"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<label
|
<label
|
||||||
for="toggleShowGeneralAdvanced"
|
for="toggleShowGeneralAdvanced"
|
||||||
class="flex items-center justify-between cursor-pointer mt-4"
|
class="flex items-center justify-between cursor-pointer mt-4"
|
||||||
@@ -667,7 +686,7 @@ import ImageMethodDialog from "@/components/ImageMethodDialog.vue";
|
|||||||
import QuickNav from "@/components/QuickNav.vue";
|
import QuickNav from "@/components/QuickNav.vue";
|
||||||
import TopMessage from "@/components/TopMessage.vue";
|
import TopMessage from "@/components/TopMessage.vue";
|
||||||
import {
|
import {
|
||||||
AppString,
|
AppString, DEFAULT_ENDORSER_API_SERVER,
|
||||||
DEFAULT_IMAGE_API_SERVER,
|
DEFAULT_IMAGE_API_SERVER,
|
||||||
DEFAULT_PUSH_SERVER,
|
DEFAULT_PUSH_SERVER,
|
||||||
IMAGE_TYPE_PROFILE,
|
IMAGE_TYPE_PROFILE,
|
||||||
@@ -675,14 +694,20 @@ import {
|
|||||||
} from "@/constants/app";
|
} from "@/constants/app";
|
||||||
import { db, accountsDB } from "@/db/index";
|
import { db, accountsDB } from "@/db/index";
|
||||||
import { Account } from "@/db/tables/accounts";
|
import { Account } from "@/db/tables/accounts";
|
||||||
import { MASTER_SETTINGS_KEY, Settings } from "@/db/tables/settings";
|
|
||||||
import { accessToken } from "@/libs/crypto";
|
|
||||||
import {
|
import {
|
||||||
|
DEFAULT_PASSKEY_EXPIRATION_MINUTES,
|
||||||
|
MASTER_SETTINGS_KEY,
|
||||||
|
Settings,
|
||||||
|
} from "@/db/tables/settings";
|
||||||
|
import {
|
||||||
|
clearPasskeyToken,
|
||||||
ErrorResponse,
|
ErrorResponse,
|
||||||
EndorserRateLimits,
|
EndorserRateLimits,
|
||||||
ImageRateLimits,
|
|
||||||
fetchEndorserRateLimits,
|
fetchEndorserRateLimits,
|
||||||
fetchImageRateLimits,
|
fetchImageRateLimits,
|
||||||
|
getHeaders,
|
||||||
|
ImageRateLimits,
|
||||||
|
tokenExpiryTimeDescription,
|
||||||
} from "@/libs/endorserServer";
|
} from "@/libs/endorserServer";
|
||||||
import { getAccount } from "@/libs/util";
|
import { getAccount } from "@/libs/util";
|
||||||
|
|
||||||
@@ -713,6 +738,9 @@ export default class AccountViewView extends Vue {
|
|||||||
limitsMessage = "";
|
limitsMessage = "";
|
||||||
loadingLimits = false;
|
loadingLimits = false;
|
||||||
notificationMaybeChanged = false;
|
notificationMaybeChanged = false;
|
||||||
|
passkeyExpirationDescription = "";
|
||||||
|
passkeyExpirationMinutes = DEFAULT_PASSKEY_EXPIRATION_MINUTES;
|
||||||
|
previousPasskeyExpirationMinutes = DEFAULT_PASSKEY_EXPIRATION_MINUTES;
|
||||||
profileImageUrl?: string;
|
profileImageUrl?: string;
|
||||||
publicHex = "";
|
publicHex = "";
|
||||||
publicBase64 = "";
|
publicBase64 = "";
|
||||||
@@ -745,12 +773,32 @@ export default class AccountViewView extends Vue {
|
|||||||
await this.initializeState();
|
await this.initializeState();
|
||||||
await this.processIdentity();
|
await this.processIdentity();
|
||||||
|
|
||||||
|
this.passkeyExpirationDescription = tokenExpiryTimeDescription();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Beware! I've seen where this "ready" never resolves.
|
||||||
|
*/
|
||||||
const registration = await navigator.serviceWorker.ready;
|
const registration = await navigator.serviceWorker.ready;
|
||||||
this.subscription = await registration.pushManager.getSubscription();
|
this.subscription = await registration.pushManager.getSubscription();
|
||||||
this.isSubscribed = !!this.subscription;
|
this.isSubscribed = !!this.subscription;
|
||||||
|
console.log("Got to the end of 'mounted' call.");
|
||||||
|
/**
|
||||||
|
* Beware! I've seen where we never get to this point because "ready" never resolves.
|
||||||
|
*/
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("Mount error:", error);
|
console.error(
|
||||||
this.handleError(error);
|
"Telling user to clear cache at page create because:",
|
||||||
|
error,
|
||||||
|
);
|
||||||
|
this.$notify(
|
||||||
|
{
|
||||||
|
group: "alert",
|
||||||
|
type: "danger",
|
||||||
|
title: "Error Loading Account",
|
||||||
|
text: "Clear your cache and start over (after data backup).",
|
||||||
|
},
|
||||||
|
-1,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -780,6 +828,10 @@ export default class AccountViewView extends Vue {
|
|||||||
this.showContactGives = !!settings?.showContactGivesInline;
|
this.showContactGives = !!settings?.showContactGivesInline;
|
||||||
this.hideRegisterPromptOnNewContact =
|
this.hideRegisterPromptOnNewContact =
|
||||||
!!settings?.hideRegisterPromptOnNewContact;
|
!!settings?.hideRegisterPromptOnNewContact;
|
||||||
|
this.passkeyExpirationMinutes =
|
||||||
|
(settings?.passkeyExpirationMinutes as number) ??
|
||||||
|
DEFAULT_PASSKEY_EXPIRATION_MINUTES;
|
||||||
|
this.previousPasskeyExpirationMinutes = this.passkeyExpirationMinutes;
|
||||||
this.showGeneralAdvanced = !!settings?.showGeneralAdvanced;
|
this.showGeneralAdvanced = !!settings?.showGeneralAdvanced;
|
||||||
this.showShortcutBvc = !!settings?.showShortcutBvc;
|
this.showShortcutBvc = !!settings?.showShortcutBvc;
|
||||||
this.warnIfProdServer = !!settings?.warnIfProdServer;
|
this.warnIfProdServer = !!settings?.warnIfProdServer;
|
||||||
@@ -835,11 +887,11 @@ export default class AccountViewView extends Vue {
|
|||||||
this.publicHex = identity.keys[0].publicKeyHex;
|
this.publicHex = identity.keys[0].publicKeyHex;
|
||||||
this.publicBase64 = Buffer.from(this.publicHex, "hex").toString("base64");
|
this.publicBase64 = Buffer.from(this.publicHex, "hex").toString("base64");
|
||||||
this.derivationPath = identity.keys[0].meta?.derivationPath as string;
|
this.derivationPath = identity.keys[0].meta?.derivationPath as string;
|
||||||
this.checkLimitsFor(this.activeDid);
|
await this.checkLimitsFor(this.activeDid);
|
||||||
} else if (account?.publicKeyHex) {
|
} else if (account?.publicKeyHex) {
|
||||||
this.publicHex = account.publicKeyHex as string;
|
this.publicHex = account.publicKeyHex as string;
|
||||||
this.publicBase64 = Buffer.from(this.publicHex, "hex").toString("base64");
|
this.publicBase64 = Buffer.from(this.publicHex, "hex").toString("base64");
|
||||||
this.checkLimitsFor(this.activeDid);
|
await this.checkLimitsFor(this.activeDid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -868,75 +920,18 @@ export default class AccountViewView extends Vue {
|
|||||||
this.notificationMaybeChanged = true;
|
this.notificationMaybeChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles errors and updates the component's state accordingly.
|
|
||||||
* @param {Error} err - The error object.
|
|
||||||
*/
|
|
||||||
handleError(err: unknown) {
|
|
||||||
if (
|
|
||||||
err instanceof Error &&
|
|
||||||
err.message ===
|
|
||||||
"Attempted to load account records with no identifier available."
|
|
||||||
) {
|
|
||||||
this.limitsMessage = "No identifier.";
|
|
||||||
} else {
|
|
||||||
console.error("Telling user to clear cache at page create because:", err);
|
|
||||||
this.$notify(
|
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "danger",
|
|
||||||
title: "Error Loading Account",
|
|
||||||
text: "Clear your cache and start over (after data backup).",
|
|
||||||
},
|
|
||||||
-1,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public async updateShowContactAmounts() {
|
public async updateShowContactAmounts() {
|
||||||
try {
|
await db.open();
|
||||||
await db.open();
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
await db.settings.update(MASTER_SETTINGS_KEY, {
|
showContactGivesInline: this.showContactGives,
|
||||||
showContactGivesInline: this.showContactGives,
|
});
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
this.$notify(
|
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "danger",
|
|
||||||
title: "Error Updating Contact Setting",
|
|
||||||
text: "The setting may not have saved. Try again, maybe after restarting the app.",
|
|
||||||
},
|
|
||||||
-1,
|
|
||||||
);
|
|
||||||
console.error(
|
|
||||||
"Telling user to try again after contact-amounts setting update because:",
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateShowGeneralAdvanced() {
|
public async updateShowGeneralAdvanced() {
|
||||||
try {
|
await db.open();
|
||||||
await db.open();
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
await db.settings.update(MASTER_SETTINGS_KEY, {
|
showGeneralAdvanced: this.showGeneralAdvanced,
|
||||||
showGeneralAdvanced: this.showGeneralAdvanced,
|
});
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
this.$notify(
|
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "danger",
|
|
||||||
title: "Error Updating Advanced Setting",
|
|
||||||
text: "The setting may not have saved. Try again, maybe after restarting the app.",
|
|
||||||
},
|
|
||||||
-1,
|
|
||||||
);
|
|
||||||
console.error(
|
|
||||||
"Telling user to try again after general-advanced setting update because:",
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateWarnIfProdServer(newSetting: boolean) {
|
public async updateWarnIfProdServer(newSetting: boolean) {
|
||||||
@@ -963,71 +958,35 @@ export default class AccountViewView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async updateWarnIfTestServer(newSetting: boolean) {
|
public async updateWarnIfTestServer(newSetting: boolean) {
|
||||||
try {
|
await db.open();
|
||||||
await db.open();
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
await db.settings.update(MASTER_SETTINGS_KEY, {
|
warnIfTestServer: newSetting,
|
||||||
warnIfTestServer: newSetting,
|
});
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
this.$notify(
|
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "danger",
|
|
||||||
title: "Error Updating Test Warning",
|
|
||||||
text: "The setting may not have saved. Try again, maybe after restarting the app.",
|
|
||||||
},
|
|
||||||
-1,
|
|
||||||
);
|
|
||||||
console.error(
|
|
||||||
"Telling user to try again after test-server-warning setting update because:",
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async toggleHideRegisterPromptOnNewContact() {
|
public async toggleHideRegisterPromptOnNewContact() {
|
||||||
const newSetting = !this.hideRegisterPromptOnNewContact;
|
const newSetting = !this.hideRegisterPromptOnNewContact;
|
||||||
try {
|
await db.open();
|
||||||
await db.open();
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
await db.settings.update(MASTER_SETTINGS_KEY, {
|
hideRegisterPromptOnNewContact: newSetting,
|
||||||
hideRegisterPromptOnNewContact: newSetting,
|
});
|
||||||
});
|
this.hideRegisterPromptOnNewContact = newSetting;
|
||||||
this.hideRegisterPromptOnNewContact = newSetting;
|
}
|
||||||
} catch (err) {
|
|
||||||
this.$notify(
|
public async updatePasskeyExpiration() {
|
||||||
{
|
await db.open();
|
||||||
group: "alert",
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
type: "danger",
|
passkeyExpirationMinutes: this.passkeyExpirationMinutes,
|
||||||
title: "Error Updating Setting",
|
});
|
||||||
text: "The setting may not have saved. Try again, maybe after restarting the app.",
|
clearPasskeyToken();
|
||||||
},
|
this.passkeyExpirationDescription = tokenExpiryTimeDescription();
|
||||||
-1,
|
|
||||||
);
|
|
||||||
console.error("Telling user to try again because:", err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async updateShowShortcutBvc(newSetting: boolean) {
|
public async updateShowShortcutBvc(newSetting: boolean) {
|
||||||
try {
|
await db.open();
|
||||||
await db.open();
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
await db.settings.update(MASTER_SETTINGS_KEY, {
|
showShortcutBvc: newSetting,
|
||||||
showShortcutBvc: newSetting,
|
});
|
||||||
});
|
|
||||||
} catch (err) {
|
|
||||||
this.$notify(
|
|
||||||
{
|
|
||||||
group: "alert",
|
|
||||||
type: "danger",
|
|
||||||
title: "Error Updating BVC Shortcut Setting",
|
|
||||||
text: "The setting may not have saved. Try again, maybe after restarting the app.",
|
|
||||||
},
|
|
||||||
-1,
|
|
||||||
);
|
|
||||||
console.error(
|
|
||||||
"Telling user to try again after BVC-shortcut setting update because:",
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1220,7 +1179,7 @@ export default class AccountViewView extends Vue {
|
|||||||
// the user was not known to be registered, but now they are (because we got no error) so let's record it
|
// the user was not known to be registered, but now they are (because we got no error) so let's record it
|
||||||
try {
|
try {
|
||||||
await db.open();
|
await db.open();
|
||||||
db.settings.update(MASTER_SETTINGS_KEY, {
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
isRegistered: true,
|
isRegistered: true,
|
||||||
});
|
});
|
||||||
this.isRegistered = true;
|
this.isRegistered = true;
|
||||||
@@ -1247,7 +1206,7 @@ export default class AccountViewView extends Vue {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
await db.open();
|
await db.open();
|
||||||
db.settings.update(MASTER_SETTINGS_KEY, {
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
isRegistered: false,
|
isRegistered: false,
|
||||||
});
|
});
|
||||||
this.isRegistered = false;
|
this.isRegistered = false;
|
||||||
@@ -1272,8 +1231,8 @@ export default class AccountViewView extends Vue {
|
|||||||
(data?.error?.message as string) || "Bad server response.";
|
(data?.error?.message as string) || "Bad server response.";
|
||||||
console.error(
|
console.error(
|
||||||
"Got bad response retrieving limits, which usually means user isn't registered.",
|
"Got bad response retrieving limits, which usually means user isn't registered.",
|
||||||
|
error,
|
||||||
);
|
);
|
||||||
//console.error(error);
|
|
||||||
} else {
|
} else {
|
||||||
this.limitsMessage = "Got an error retrieving limits.";
|
this.limitsMessage = "Got an error retrieving limits.";
|
||||||
console.error("Got some error retrieving limits:", error);
|
console.error("Got some error retrieving limits:", error);
|
||||||
@@ -1350,7 +1309,7 @@ export default class AccountViewView extends Vue {
|
|||||||
|
|
||||||
async onClickSaveApiServer() {
|
async onClickSaveApiServer() {
|
||||||
await db.open();
|
await db.open();
|
||||||
db.settings.update(MASTER_SETTINGS_KEY, {
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
apiServer: this.apiServerInput,
|
apiServer: this.apiServerInput,
|
||||||
});
|
});
|
||||||
this.apiServer = this.apiServerInput;
|
this.apiServer = this.apiServerInput;
|
||||||
@@ -1358,7 +1317,7 @@ export default class AccountViewView extends Vue {
|
|||||||
|
|
||||||
async onClickSavePushServer() {
|
async onClickSavePushServer() {
|
||||||
await db.open();
|
await db.open();
|
||||||
db.settings.update(MASTER_SETTINGS_KEY, {
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
webPushServer: this.webPushServerInput,
|
webPushServer: this.webPushServerInput,
|
||||||
});
|
});
|
||||||
this.webPushServer = this.webPushServerInput;
|
this.webPushServer = this.webPushServerInput;
|
||||||
@@ -1377,7 +1336,7 @@ export default class AccountViewView extends Vue {
|
|||||||
(this.$refs.imageMethodDialog as ImageMethodDialog).open(
|
(this.$refs.imageMethodDialog as ImageMethodDialog).open(
|
||||||
async (imgUrl) => {
|
async (imgUrl) => {
|
||||||
await db.open();
|
await db.open();
|
||||||
db.settings.update(MASTER_SETTINGS_KEY, {
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
profileImageUrl: imgUrl,
|
profileImageUrl: imgUrl,
|
||||||
});
|
});
|
||||||
this.profileImageUrl = imgUrl;
|
this.profileImageUrl = imgUrl;
|
||||||
@@ -1407,16 +1366,13 @@ export default class AccountViewView extends Vue {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const token = await accessToken(this.activeDid);
|
const headers = await getHeaders(this.activeDid);
|
||||||
|
this.passkeyExpirationDescription = tokenExpiryTimeDescription();
|
||||||
const response = await this.axios.delete(
|
const response = await this.axios.delete(
|
||||||
DEFAULT_IMAGE_API_SERVER +
|
DEFAULT_IMAGE_API_SERVER +
|
||||||
"/image/" +
|
"/image/" +
|
||||||
encodeURIComponent(this.profileImageUrl),
|
encodeURIComponent(this.profileImageUrl),
|
||||||
{
|
{ headers },
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
if (response.status === 204) {
|
if (response.status === 204) {
|
||||||
// don't bother with a notification
|
// don't bother with a notification
|
||||||
@@ -1436,7 +1392,7 @@ export default class AccountViewView extends Vue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await db.open();
|
await db.open();
|
||||||
db.settings.update(MASTER_SETTINGS_KEY, {
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
profileImageUrl: undefined,
|
profileImageUrl: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1448,7 +1404,7 @@ export default class AccountViewView extends Vue {
|
|||||||
console.error("The image was already deleted:", error);
|
console.error("The image was already deleted:", error);
|
||||||
|
|
||||||
await db.open();
|
await db.open();
|
||||||
db.settings.update(MASTER_SETTINGS_KEY, {
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
||||||
profileImageUrl: undefined,
|
profileImageUrl: undefined,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@
|
|||||||
{{ new Date(record.issuedAt).toLocaleString() }}
|
{{ new Date(record.issuedAt).toLocaleString() }}
|
||||||
</td>
|
</td>
|
||||||
<td class="p-1">
|
<td class="p-1">
|
||||||
<span v-if="record.agentDid == contact.did">
|
<span v-if="record.agentDid == contact?.did">
|
||||||
<div class="font-bold">
|
<div class="font-bold">
|
||||||
{{ displayAmount(record.unit, record.amount) }}
|
{{ displayAmount(record.unit, record.amount) }}
|
||||||
<span v-if="record.amountConfirmed" title="Confirmed">
|
<span v-if="record.amountConfirmed" title="Confirmed">
|
||||||
@@ -71,7 +71,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="p-1">
|
<td class="p-1">
|
||||||
<span v-if="record.agentDid == contact.did">
|
<span v-if="record.agentDid == contact?.did">
|
||||||
<fa icon="arrow-left" class="text-slate-400 fa-fw" />
|
<fa icon="arrow-left" class="text-slate-400 fa-fw" />
|
||||||
</span>
|
</span>
|
||||||
<span v-else>
|
<span v-else>
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="p-1">
|
<td class="p-1">
|
||||||
<span v-if="record.agentDid != contact.did">
|
<span v-if="record.agentDid != contact?.did">
|
||||||
<div class="font-bold">
|
<div class="font-bold">
|
||||||
{{ displayAmount(record.unit, record.amount) }}
|
{{ displayAmount(record.unit, record.amount) }}
|
||||||
<span v-if="record.amountConfirmed" title="Confirmed">
|
<span v-if="record.amountConfirmed" title="Confirmed">
|
||||||
@@ -105,7 +105,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { AxiosError } from "axios";
|
import { AxiosError, AxiosRequestHeaders } from "axios";
|
||||||
import * as R from "ramda";
|
import * as R from "ramda";
|
||||||
import { Component, Vue } from "vue-facing-decorator";
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
|
|
||||||
@@ -114,7 +114,6 @@ import { NotificationIface } from "@/constants/app";
|
|||||||
import { accountsDB, db } from "@/db/index";
|
import { accountsDB, db } from "@/db/index";
|
||||||
import { Contact } from "@/db/tables/contacts";
|
import { Contact } from "@/db/tables/contacts";
|
||||||
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||||
import { accessToken } from "@/libs/crypto";
|
|
||||||
import {
|
import {
|
||||||
AgreeVerifiableCredential,
|
AgreeVerifiableCredential,
|
||||||
createEndorserJwtVcFromClaim,
|
createEndorserJwtVcFromClaim,
|
||||||
@@ -271,11 +270,7 @@ export default class ContactAmountssView extends Vue {
|
|||||||
// Make the xhr request payload
|
// Make the xhr request payload
|
||||||
const payload = JSON.stringify({ jwtEncoded: vcJwt });
|
const payload = JSON.stringify({ jwtEncoded: vcJwt });
|
||||||
const url = this.apiServer + "/api/v2/claim";
|
const url = this.apiServer + "/api/v2/claim";
|
||||||
const token = await accessToken(this.activeDid);
|
const headers = getHeaders(this.activeDid) as AxiosRequestHeaders;
|
||||||
const headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: "Bearer " + token,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await this.axios.post(url, payload, { headers });
|
const resp = await this.axios.post(url, payload, { headers });
|
||||||
|
|||||||
@@ -186,10 +186,10 @@ import {
|
|||||||
constructGive,
|
constructGive,
|
||||||
createAndSubmitGive,
|
createAndSubmitGive,
|
||||||
didInfo,
|
didInfo,
|
||||||
|
getHeaders,
|
||||||
getPlanFromCache,
|
getPlanFromCache,
|
||||||
} from "@/libs/endorserServer";
|
} from "@/libs/endorserServer";
|
||||||
import * as libsUtil from "@/libs/util";
|
import * as libsUtil from "@/libs/util";
|
||||||
import { accessToken } from "@/libs/crypto";
|
|
||||||
import { Contact } from "@/db/tables/contacts";
|
import { Contact } from "@/db/tables/contacts";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -380,16 +380,12 @@ export default class GiftedDetails extends Vue {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const token = await accessToken(this.activeDid);
|
const headers = await getHeaders(this.activeDid);
|
||||||
const response = await this.axios.delete(
|
const response = await this.axios.delete(
|
||||||
DEFAULT_IMAGE_API_SERVER +
|
DEFAULT_IMAGE_API_SERVER +
|
||||||
"/image/" +
|
"/image/" +
|
||||||
encodeURIComponent(this.imageUrl),
|
encodeURIComponent(this.imageUrl),
|
||||||
{
|
{ headers },
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
if (response.status === 204) {
|
if (response.status === 204) {
|
||||||
// don't bother with a notification
|
// don't bother with a notification
|
||||||
|
|||||||
@@ -173,7 +173,7 @@
|
|||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import "leaflet/dist/leaflet.css";
|
import "leaflet/dist/leaflet.css";
|
||||||
import { AxiosError } from "axios";
|
import { AxiosError, AxiosRequestHeaders } from "axios";
|
||||||
import { DateTime } from "luxon";
|
import { DateTime } from "luxon";
|
||||||
import { Component, Vue } from "vue-facing-decorator";
|
import { Component, Vue } from "vue-facing-decorator";
|
||||||
import { LMap, LMarker, LTileLayer } from "@vue-leaflet/vue-leaflet";
|
import { LMap, LMarker, LTileLayer } from "@vue-leaflet/vue-leaflet";
|
||||||
@@ -183,9 +183,9 @@ import QuickNav from "@/components/QuickNav.vue";
|
|||||||
import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "@/constants/app";
|
import { DEFAULT_IMAGE_API_SERVER, NotificationIface } from "@/constants/app";
|
||||||
import { accountsDB, db } from "@/db/index";
|
import { accountsDB, db } from "@/db/index";
|
||||||
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||||
import { accessToken } from "@/libs/crypto";
|
|
||||||
import {
|
import {
|
||||||
createEndorserJwtVcFromClaim,
|
createEndorserJwtVcFromClaim,
|
||||||
|
getHeaders,
|
||||||
PlanVerifiableCredential,
|
PlanVerifiableCredential,
|
||||||
} from "@/libs/endorserServer";
|
} from "@/libs/endorserServer";
|
||||||
import { useAppStore } from "@/store/app";
|
import { useAppStore } from "@/store/app";
|
||||||
@@ -250,11 +250,7 @@ export default class NewEditProjectView extends Vue {
|
|||||||
this.apiServer +
|
this.apiServer +
|
||||||
"/api/claim/byHandle/" +
|
"/api/claim/byHandle/" +
|
||||||
encodeURIComponent(this.projectId);
|
encodeURIComponent(this.projectId);
|
||||||
const token = await accessToken(userDid);
|
const headers = await getHeaders(userDid);
|
||||||
const headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: "Bearer " + token,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await this.axios.get(url, { headers });
|
const resp = await this.axios.get(url, { headers });
|
||||||
@@ -309,16 +305,12 @@ export default class NewEditProjectView extends Vue {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const token = await accessToken(this.activeDid);
|
const headers = getHeaders(this.activeDid) as AxiosRequestHeaders;
|
||||||
const response = await this.axios.delete(
|
const response = await this.axios.delete(
|
||||||
DEFAULT_IMAGE_API_SERVER +
|
DEFAULT_IMAGE_API_SERVER +
|
||||||
"/image/" +
|
"/image/" +
|
||||||
encodeURIComponent(this.imageUrl),
|
encodeURIComponent(this.imageUrl),
|
||||||
{
|
{ headers },
|
||||||
headers: {
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
if (response.status === 204) {
|
if (response.status === 204) {
|
||||||
// don't bother with a notification
|
// don't bother with a notification
|
||||||
@@ -418,11 +410,7 @@ export default class NewEditProjectView extends Vue {
|
|||||||
|
|
||||||
const payload = JSON.stringify({ jwtEncoded: vcJwt });
|
const payload = JSON.stringify({ jwtEncoded: vcJwt });
|
||||||
const url = this.apiServer + "/api/v2/claim";
|
const url = this.apiServer + "/api/v2/claim";
|
||||||
const token = await accessToken(issuerDid);
|
const headers = await getHeaders(issuerDid);
|
||||||
const headers = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: "Bearer " + token,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const resp = await this.axios.post(url, payload, { headers });
|
const resp = await this.axios.post(url, payload, { headers });
|
||||||
|
|||||||
@@ -416,7 +416,6 @@ import { accountsDB, db } from "@/db/index";
|
|||||||
import { Account } from "@/db/tables/accounts";
|
import { Account } from "@/db/tables/accounts";
|
||||||
import { Contact } from "@/db/tables/contacts";
|
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 * as libsUtil from "@/libs/util";
|
import * as libsUtil from "@/libs/util";
|
||||||
import {
|
import {
|
||||||
BLANK_GENERIC_SERVER_RECORD,
|
BLANK_GENERIC_SERVER_RECORD,
|
||||||
@@ -583,11 +582,6 @@ export default class ProjectViewView extends Vue {
|
|||||||
|
|
||||||
this.loadPlanFulfillersTo();
|
this.loadPlanFulfillersTo();
|
||||||
|
|
||||||
// now load fulfilled-by, a single project
|
|
||||||
if (this.activeDid) {
|
|
||||||
const token = await accessToken(this.activeDid);
|
|
||||||
headers["Authorization"] = "Bearer " + token;
|
|
||||||
}
|
|
||||||
const fulfilledByUrl =
|
const fulfilledByUrl =
|
||||||
this.apiServer +
|
this.apiServer +
|
||||||
"/api/v2/report/planFulfilledByPlan?planHandleId=" +
|
"/api/v2/report/planFulfilledByPlan?planHandleId=" +
|
||||||
|
|||||||
@@ -233,13 +233,16 @@ import { Component, Vue } from "vue-facing-decorator";
|
|||||||
import { NotificationIface } from "@/constants/app";
|
import { NotificationIface } from "@/constants/app";
|
||||||
import { accountsDB, db } from "@/db/index";
|
import { accountsDB, db } from "@/db/index";
|
||||||
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||||
import { accessToken } from "@/libs/crypto";
|
|
||||||
import * as libsUtil from "@/libs/util";
|
import * as libsUtil from "@/libs/util";
|
||||||
import InfiniteScroll from "@/components/InfiniteScroll.vue";
|
import InfiniteScroll from "@/components/InfiniteScroll.vue";
|
||||||
import QuickNav from "@/components/QuickNav.vue";
|
import QuickNav from "@/components/QuickNav.vue";
|
||||||
import ProjectIcon from "@/components/ProjectIcon.vue";
|
import ProjectIcon from "@/components/ProjectIcon.vue";
|
||||||
import TopMessage from "@/components/TopMessage.vue";
|
import TopMessage from "@/components/TopMessage.vue";
|
||||||
import { OfferSummaryRecord, PlanData } from "@/libs/endorserServer";
|
import {
|
||||||
|
getHeaders,
|
||||||
|
OfferSummaryRecord,
|
||||||
|
PlanData,
|
||||||
|
} from "@/libs/endorserServer";
|
||||||
import EntityIcon from "@/components/EntityIcon.vue";
|
import EntityIcon from "@/components/EntityIcon.vue";
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
@@ -293,13 +296,9 @@ export default class ProjectsView extends Vue {
|
|||||||
* @param url the url used to fetch the data
|
* @param url the url used to fetch the data
|
||||||
* @param token Authorization token
|
* @param token Authorization token
|
||||||
**/
|
**/
|
||||||
async projectDataLoader(url: string, token: string) {
|
async projectDataLoader(url: string) {
|
||||||
const headers: { [key: string]: string } = {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const headers = await getHeaders(this.activeDid);
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
const resp = await this.axios.get(url, { headers } as AxiosRequestConfig);
|
const resp = await this.axios.get(url, { headers } as AxiosRequestConfig);
|
||||||
if (resp.status === 200 && resp.data.data) {
|
if (resp.status === 200 && resp.data.data) {
|
||||||
@@ -353,8 +352,7 @@ export default class ProjectsView extends Vue {
|
|||||||
**/
|
**/
|
||||||
async loadProjects(activeDid?: string, urlExtra: string = "") {
|
async loadProjects(activeDid?: string, urlExtra: string = "") {
|
||||||
const url = `${this.apiServer}/api/v2/report/plansByIssuer?${urlExtra}`;
|
const url = `${this.apiServer}/api/v2/report/plansByIssuer?${urlExtra}`;
|
||||||
const token: string = await accessToken(activeDid);
|
await this.projectDataLoader(url);
|
||||||
await this.projectDataLoader(url, token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -392,11 +390,8 @@ export default class ProjectsView extends Vue {
|
|||||||
* @param url the url used to fetch the data
|
* @param url the url used to fetch the data
|
||||||
* @param token Authorization token
|
* @param token Authorization token
|
||||||
**/
|
**/
|
||||||
async offerDataLoader(url: string, token: string) {
|
async offerDataLoader(url: string) {
|
||||||
const headers: { [key: string]: string } = {
|
const headers = getHeaders(this.activeDid);
|
||||||
"Content-Type": "application/json",
|
|
||||||
Authorization: `Bearer ${token}`,
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.isLoading = true;
|
this.isLoading = true;
|
||||||
@@ -454,8 +449,7 @@ export default class ProjectsView extends Vue {
|
|||||||
**/
|
**/
|
||||||
async loadOffers(issuerDid?: string, urlExtra: string = "") {
|
async loadOffers(issuerDid?: string, urlExtra: string = "") {
|
||||||
const url = `${this.apiServer}/api/v2/report/offers?offeredByDid=${issuerDid}${urlExtra}`;
|
const url = `${this.apiServer}/api/v2/report/offers?offeredByDid=${issuerDid}${urlExtra}`;
|
||||||
const token: string = await accessToken(issuerDid);
|
await this.offerDataLoader(url);
|
||||||
await this.offerDataLoader(url, token);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public computedOfferTabClassNames() {
|
public computedOfferTabClassNames() {
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ import {
|
|||||||
} from "@/constants/app";
|
} from "@/constants/app";
|
||||||
import { db } from "@/db/index";
|
import { db } from "@/db/index";
|
||||||
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
|
||||||
import { accessToken } from "@/libs/crypto";
|
import { getHeaders } from "@/libs/endorserServer";
|
||||||
|
|
||||||
@Component({ components: { PhotoDialog, QuickNav } })
|
@Component({ components: { PhotoDialog, QuickNav } })
|
||||||
export default class SharedPhotoView extends Vue {
|
export default class SharedPhotoView extends Vue {
|
||||||
@@ -151,10 +151,7 @@ export default class SharedPhotoView extends Vue {
|
|||||||
let result;
|
let result;
|
||||||
try {
|
try {
|
||||||
// send the image to the server
|
// send the image to the server
|
||||||
const token = await accessToken(this.activeDid);
|
const headers = await getHeaders(this.activeDid);
|
||||||
const headers = {
|
|
||||||
Authorization: "Bearer " + token,
|
|
||||||
};
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
formData.append(
|
formData.append(
|
||||||
"image",
|
"image",
|
||||||
|
|||||||
Reference in New Issue
Block a user