|
|
|
<template>
|
|
|
|
<QuickNav selected="Invite" />
|
|
|
|
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
|
|
|
|
<div v-if="acceptInput" class="text-center mt-4">
|
|
|
|
<p>That invitation did not work.</p>
|
|
|
|
<p class="mt-2">
|
|
|
|
Go back to your invite message and copy the entire text, then paste it
|
|
|
|
here.
|
|
|
|
</p>
|
|
|
|
<p class="mt-2">
|
|
|
|
If the link looks correct, try Chrome. (For example, iOS Safari does not
|
|
|
|
work well with the invite link.)
|
|
|
|
</p>
|
|
|
|
<textarea
|
|
|
|
v-model="inputJwt"
|
|
|
|
placeholder="Paste invitation..."
|
|
|
|
class="mt-4 border-2 border-gray-300 p-2 rounded"
|
|
|
|
cols="40"
|
|
|
|
@input="() => checkInvite(inputJwt)"
|
|
|
|
/>
|
|
|
|
<br />
|
|
|
|
<button
|
|
|
|
@click="() => processInvite(inputJwt, true)"
|
|
|
|
class="ml-2 p-2 bg-blue-500 text-white rounded"
|
|
|
|
>
|
|
|
|
Submit
|
|
|
|
</button>
|
|
|
|
</div>
|
|
|
|
<div
|
|
|
|
v-if="checkingInvite"
|
|
|
|
class="text-lg text-center font-light relative px-7"
|
|
|
|
>
|
|
|
|
<fa icon="spinner" class="fa-spin-pulse" />
|
|
|
|
Loading…
|
|
|
|
</div>
|
|
|
|
</section>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts">
|
|
|
|
import { Component, Vue } from "vue-facing-decorator";
|
|
|
|
import { Router } from "vue-router";
|
|
|
|
|
|
|
|
import QuickNav from "@/components/QuickNav.vue";
|
|
|
|
import { NotificationIface } from "@/constants/app";
|
|
|
|
import { db, retrieveSettingsForActiveAccount } from "@/db/index";
|
|
|
|
import { decodeEndorserJwt } from "@/libs/crypto/vc";
|
|
|
|
import { generateSaveAndActivateIdentity } from "@/libs/util";
|
|
|
|
|
|
|
|
@Component({ components: { QuickNav } })
|
|
|
|
export default class InviteOneAcceptView extends Vue {
|
|
|
|
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
|
|
|
|
|
|
|
acceptInput: boolean = false;
|
|
|
|
activeDid: string = "";
|
|
|
|
apiServer: string = "";
|
|
|
|
checkingInvite: boolean = true;
|
|
|
|
inputJwt: string = "";
|
|
|
|
|
|
|
|
async mounted() {
|
|
|
|
this.checkingInvite = true;
|
|
|
|
await db.open();
|
|
|
|
const settings = await retrieveSettingsForActiveAccount();
|
|
|
|
this.activeDid = settings.activeDid || "";
|
|
|
|
this.apiServer = settings.apiServer || "";
|
|
|
|
|
|
|
|
if (!this.activeDid) {
|
|
|
|
this.activeDid = await generateSaveAndActivateIdentity();
|
|
|
|
}
|
|
|
|
|
|
|
|
const jwt = window.location.pathname.substring(
|
|
|
|
"/invite-one-accept/".length,
|
|
|
|
);
|
|
|
|
await this.processInvite(jwt, false);
|
|
|
|
|
|
|
|
this.checkingInvite = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// process the invite JWT and/or text message containing the URL with the JWT
|
|
|
|
async processInvite(jwtInput: string, notifyOnFailure: boolean) {
|
|
|
|
this.checkingInvite = true;
|
|
|
|
|
|
|
|
try {
|
|
|
|
let jwt: string = jwtInput ?? "";
|
|
|
|
|
|
|
|
// parse the string: extract the URL or JWT if surrounded by spaces
|
|
|
|
// and then extract the JWT from the URL
|
|
|
|
const urlMatch = jwtInput.match(/(https?:\/\/[^\s]+)/);
|
|
|
|
if (urlMatch && urlMatch[1]) {
|
|
|
|
// extract the JWT from the URL, meaning any character except "?"
|
|
|
|
const internalMatch = urlMatch[1].match(/\/invite-one-accept\/([^?]+)/);
|
|
|
|
if (internalMatch && internalMatch[1]) {
|
|
|
|
jwt = internalMatch[1];
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// extract the JWT (which starts with "ey") if it is surrounded by other input
|
|
|
|
const spaceMatch = jwtInput.match(/(ey[\w.-]+)/);
|
|
|
|
if (spaceMatch && spaceMatch[1]) {
|
|
|
|
jwt = spaceMatch[1];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!jwt) {
|
|
|
|
if (notifyOnFailure) {
|
|
|
|
this.$notify(
|
|
|
|
{
|
|
|
|
group: "alert",
|
|
|
|
type: "danger",
|
|
|
|
title: "Missing invite",
|
|
|
|
text: "There was no invite. Paste the entire text that has the link.",
|
|
|
|
},
|
|
|
|
5000,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
this.acceptInput = true;
|
|
|
|
} else {
|
|
|
|
//const payload: JWTPayload =
|
|
|
|
decodeEndorserJwt(jwt);
|
|
|
|
|
|
|
|
// That's good enough for an initial check.
|
|
|
|
// Send them to the contacts page to finish, with inviteJwt in the query string.
|
|
|
|
(this.$router as Router).push({
|
|
|
|
name: "contacts",
|
|
|
|
query: { inviteJwt: jwt },
|
|
|
|
});
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.error("Error accepting invite:", error);
|
|
|
|
if (notifyOnFailure) {
|
|
|
|
this.$notify(
|
|
|
|
{
|
|
|
|
group: "alert",
|
|
|
|
type: "danger",
|
|
|
|
title: "Error",
|
|
|
|
text: "There was an error processing that invite.",
|
|
|
|
},
|
|
|
|
3000,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
this.acceptInput = true;
|
|
|
|
}
|
|
|
|
this.checkingInvite = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check the invite JWT
|
|
|
|
async checkInvite(jwtInput: string) {
|
|
|
|
if (
|
|
|
|
jwtInput.endsWith("invite-one-accept") ||
|
|
|
|
jwtInput.endsWith("invite-one-accept/")
|
|
|
|
) {
|
|
|
|
this.$notify(
|
|
|
|
{
|
|
|
|
group: "alert",
|
|
|
|
type: "danger",
|
|
|
|
title: "Error",
|
|
|
|
text: "That is only part of the invite link; it's missing data at the end. Try another way to get the full link.",
|
|
|
|
},
|
|
|
|
5000,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|