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
diff --git a/src/views/InviteOneView.vue b/src/views/InviteOneView.vue
index 179a7257a..7f63f8fc9 100644
--- a/src/views/InviteOneView.vue
+++ b/src/views/InviteOneView.vue
@@ -44,7 +44,10 @@
:key="invite.inviteIdentifier"
class="border-t"
>
-
+ |
{{ getTruncatedInviteId(invite.inviteIdentifier) }}
|
{{ invite.notes }} |
@@ -62,19 +65,21 @@