Skip to content

Commit cc0b128

Browse files
committed
devin: handle duplicate org invites gracefully
1 parent a2e742d commit cc0b128

2 files changed

Lines changed: 18 additions & 2 deletions

File tree

.server-changes/invite-email-case-insensitive.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,8 @@ the accept route compared emails strictly and the pending-invite lookups
1010
were exact-match. Invite emails are now lowercased on creation, and all
1111
invite-by-email lookups (accept, decline, pending list) match
1212
case-insensitively so existing mixed-case invite rows still work.
13+
14+
Accepting an invite now also consumes any case-variant duplicate invites
15+
for the same org (pairs left over from before normalization), and
16+
re-inviting an already-invited email acts as a resend instead of failing
17+
on the unique constraint.

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,14 +122,16 @@ export async function inviteMembers({
122122
} satisfies Prisma.OrgMemberInviteCreateManyInput)
123123
);
124124

125+
// Re-inviting an already-invited email is treated as a resend: skip the
126+
// conflicting insert and return the existing invite below.
125127
await prisma.orgMemberInvite.createMany({
126128
data: invites,
129+
skipDuplicates: true,
127130
});
128131

129132
return await prisma.orgMemberInvite.findMany({
130133
where: {
131134
organizationId: org.id,
132-
inviterId: userId,
133135
email: {
134136
in: emails,
135137
},
@@ -212,7 +214,16 @@ export async function acceptInvite({
212214
});
213215
}
214216

215-
// 4. Check for other invites
217+
// 4. Consume any case-variant duplicate invites for this org (rows
218+
// created before invite emails were lowercased)
219+
await tx.orgMemberInvite.deleteMany({
220+
where: {
221+
organizationId: invite.organizationId,
222+
email: { equals: user.email, mode: "insensitive" },
223+
},
224+
});
225+
226+
// 5. Check for other invites
216227
const remainingInvites = await tx.orgMemberInvite.findMany({
217228
where: {
218229
email: { equals: user.email, mode: "insensitive" },

0 commit comments

Comments
 (0)