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:
parent
915bd400c1
commit
e31baa1f40
|
|
@ -274,6 +274,10 @@ export class TenantController {
|
||||||
}
|
}
|
||||||
|
|
||||||
await qr.query(`DELETE FROM users WHERE id = $1`, [memberId]);
|
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 };
|
return { success: true };
|
||||||
} finally {
|
} finally {
|
||||||
await qr.release();
|
await qr.release();
|
||||||
|
|
@ -287,8 +291,9 @@ export class TenantController {
|
||||||
*/
|
*/
|
||||||
@Get(':id/invites')
|
@Get(':id/invites')
|
||||||
@Roles('admin')
|
@Roles('admin')
|
||||||
async listInvites(@Param('id') tenantId: string) {
|
async listInvites(@Param('id') id: string) {
|
||||||
const invites = await this.authService.listInvites(tenantId);
|
const tenant = await this.findTenantOrFail(id);
|
||||||
|
const invites = await this.authService.listInvites(tenant.slug);
|
||||||
return invites.map((inv) => ({
|
return invites.map((inv) => ({
|
||||||
id: inv.id,
|
id: inv.id,
|
||||||
email: inv.email,
|
email: inv.email,
|
||||||
|
|
@ -306,12 +311,13 @@ export class TenantController {
|
||||||
@Post(':id/invites')
|
@Post(':id/invites')
|
||||||
@Roles('admin')
|
@Roles('admin')
|
||||||
async createInvite(
|
async createInvite(
|
||||||
@Param('id') tenantId: string,
|
@Param('id') id: string,
|
||||||
@Body() body: { email: string; role?: string },
|
@Body() body: { email: string; role?: string },
|
||||||
@Request() req: any,
|
@Request() req: any,
|
||||||
) {
|
) {
|
||||||
|
const tenant = await this.findTenantOrFail(id);
|
||||||
const invite = await this.authService.createInvite(
|
const invite = await this.authService.createInvite(
|
||||||
tenantId,
|
tenant.slug,
|
||||||
body.email,
|
body.email,
|
||||||
body.role || 'viewer',
|
body.role || 'viewer',
|
||||||
req.user?.sub || 'system',
|
req.user?.sub || 'system',
|
||||||
|
|
@ -333,10 +339,11 @@ export class TenantController {
|
||||||
@Delete(':id/invites/:inviteId')
|
@Delete(':id/invites/:inviteId')
|
||||||
@Roles('admin')
|
@Roles('admin')
|
||||||
async revokeInvite(
|
async revokeInvite(
|
||||||
@Param('id') tenantId: string,
|
@Param('id') id: string,
|
||||||
@Param('inviteId') inviteId: 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 };
|
return { success: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue