@@ -79,6 +79,57 @@ export async function cardRoutes(app: FastifyInstance): Promise<void> {
7979 }
8080
8181 try {
82+ // Verify every supplied link belongs to the authenticated user before any write.
83+ // A count mismatch means at least one ID is foreign — reject before touching the DB.
84+ if ( parsed . data . linkIds . length > 0 ) {
85+ const ownedLinks = await app . prisma . platformLink . findMany ( {
86+ where : { id : { in : parsed . data . linkIds } , userId } ,
87+ select : { id : true } ,
88+ } ) ;
89+
90+ if ( ownedLinks . length !== parsed . data . linkIds . length ) {
91+ return reply . status ( 403 ) . send ( { error : 'One or more links do not belong to your account' } ) ;
92+ }
93+ }
94+
95+ // Check if user's first card -> make it default.
96+ // Prisma wraps the nested cardLinks.create inside card.create in a single
97+ // implicit transaction, so either both the card and its links are written or neither is.
98+ const card = await app . prisma . $transaction ( async ( tx ) => {
99+ const cardCount = await tx . card . count ( {
100+ where : { userId } ,
101+ } ) ;
102+
103+ return tx . card . create ( {
104+ data : {
105+ userId,
106+ title : parsed . data . title ,
107+ isDefault : cardCount === 0 ,
108+ cardLinks : {
109+ create : parsed . data . linkIds . map ( ( linkId , index ) => ( {
110+ platformLinkId : linkId ,
111+ displayOrder : index ,
112+ } ) ) ,
113+ } ,
114+ } ,
115+ include : {
116+ cardLinks : {
117+ include : { platformLink : true } ,
118+ orderBy : { displayOrder : 'asc' } ,
119+ } ,
120+ } ,
121+ } ) ;
122+ } } ;
123+ const response = {
124+ id : card . id ,
125+ title : card . title ,
126+ isDefault : card . isDefault ,
127+ links : card . cardLinks . map ( ( cl : CardLinkWithPlatform ) => cl . platformLink ) ,
128+ }
129+
130+ return reply . status ( 201 ) . send ( response ) ;
131+ } catch ( error ) {
132+ return handleDbError ( error , request , reply ) ;
82133 const card = await cardService . createCard ( app , userId , parsed . data )
83134 return reply . status ( 201 ) . send ( card )
84135 } catch ( error : any) {
0 commit comments