From e31baa1f40f85efaa91b401847fa4e17fb60db68 Mon Sep 17 00:00:00 2001 From: hailin Date: Sat, 7 Mar 2026 05:34:47 -0800 Subject: [PATCH] fix(auth): fix invite flow UUID/slug mismatch and removeMember cleanup - TenantController invite endpoints (list/create/revoke) were passing the tenant UUID from the URL param directly to AuthService methods that expect a slug, causing 404 on every invite operation. Now resolves tenant via findTenantOrFail() first and passes slug. - removeMember now also deletes from public.users so removed members can no longer log in. Co-Authored-By: Claude Sonnet 4.6 --- .../rest/controllers/tenant.controller.ts | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/packages/services/auth-service/src/interfaces/rest/controllers/tenant.controller.ts b/packages/services/auth-service/src/interfaces/rest/controllers/tenant.controller.ts index ac0f6a8..5552158 100644 --- a/packages/services/auth-service/src/interfaces/rest/controllers/tenant.controller.ts +++ b/packages/services/auth-service/src/interfaces/rest/controllers/tenant.controller.ts @@ -274,6 +274,10 @@ export class TenantController { } await qr.query(`DELETE FROM users WHERE id = $1`, [memberId]); + // Also remove from global user index so the user can no longer log in + await this.dataSource.query( + `DELETE FROM public.users WHERE id = $1`, [memberId], + ); return { success: true }; } finally { await qr.release(); @@ -287,8 +291,9 @@ export class TenantController { */ @Get(':id/invites') @Roles('admin') - async listInvites(@Param('id') tenantId: string) { - const invites = await this.authService.listInvites(tenantId); + async listInvites(@Param('id') id: string) { + const tenant = await this.findTenantOrFail(id); + const invites = await this.authService.listInvites(tenant.slug); return invites.map((inv) => ({ id: inv.id, email: inv.email, @@ -306,12 +311,13 @@ export class TenantController { @Post(':id/invites') @Roles('admin') async createInvite( - @Param('id') tenantId: string, + @Param('id') id: string, @Body() body: { email: string; role?: string }, @Request() req: any, ) { + const tenant = await this.findTenantOrFail(id); const invite = await this.authService.createInvite( - tenantId, + tenant.slug, body.email, body.role || 'viewer', req.user?.sub || 'system', @@ -333,10 +339,11 @@ export class TenantController { @Delete(':id/invites/:inviteId') @Roles('admin') async revokeInvite( - @Param('id') tenantId: string, + @Param('id') id: string, @Param('inviteId') inviteId: string, ) { - await this.authService.revokeInvite(inviteId, tenantId); + const tenant = await this.findTenantOrFail(id); + await this.authService.revokeInvite(inviteId, tenant.slug); return { success: true }; }