mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-17 03:21:51 -05:00
fix: team invites (#1699)
This commit is contained in:
@@ -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 />;
|
||||
}
|
||||
|
||||
@@ -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 }
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user