finish the loading of an invite RegisterAction when clicking on a link

This commit is contained in:
2024-10-06 20:01:07 -06:00
parent 1bfdcab90b
commit 149481d468
14 changed files with 247 additions and 44 deletions

View File

@@ -168,7 +168,7 @@
}"
title="See more about this person"
>
<fa icon="circle-info" class="text-blue-500 ml-4" />
<fa icon="circle-info" class="text-xl text-blue-500 ml-4" />
</router-link>
<span class="ml-4 text-sm overflow-hidden"
@@ -276,6 +276,7 @@
<GiftedDialog ref="customGivenDialog" />
<OfferDialog ref="customOfferDialog" />
<ContactNameDialog ref="contactNameDialog" />
<div v-if="showLargeIdenticon" class="fixed z-[100] top-0 inset-x-0 w-full">
<div
@@ -296,6 +297,7 @@
import { AxiosError } from "axios";
import { Buffer } from "buffer/";
import { IndexableType } from "dexie";
import { JWTPayload } from "did-jwt";
import * as R from "ramda";
import { Component, Vue } from "vue-facing-decorator";
import { RouteLocationNormalizedLoaded, Router } from "vue-router";
@@ -304,7 +306,7 @@ import { useClipboard } from "@vueuse/core";
import { AppString, NotificationIface } from "@/constants/app";
import {
db,
retrieveSettingsForActiveAccount,
retrieveSettingsForActiveAccount, updateAccountSettings,
updateDefaultSettings,
} from "@/db/index";
import { Contact } from "@/db/tables/contacts";
@@ -319,16 +321,26 @@ import {
register,
setVisibilityUtil,
UserInfo,
VerifiableCredential,
} from "@/libs/endorserServer";
import * as libsUtil from "@/libs/util";
import QuickNav from "@/components/QuickNav.vue";
import EntityIcon from "@/components/EntityIcon.vue";
import GiftedDialog from "@/components/GiftedDialog.vue";
import OfferDialog from "@/components/OfferDialog.vue";
import ContactNameDialog from "@/components/ContactNameDialog.vue";
import TopMessage from "@/components/TopMessage.vue";
import {generateSaveAndActivateIdentity} from "@/libs/util";
@Component({
components: { TopMessage, GiftedDialog, EntityIcon, OfferDialog, QuickNav },
components: {
GiftedDialog,
EntityIcon,
OfferDialog,
QuickNav,
ContactNameDialog,
TopMessage,
},
})
export default class ContactsView extends Vue {
$notify!: (notification: NotificationIface, timeout?: number) => void;
@@ -387,11 +399,11 @@ export default class ContactsView extends Vue {
(a.name || "").localeCompare(b.name || ""),
);
const importedContactJwt = (this.$route as RouteLocationNormalizedLoaded).query[
"contactJwt"
] as string;
// handle a contact sent via URL
const importedContactJwt = (this.$route as RouteLocationNormalizedLoaded)
.query["contactJwt"] as string;
if (importedContactJwt) {
// really should fully verify
// really should fully verify contents
const { payload } = decodeEndorserJwt(importedContactJwt);
const userInfo = payload["own"] as UserInfo;
const newContact = {
@@ -404,6 +416,76 @@ export default class ContactsView extends Vue {
} as Contact;
this.addContact(newContact);
}
// handle an invite JWT sent via URL
const importedInviteJwt = (this.$route as RouteLocationNormalizedLoaded)
.query["inviteJwt"] as string;
if (importedInviteJwt) {
// make sure user is created
if (!this.activeDid) {
this.activeDid = await generateSaveAndActivateIdentity();
}
// send invite directly to server, with auth for this user
const headers = await getHeaders(this.activeDid);
try {
const response = await this.axios.post(
this.apiServer + "/api/v2/claim",
{ jwtEncoded: importedInviteJwt },
{ headers },
);
if (response.status != 201) {
throw { error: { response: response } };
}
await updateAccountSettings(this.activeDid, { isRegistered: true });
this.isRegistered = true;
this.$notify(
{
group: "alert",
type: "success",
title: "Registered",
text: "You are now registered.",
},
3000,
);
// now add the inviter as a contact
const payload: JWTPayload =
decodeEndorserJwt(importedInviteJwt).payload;
const registration = payload as VerifiableCredential;
(this.$refs.contactNameDialog as ContactNameDialog).open((name) =>
this.addContact({
did: registration.vc.credentialSubject.agent.identifier,
name: name, // may be undefined if they cancel
registered: true,
}),
);
} catch (error) {
console.error("Error redeeming invite:", error);
let message = "Got an error sending the invite.";
if (
error.response &&
error.response.data &&
error.response.data.error
) {
if (error.response.data.error.message) {
message = error.response.data.error.message;
} else {
message = error.response.data.error;
}
} else if (error.message) {
message = error.message;
}
this.$notify(
{
group: "alert",
type: "danger",
title: "Error with Invite",
text: message,
},
5000,
);
}
}
}
private danger(message: string, title: string = "Error", timeout = 5000) {
@@ -864,12 +946,14 @@ export default class ContactsView extends Vue {
let userMessage = "There was an error. See logs for more info.";
const serverError = error as AxiosError;
if (serverError.isAxiosError) {
if (serverError.response?.data
&& typeof serverError.response.data === 'object'
&& 'error' in serverError.response.data
&& typeof serverError.response.data.error === 'object'
&& serverError.response.data.error !== null
&& 'message' in serverError.response.data.error){
if (
serverError.response?.data &&
typeof serverError.response.data === "object" &&
"error" in serverError.response.data &&
typeof serverError.response.data.error === "object" &&
serverError.response.data.error !== null &&
"message" in serverError.response.data.error
) {
userMessage = serverError.response.data.error.message as string;
} else if (serverError.message) {
userMessage = serverError.message; // Info for the user