Skip to content

Commit 61b7219

Browse files
committed
fix: org invite scoping
Fixes some scoping issues with team invites.
1 parent e22c321 commit 61b7219

File tree

4 files changed

+59
-22
lines changed

4 files changed

+59
-22
lines changed

apps/webapp/app/models/member.server.ts

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,17 @@ export async function inviteMembers({
120120
});
121121
}
122122

123-
export async function getInviteFromToken({ token }: { token: string }) {
123+
export async function getInviteFromToken({ token, userId }: { token: string; userId: string }) {
124124
return await prisma.orgMemberInvite.findFirst({
125125
where: {
126126
token,
127+
organization: {
128+
members: {
129+
some: {
130+
userId,
131+
},
132+
},
133+
},
127134
},
128135
include: {
129136
organization: true,
@@ -153,6 +160,13 @@ export async function acceptInvite({ userId, inviteId }: { userId: string; invit
153160
const invite = await tx.orgMemberInvite.delete({
154161
where: {
155162
id: inviteId,
163+
organization: {
164+
members: {
165+
some: {
166+
userId,
167+
},
168+
},
169+
},
156170
},
157171
include: {
158172
organization: {
@@ -188,6 +202,13 @@ export async function acceptInvite({ userId, inviteId }: { userId: string; invit
188202
const remainingInvites = await tx.orgMemberInvite.findMany({
189203
where: {
190204
email: invite.email,
205+
organization: {
206+
members: {
207+
some: {
208+
userId,
209+
},
210+
},
211+
},
191212
},
192213
});
193214

@@ -201,6 +222,13 @@ export async function declineInvite({ userId, inviteId }: { userId: string; invi
201222
const declinedInvite = await prisma.orgMemberInvite.delete({
202223
where: {
203224
id: inviteId,
225+
organization: {
226+
members: {
227+
some: {
228+
userId,
229+
},
230+
},
231+
},
204232
},
205233
include: {
206234
organization: true,
@@ -217,17 +245,25 @@ export async function declineInvite({ userId, inviteId }: { userId: string; invi
217245
const remainingInvites = await prisma.orgMemberInvite.findMany({
218246
where: {
219247
email: user!.email,
248+
organization: {
249+
members: {
250+
some: {
251+
userId,
252+
},
253+
},
254+
},
220255
},
221256
});
222257

223258
return { remainingInvites, organization: declinedInvite.organization };
224259
});
225260
}
226261

227-
export async function resendInvite({ inviteId }: { inviteId: string }) {
262+
export async function resendInvite({ inviteId, userId }: { inviteId: string; userId: string }) {
228263
return await prisma.orgMemberInvite.update({
229264
where: {
230265
id: inviteId,
266+
inviterId: userId,
231267
},
232268
data: {
233269
updatedAt: new Date(),
@@ -241,24 +277,24 @@ export async function resendInvite({ inviteId }: { inviteId: string }) {
241277

242278
export async function revokeInvite({
243279
userId,
244-
slug,
280+
orgSlug,
245281
inviteId,
246282
}: {
247283
userId: string;
248-
slug: string;
284+
orgSlug: string;
249285
inviteId: string;
250286
}) {
251-
const org = await prisma.organization.findFirst({
252-
where: { slug, members: { some: { userId } } },
253-
});
254-
255-
if (!org) {
256-
throw new Error("User does not have access to this organization");
257-
}
258287
const invite = await prisma.orgMemberInvite.delete({
259288
where: {
260289
id: inviteId,
261-
organizationId: org.id,
290+
organization: {
291+
slug: orgSlug,
292+
members: {
293+
some: {
294+
userId,
295+
},
296+
},
297+
},
262298
},
263299
select: {
264300
email: true,

apps/webapp/app/routes/invite-accept.tsx

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,13 @@ export async function loader({ request }: LoaderFunctionArgs) {
1818
);
1919
}
2020

21-
const invite = await getInviteFromToken({ token });
21+
if (!user) {
22+
return redirectWithSuccessMessage("/", request, "Please log in to accept the invite.", {
23+
ephemeral: false,
24+
});
25+
}
26+
27+
const invite = await getInviteFromToken({ token, userId: user.id });
2228
if (!invite) {
2329
return redirectWithErrorMessage(
2430
"/",
@@ -28,12 +34,6 @@ export async function loader({ request }: LoaderFunctionArgs) {
2834
);
2935
}
3036

31-
if (!user) {
32-
return redirectWithSuccessMessage("/", request, "Please log in to accept the invite.", {
33-
ephemeral: false,
34-
});
35-
}
36-
3737
if (invite.email !== user.email) {
3838
return redirectWithErrorMessage(
3939
"/",

apps/webapp/app/routes/invite-resend.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { parse } from "@conform-to/zod";
2-
import { ActionFunction, json } from "@remix-run/server-runtime";
2+
import { type ActionFunction, json } from "@remix-run/server-runtime";
33
import { env } from "process";
44
import { z } from "zod";
55
import { resendInvite } from "~/models/member.server";
@@ -25,6 +25,7 @@ export const action: ActionFunction = async ({ request }) => {
2525
try {
2626
const invite = await resendInvite({
2727
inviteId: submission.value.inviteId,
28+
userId,
2829
});
2930

3031
try {

apps/webapp/app/routes/invite-revoke.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { parse } from "@conform-to/zod";
2-
import { ActionFunction, json } from "@remix-run/server-runtime";
2+
import { type ActionFunction, json } from "@remix-run/server-runtime";
33
import { z } from "zod";
44
import { revokeInvite } from "~/models/member.server";
55
import { redirectWithSuccessMessage } from "~/models/message.server";
@@ -24,7 +24,7 @@ export const action: ActionFunction = async ({ request }) => {
2424
try {
2525
const { email, organization } = await revokeInvite({
2626
userId,
27-
slug: submission.value.slug,
27+
orgSlug: submission.value.slug,
2828
inviteId: submission.value.inviteId,
2929
});
3030

0 commit comments

Comments
 (0)