@@ -5,6 +5,17 @@ import sendNotification from "src/notifications/mutations/sendNotification"
55import { getPrivilegeText } from "src/core/utils/getPrivilegeText"
66import { Routes } from "@blitzjs/next"
77
8+ const parseFormerTeamIds = ( value : unknown ) : number [ ] => {
9+ if ( ! Array . isArray ( value ) ) return [ ]
10+ return value
11+ . map ( ( id ) => {
12+ if ( typeof id === "number" ) return id
13+ const parsed = Number ( id )
14+ return Number . isFinite ( parsed ) ? parsed : null
15+ } )
16+ . filter ( ( id ) : id is number => id !== null )
17+ }
18+
819export default resolver . pipe (
920 resolver . zod ( AcceptInviteSchema ) ,
1021 resolver . authorize ( ) ,
@@ -17,27 +28,86 @@ export default resolver.pipe(
1728 if ( ! invite ) throw new Error ( "Invitation not found" )
1829
1930 let projectMember
31+ let formerTeamIds : number [ ] = [ ]
32+
33+ const reconnectFormerTeams = async ( teamIds : number [ ] ) => {
34+ if ( teamIds . length === 0 ) return
35+
36+ for ( const teamId of teamIds ) {
37+ try {
38+ await db . projectMember . update ( {
39+ where : { id : teamId } ,
40+ data : {
41+ users : {
42+ connect : { id : userId } ,
43+ } ,
44+ } ,
45+ } )
46+ } catch ( error ) {
47+ console . error (
48+ `[acceptInvite] Failed to reconnect user ${ userId } to team ${ teamId } :` ,
49+ error
50+ )
51+ }
52+ }
53+ }
2054
2155 // Check if this is a reassignment invitation
2256 if ( invite . reassignmentFor ) {
57+ const reassignmentTarget = await db . projectMember . findUnique ( {
58+ where : { id : invite . reassignmentFor } ,
59+ } )
60+ if ( ! reassignmentTarget ) {
61+ throw new Error ( "Reassignment target not found" )
62+ }
63+ formerTeamIds = parseFormerTeamIds ( reassignmentTarget . formerTeamIds )
64+
2365 // Restore the soft-deleted ProjectMember
2466 projectMember = await db . projectMember . update ( {
2567 where : { id : invite . reassignmentFor } ,
26- data : { deleted : false } ,
68+ data : {
69+ deleted : false ,
70+ tags : invite . tags as any ,
71+ formerTeamIds : formerTeamIds . length > 0 ? formerTeamIds : undefined ,
72+ } ,
2773 } )
2874 } else {
29- // Create a new ProjectMember for fresh invitations
30- projectMember = await db . projectMember . create ( {
31- data : {
75+ // Check whether this user already has a soft-deleted ProjectMember for this project
76+ const existingProjectMember = await db . projectMember . findFirst ( {
77+ where : {
78+ projectId : invite . projectId ,
3279 users : {
33- connect : { id : userId } ,
80+ some : { id : userId } ,
3481 } ,
35- projectId : invite . projectId ,
36- tags : invite . tags as any ,
3782 } ,
3883 } )
84+
85+ if ( existingProjectMember ) {
86+ formerTeamIds = parseFormerTeamIds ( existingProjectMember . formerTeamIds )
87+ projectMember = await db . projectMember . update ( {
88+ where : { id : existingProjectMember . id } ,
89+ data : {
90+ deleted : false ,
91+ tags : invite . tags as any ,
92+ formerTeamIds : formerTeamIds . length > 0 ? formerTeamIds : undefined ,
93+ } ,
94+ } )
95+ } else {
96+ // Create a new ProjectMember for fresh invitations
97+ projectMember = await db . projectMember . create ( {
98+ data : {
99+ users : {
100+ connect : { id : userId } ,
101+ } ,
102+ projectId : invite . projectId ,
103+ tags : invite . tags as any ,
104+ } ,
105+ } )
106+ }
39107 }
40108
109+ await reconnectFormerTeams ( formerTeamIds )
110+
41111 // Create the project privilege
42112 const projectPrivilege = await db . projectPrivilege . create ( {
43113 data : {
0 commit comments