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 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-03-07 05:34:47 -08:00
parent 915bd400c1
commit e31baa1f40
1 changed files with 13 additions and 6 deletions

View File

@ -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 };
}