fix: team invites (#1699)

This commit is contained in:
Anshuman Pandey
2023-11-30 13:53:05 +05:30
committed by GitHub
parent d71b1ee052
commit f734a76588
3 changed files with 25 additions and 43 deletions

View File

@@ -2,7 +2,6 @@ import { sendInviteAcceptedEmail } from "@/app/lib/email";
import { verifyInviteToken } from "@formbricks/lib/jwt";
import { authOptions } from "@formbricks/lib/authOptions";
import { getServerSession } from "next-auth";
import { prisma } from "@formbricks/database";
import {
NotLoggedInContent,
WrongAccountContent,
@@ -11,21 +10,20 @@ import {
RightAccountContent,
} from "./components/InviteContentComponents";
import { env } from "@formbricks/lib/env.mjs";
import { deleteInvite, getInvite } from "@formbricks/lib/invite/service";
import { createMembership } from "@formbricks/lib/membership/service";
export default async function JoinTeam({ searchParams }) {
const currentUser = await getServerSession(authOptions);
try {
const { inviteId, email } = await verifyInviteToken(searchParams.token);
const { inviteId, email } = verifyInviteToken(searchParams.token);
const invite = await prisma?.invite.findUnique({
where: { id: inviteId },
include: { creator: true },
});
const invite = await getInvite(inviteId);
const isExpired = (i) => new Date(i.expiresAt) < new Date();
const isInviteExpired = new Date(invite.expiresAt) < new Date();
if (!invite || isExpired(invite)) {
if (!invite || isInviteExpired) {
return <ExpiredContent />;
} else if (invite.accepted) {
return <UsedContent />;
@@ -35,32 +33,10 @@ export default async function JoinTeam({ searchParams }) {
} else if (currentUser.user?.email !== email) {
return <WrongAccountContent />;
} else {
// create membership
await prisma?.membership.create({
data: {
team: {
connect: {
id: invite.teamId,
},
},
user: {
connect: {
id: currentUser.user?.id,
},
},
role: invite.role,
accepted: true,
},
});
await createMembership(invite.teamId, currentUser.user.id, { accepted: true, role: invite.role });
await deleteInvite(inviteId);
// delete invite
await prisma?.invite.delete({
where: {
id: inviteId,
},
});
sendInviteAcceptedEmail(invite.creator.name, currentUser.user?.name, invite.creator.email);
sendInviteAcceptedEmail(invite.creator.name ?? "", currentUser.user?.name, invite.creator.email);
return <RightAccountContent />;
}

View File

@@ -114,7 +114,9 @@ export const deleteInvite = async (inviteId: string): Promise<TInvite> => {
}
};
export const getInvite = async (inviteId: string): Promise<{ inviteId: string; email: string }> =>
export const getInvite = async (
inviteId: string
): Promise<TInvite & { creator: { name: string | null; email: string } }> =>
unstable_cache(
async () => {
validateInputs([inviteId, ZString]);
@@ -123,8 +125,13 @@ export const getInvite = async (inviteId: string): Promise<{ inviteId: string; e
where: {
id: inviteId,
},
select: {
email: true,
include: {
creator: {
select: {
name: true,
email: true,
},
},
},
});
@@ -132,10 +139,7 @@ export const getInvite = async (inviteId: string): Promise<{ inviteId: string; e
throw new ResourceNotFoundError("Invite", inviteId);
}
return {
inviteId,
email: invite.email,
};
return invite;
},
[`getInvite-${inviteId}`],
{ tags: [inviteCache.tag.byId(inviteId)], revalidate: SERVICES_REVALIDATION_INTERVAL }

View File

@@ -48,14 +48,16 @@ export async function verifyToken(token: string, userEmail: string = ""): Promis
return jwt.verify(token, env.NEXTAUTH_SECRET + userEmail) as JwtPayload;
}
export const verifyInviteToken = (token: string): JwtPayload => {
export const verifyInviteToken = (token: string): { inviteId: string; email: string } => {
try {
const decoded = jwt.decode(token);
const payload: JwtPayload = decoded as JwtPayload;
const { inviteId, email } = payload;
return {
inviteId: payload.inviteId,
email: payload.email,
inviteId,
email,
};
} catch (error) {
console.error("Error verifying invite token:", error);