do not share the invite JWT with the server; always keep it on the client, generated at will
This commit is contained in:
@@ -73,17 +73,15 @@
|
||||
invite.expiresAt > new Date().toISOString()
|
||||
"
|
||||
class="text-center text-blue-500 cursor-pointer"
|
||||
:title="inviteLink(invite.jwt)"
|
||||
@click="
|
||||
copyInviteAndNotify(invite.inviteIdentifier, invite.jwt)
|
||||
"
|
||||
title="Click to copy invite link"
|
||||
@click="copyInviteAndNotify(invite)"
|
||||
>
|
||||
{{ getTruncatedInviteId(invite.inviteIdentifier) }}
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
class="text-center text-slate-500 cursor-pointer"
|
||||
:title="inviteLink(invite.jwt)"
|
||||
title="Click to see invite details"
|
||||
@click="
|
||||
showInvite(
|
||||
invite.inviteIdentifier,
|
||||
@@ -120,6 +118,8 @@
|
||||
@click="deleteInvite(invite.inviteIdentifier, invite.notes)"
|
||||
/>
|
||||
</td>
|
||||
<td class="hidden" :data-testId="invite.jwt" aria-hidden="true">
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -146,7 +146,7 @@ import { logger } from "../utils/logger";
|
||||
interface Invite {
|
||||
inviteIdentifier: string;
|
||||
expiresAt: string;
|
||||
jwt: string;
|
||||
jwt?: string; // only used to store a JWT for testing, after the link is clicked
|
||||
notes: string;
|
||||
redeemedAt: string | null;
|
||||
redeemedBy: string | null;
|
||||
@@ -220,18 +220,27 @@ export default class InviteOneView extends Vue {
|
||||
return `${redeemedBy.slice(0, 13)}...${redeemedBy.slice(-3)}`;
|
||||
}
|
||||
|
||||
inviteLink(jwt: string): string {
|
||||
inviteLink(jwt: string | undefined): string {
|
||||
if (!jwt) return "Click to set JWT link";
|
||||
return APP_SERVER + "/invite-one-accept/" + jwt;
|
||||
}
|
||||
|
||||
copyInviteAndNotify(inviteId: string, jwt: string) {
|
||||
useClipboard().copy(this.inviteLink(jwt));
|
||||
async copyInviteAndNotify(invite: Invite) {
|
||||
const expiresIn = (new Date(invite.expiresAt).getTime() - Date.now()) / 1000;
|
||||
const inviteJwt = await createInviteJwt(
|
||||
this.activeDid,
|
||||
undefined,
|
||||
invite.inviteIdentifier,
|
||||
expiresIn,
|
||||
);
|
||||
invite.jwt = inviteJwt; // set for testing
|
||||
useClipboard().copy(this.inviteLink(inviteJwt));
|
||||
this.$notify(
|
||||
{
|
||||
group: "alert",
|
||||
type: "success",
|
||||
title: "Copied",
|
||||
text: "Your clipboard now contains the link for invite " + inviteId,
|
||||
text: "Your clipboard now contains the link for invite " + invite.inviteIdentifier,
|
||||
},
|
||||
5000,
|
||||
);
|
||||
@@ -295,22 +304,14 @@ export default class InviteOneView extends Vue {
|
||||
},
|
||||
};
|
||||
}
|
||||
const expiresIn = (new Date(expiresAt).getTime() - Date.now()) / 1000;
|
||||
const inviteJwt = await createInviteJwt(
|
||||
this.activeDid,
|
||||
undefined,
|
||||
inviteIdentifier,
|
||||
expiresIn,
|
||||
);
|
||||
await axios.post(
|
||||
this.apiServer + "/api/userUtil/invite",
|
||||
{ inviteJwt: inviteJwt, notes: notes },
|
||||
{ inviteIdentifier: inviteIdentifier, notes: notes, expiresAt: expiresAt },
|
||||
{ headers },
|
||||
);
|
||||
const newInvite = {
|
||||
inviteIdentifier: inviteIdentifier,
|
||||
expiresAt: expiresAt,
|
||||
jwt: inviteJwt,
|
||||
notes: notes,
|
||||
redeemedAt: null,
|
||||
redeemedBy: null,
|
||||
|
||||
@@ -44,6 +44,11 @@ test('Check User 0 can invite someone', async ({ page }) => {
|
||||
await expect(page.locator('div[role="alert"] button:has-text("Yes")')).toBeHidden();
|
||||
|
||||
// check that the invite is in the list
|
||||
const newInviteRow = page.locator(`tr:has(td:has-text("Neighbor ${neighborNum}"))`);
|
||||
await expect(newInviteRow).toBeVisible();
|
||||
// click on the link in the first column, which generates the JWT in the other column
|
||||
await newInviteRow.locator('td:first-child').click();
|
||||
|
||||
const newInviteLine = page.locator(`td:has-text("Neighbor ${neighborNum}")`);
|
||||
await expect(newInviteLine).toBeVisible();
|
||||
// retrieve the link from the title
|
||||
|
||||
Reference in New Issue
Block a user