Files
edr-platform/apps/edr-passenger-api/src/modules/auth/auth.controller.ts
2026-06-26 14:20:32 +03:00

142 lines
5.4 KiB
TypeScript

import { Body, Controller, Post, HttpCode, HttpStatus, UseGuards, Get, Patch, Delete, Param, Request, Query, UnauthorizedException } from '@nestjs/common';
import { ApiTags, ApiOperation, ApiResponse, ApiBody, ApiBearerAuth } from '@nestjs/swagger';
import { Throttle, SkipThrottle } from '@nestjs/throttler';
import { IsPublic } from '@tria-plc/api-common/modules/auth/decorators/public.decorator';
import { PassengerAuthService } from './passenger-auth.service';
import { RegisterDto, LoginDto, FaydaRequestPasswordSetupDto, FaydaVerifyAndLoginDto } from './auth.dto';
import { JwtGuard } from '../../common/jwt.guard';
@ApiTags('Passenger Auth')
@Controller('auth')
@Throttle({ auth: { limit: 5, ttl: 60_000 } })
export class AuthController {
constructor(private passengerAuthService: PassengerAuthService) {}
@Post('register')
@IsPublic()
@ApiOperation({ summary: 'Register new passenger account' })
@ApiResponse({ status: 201, description: 'Account created. Returns token + user.' })
@ApiResponse({ status: 409, description: 'Email or phone already registered' })
@ApiBody({ type: RegisterDto })
register(@Request() req: any, @Body() dto: RegisterDto) {
return this.passengerAuthService.register(dto, req);
}
@Post('login')
@IsPublic()
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'Login with email and password' })
@ApiResponse({ status: 200, description: 'Login successful. Returns token + passengerId.' })
@ApiResponse({ status: 401, description: 'Invalid credentials' })
@ApiBody({ type: LoginDto })
login(@Request() req: any, @Body() dto: LoginDto) {
return this.passengerAuthService.login(dto, req);
}
@Post('logout')
@HttpCode(HttpStatus.OK)
@UseGuards(JwtGuard)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Logout current user' })
@ApiResponse({ status: 200, description: 'Logout successful' })
@ApiResponse({ status: 401, description: 'Unauthorized' })
logout(@Request() req: any) {
if (!req.user?.id) throw new UnauthorizedException('User not authenticated');
return this.passengerAuthService.logout(req.user, req);
}
@Get('me')
@UseGuards(JwtGuard)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: '[DEV] Inspect raw JWT payload — shows full req.user from JwtGuard' })
@ApiResponse({ status: 200, description: 'Returns the full req.user object set by JwtGuard' })
@ApiResponse({ status: 401, description: 'Unauthorized' })
getMe(@Request() req: any) {
return { user: req.user };
}
@Get('profile')
@UseGuards(JwtGuard)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Get current user profile' })
@ApiResponse({ status: 200, description: 'User profile retrieved successfully' })
@ApiResponse({ status: 401, description: 'Unauthorized' })
getProfile(@Request() req: any) {
const userId = req.user?.id;
if (!userId) throw new UnauthorizedException('User not authenticated');
return this.passengerAuthService.getProfile(userId);
}
// TODO: admin user management endpoints — implement when admin module is ready
@Get('users')
@UseGuards(JwtGuard)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'List all users (admin)' })
listUsers(
@Query('search') search?: string,
@Query('role') role?: string,
@Query('status') status?: string,
@Query('page') page?: string,
@Query('pageSize') pageSize?: string,
) {
return this.passengerAuthService.listUsers({
search, role, status,
page: page ? +page : 1,
pageSize: pageSize ? +pageSize : 20,
});
}
@Post('users')
@UseGuards(JwtGuard)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Create user (admin)' })
createUser(@Body() body: any) {
return this.passengerAuthService.createUser(body);
}
@Patch('users/:id')
@UseGuards(JwtGuard)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Update user (admin)' })
updateUser(@Param('id') id: string, @Body() body: any) {
return this.passengerAuthService.updateUser(id, body);
}
@Delete('users/:id')
@UseGuards(JwtGuard)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Delete user (admin)' })
deleteUser(@Param('id') id: string) {
return this.passengerAuthService.deleteUser(id);
}
@Post('users/:id/reset-password')
@UseGuards(JwtGuard)
@ApiBearerAuth('JWT-auth')
@ApiOperation({ summary: 'Reset user password (admin)' })
resetPassword(@Param('id') id: string, @Body() body: { tempPassword: string }) {
return this.passengerAuthService.resetUserPassword(id, body.tempPassword);
}
@Post('fayda/request-password-setup')
@IsPublic()
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'Send OTP to phone for Fayda-verified account password setup' })
@ApiResponse({ status: 200, description: 'OTP sent to registered phone number' })
@ApiBody({ type: FaydaRequestPasswordSetupDto })
requestFaydaPasswordSetup(@Body() dto: FaydaRequestPasswordSetupDto, @Request() req: any) {
return this.passengerAuthService.requestFaydaPasswordSetup(dto.phoneNumber, req);
}
@Post('fayda/verify-and-login')
@IsPublic()
@HttpCode(HttpStatus.OK)
@ApiOperation({ summary: 'Verify OTP and receive session token for Fayda-verified account' })
@ApiResponse({ status: 200, description: 'Returns token + requiresPassword flag. Use token with POST /v1/auth/set-fayda-password.' })
@ApiBody({ type: FaydaVerifyAndLoginDto })
verifyFaydaAndLogin(@Body() dto: FaydaVerifyAndLoginDto) {
return this.passengerAuthService.verifyFaydaAndLogin(dto.phoneNumber, dto.otp);
}
}