import { BadRequestException, Body, Controller, Delete, Get, Patch, Post, StreamableFile, UploadedFile, UseGuards, UseInterceptors, } from '@nestjs/common'; import { FileInterceptor } from '@nestjs/platform-express'; import { memoryStorage } from 'multer'; import { AuthService } from './auth.service'; import { LoginDto, LoginOtpRequestDto, LoginOtpVerifyDto, RegisterOrganizationDto, RegisterVerifyOtpDto, SelectOrganizationDto, SwitchOrganizationDto, UpdateProfileDto, } from './dto'; import { JwtAuthGuard } from './jwt-auth.guard'; import { CurrentUser } from './current-user.decorator'; import type { Actor } from '../common/record-scope'; @Controller('auth') export class AuthController { constructor(private readonly authService: AuthService) {} @Post('register') register(@Body() dto: RegisterOrganizationDto) { return this.authService.startRegister(dto); } @Post('register/verify') registerVerify(@Body() dto: RegisterVerifyOtpDto) { return this.authService.verifyRegister(dto); } /** ورود با رمز (بدون OTP) */ @Post('login') login(@Body() dto: LoginDto) { return this.authService.loginWithPassword(dto); } /** درخواست کد ورود با موبایل */ @Post('login/otp') loginOtpRequest(@Body() dto: LoginOtpRequestDto) { return this.authService.requestLoginOtp(dto); } /** تأیید کد ورود با موبایل */ @Post('login/otp/verify') loginOtpVerify(@Body() dto: LoginOtpVerifyDto) { return this.authService.verifyLoginOtp(dto); } @Post('select-organization') selectOrganization(@Body() dto: SelectOrganizationDto) { return this.authService.selectOrganization(dto.selectionToken, dto.organizationId); } @UseGuards(JwtAuthGuard) @Post('switch-organization') switchOrganization( @CurrentUser() user: Actor, @Body() dto: SwitchOrganizationDto, ) { return this.authService.switchOrganization(user.userId, dto.organizationId); } @UseGuards(JwtAuthGuard) @Get('organizations') listOrganizations(@CurrentUser() user: Actor) { return this.authService.listMyOrganizations(user.userId); } @UseGuards(JwtAuthGuard) @Post('logout') logout(@CurrentUser() user: Actor) { return this.authService.logout(user); } @UseGuards(JwtAuthGuard) @Get('me') me(@CurrentUser() user: Actor) { return this.authService.me(user.userId, user.organizationId, user); } @UseGuards(JwtAuthGuard) @Post('view-as') viewAs( @CurrentUser() user: Actor, @Body() body: { targetUserId?: string }, ) { if (!body.targetUserId?.trim()) { throw new BadRequestException('کاربر هدف مشخص نیست.'); } return this.authService.viewAs(user, body.targetUserId.trim()); } @UseGuards(JwtAuthGuard) @Patch('me') updateMe(@CurrentUser() user: Actor, @Body() dto: UpdateProfileDto) { return this.authService.updateMe(user.userId, user.organizationId, dto); } @UseGuards(JwtAuthGuard) @Patch('me/prior-archive') setPriorLens( @CurrentUser() user: Actor, @Body() body: { lens?: string }, ) { if (body.lens !== 'archive' && body.lens !== 'current') { throw new BadRequestException('حالت بایگانی نامعتبر است'); } return this.authService.setPriorLens( user.userId, user.organizationId, body.lens, user, ); } /** عکس پروفایل کاربر جاری */ @UseGuards(JwtAuthGuard) @Get('me/avatar') async avatar(@CurrentUser() user: Actor) { const file = await this.authService.openAvatar(user.userId); return new StreamableFile(file.stream, { type: file.mimeType }); } @UseGuards(JwtAuthGuard) @Post('me/avatar') @UseInterceptors( FileInterceptor('file', { storage: memoryStorage(), limits: { fileSize: 2 * 1024 * 1024 }, }), ) uploadAvatar( @CurrentUser() user: Actor, @UploadedFile() file: Express.Multer.File, ) { return this.authService.saveAvatar(user.userId, user.organizationId, file); } @UseGuards(JwtAuthGuard) @Delete('me/avatar') removeAvatar(@CurrentUser() user: Actor) { return this.authService.removeAvatar(user.userId, user.organizationId); } }