diff --git a/apps/dokploy/components/dashboard/settings/users/show-invitations.tsx b/apps/dokploy/components/dashboard/settings/users/show-invitations.tsx index 1bf7aa08..8c9813fc 100644 --- a/apps/dokploy/components/dashboard/settings/users/show-invitations.tsx +++ b/apps/dokploy/components/dashboard/settings/users/show-invitations.tsx @@ -36,6 +36,9 @@ export const ShowInvitations = () => { const { data, isLoading, refetch } = api.organization.allInvitations.useQuery(); + const { mutateAsync: removeInvitation } = + api.organization.removeInvitation.useMutation(); + return (
@@ -182,6 +185,22 @@ export const ShowInvitations = () => { Cancel Invitation )} + + { + await removeInvitation({ + invitationId: invitation.id, + }).then(() => { + refetch(); + toast.success( + "Invitation removed", + ); + }); + }} + > + Remove Invitation + )} diff --git a/apps/dokploy/server/api/routers/organization.ts b/apps/dokploy/server/api/routers/organization.ts index 3d7753de..25498143 100644 --- a/apps/dokploy/server/api/routers/organization.ts +++ b/apps/dokploy/server/api/routers/organization.ts @@ -157,4 +157,31 @@ export const organizationRouter = createTRPCRouter({ orderBy: [desc(invitation.status), desc(invitation.expiresAt)], }); }), + removeInvitation: adminProcedure + .input(z.object({ invitationId: z.string() })) + .mutation(async ({ ctx, input }) => { + const invitationResult = await db.query.invitation.findFirst({ + where: eq(invitation.id, input.invitationId), + }); + + if (!invitationResult) { + throw new TRPCError({ + code: "NOT_FOUND", + message: "Invitation not found", + }); + } + + if ( + invitationResult?.organizationId !== ctx.session.activeOrganizationId + ) { + throw new TRPCError({ + code: "FORBIDDEN", + message: "You are not allowed to remove this invitation", + }); + } + + return await db + .delete(invitation) + .where(eq(invitation.id, input.invitationId)); + }), });