fix: ( iam ) resolve post-merge type errors and apply IAM column migrations

This commit is contained in:
Abubeker Yasin
2026-06-22 11:22:57 +03:00
parent 177e1cea8d
commit 7108035f7e
9 changed files with 139 additions and 81 deletions

View File

@@ -1,11 +1,8 @@
import { Body, Controller, Post, HttpCode, HttpStatus, UseGuards, Get, Request, UnauthorizedException, Param, Patch, Delete, Query } from '@nestjs/common';
import { Body, Controller, Post, HttpCode, HttpStatus, UseGuards, Get, Request, UnauthorizedException } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiBody, ApiBearerAuth } from '@nestjs/swagger';
import { PassengerAuthService } from './passenger-auth.service';
import { RegisterDto, LoginDto } from './auth.dto';
import { JwtGuard } from '../../common/jwt.guard';
import { RolesGuard } from '../../common/roles.guard';
import { Roles } from '../../common/roles.decorator';
import { UserRole } from '@prisma/client';
@ApiTags('Auth')
@Controller('auth')
@@ -65,60 +62,5 @@ export class AuthController {
return this.passengerAuthService.getProfile(userId);
}
@Get('users')
@UseGuards(JwtGuard, RolesGuard)
@Roles(UserRole.ADMIN, UserRole.SUPERVISOR)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Get all backoffice users (admin/supervisor only)' })
getUsers(
@Query('search') search?: string,
@Query('role') role?: string,
@Query('status') status?: string,
@Query('page') page?: string,
@Query('pageSize') pageSize?: string,
) {
return this.service.getUsers({
search,
role,
status,
page: page ? parseInt(page) : 1,
pageSize: pageSize ? parseInt(pageSize) : 10,
});
}
@Post('users')
@UseGuards(JwtGuard, RolesGuard)
@Roles(UserRole.ADMIN, UserRole.SUPERVISOR)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Create new backoffice user (admin/supervisor only)' })
createUser(@Body() dto: any) {
return this.service.createUser(dto);
}
@Patch('users/:id')
@UseGuards(JwtGuard, RolesGuard)
@Roles(UserRole.ADMIN, UserRole.SUPERVISOR)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Update backoffice user (admin/supervisor only)' })
updateUser(@Param('id') id: string, @Body() dto: any) {
return this.service.updateUser(id, dto);
}
@Delete('users/:id')
@UseGuards(JwtGuard, RolesGuard)
@Roles(UserRole.ADMIN)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Delete backoffice user (admin only)' })
deleteUser(@Param('id') id: string) {
return this.service.deleteUser(id);
}
@Post('users/:id/reset-password')
@UseGuards(JwtGuard, RolesGuard)
@Roles(UserRole.ADMIN, UserRole.SUPERVISOR)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Reset user password with temporary password (admin/supervisor only)' })
resetUserPassword(@Param('id') id: string, @Body() dto: { tempPassword: string }) {
return this.service.resetUserPassword(id, dto.tempPassword);
}
// TODO: admin user management endpoints — implement when admin module is ready
}

View File

@@ -195,8 +195,35 @@ export class PassengerAuthService {
private async compensateIamSignup(email: string): Promise<void> {
try {
await this.dataSource.query(`DELETE FROM iam.sessions WHERE email = $1`, [email]);
await this.dataSource.query(`DELETE FROM iam.users WHERE email = $1`, [email]);
const rows = await this.dataSource.query<{ id: string }[]>(
`SELECT id FROM iam.users WHERE email = $1 LIMIT 1`,
[email],
);
if (!rows.length) return;
const iamUserId = rows[0].id;
// Discover every table in the iam schema that has a FK pointing at iam.users.id
const fkDeps = await this.dataSource.query<{ table_name: string; column_name: string }[]>(`
SELECT kcu.table_name, kcu.column_name
FROM information_schema.table_constraints tc
JOIN information_schema.key_column_usage kcu
ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
JOIN information_schema.referential_constraints rc
ON tc.constraint_name = rc.constraint_name
JOIN information_schema.key_column_usage ccu
ON rc.unique_constraint_name = ccu.constraint_name
WHERE ccu.table_schema = 'iam' AND ccu.table_name = 'users' AND ccu.column_name = 'id'
AND tc.table_schema = 'iam' AND tc.constraint_type = 'FOREIGN KEY'
`);
for (const { table_name, column_name } of fkDeps) {
await this.dataSource.query(
`DELETE FROM iam.${table_name} WHERE ${column_name} = $1`,
[iamUserId],
);
}
await this.dataSource.query(`DELETE FROM iam.users WHERE id = $1`, [iamUserId]);
} catch (err) {
console.error('[PassengerAuthService] IAM compensating cleanup failed for', email, (err as Error).message);
}