From 481c70b5c7d9bbe36fc07af747829b03ef5cfb85 Mon Sep 17 00:00:00 2001 From: Gabriel Viell Castilho Date: Mon, 27 Apr 2026 10:49:29 -0300 Subject: [PATCH] feat: delete image route --- backend/src/modules/email/email.service.ts | 2 +- .../modules/file/application/file.service.ts | 38 ++++++++++++++++++- .../file/presentation/file.controller.ts | 37 +++++++++++++++++- 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/backend/src/modules/email/email.service.ts b/backend/src/modules/email/email.service.ts index c85e974..375bdf4 100644 --- a/backend/src/modules/email/email.service.ts +++ b/backend/src/modules/email/email.service.ts @@ -12,7 +12,7 @@ export class EmailService { }); async sendResetPasswordEmail(email: string, token: string) { - const resetLink = `myapp://reset-password?token=${token}`; + const resetLink = `frontend://resetPassword?token=${token}`; await this.transporter.sendMail({ to: email, diff --git a/backend/src/modules/file/application/file.service.ts b/backend/src/modules/file/application/file.service.ts index f007470..bbe9128 100644 --- a/backend/src/modules/file/application/file.service.ts +++ b/backend/src/modules/file/application/file.service.ts @@ -1,4 +1,4 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; +import { BadRequestException, Injectable, NotFoundException } from '@nestjs/common'; import { InjectModel } from '@nestjs/mongoose'; import { Model } from 'mongoose'; import { FileDocument } from '../infra/schemas/file.schema'; @@ -127,6 +127,24 @@ async uploadProfileImage( return user.profileImage; } + async deleteUserProfileImage(userId: string): Promise { + const user = await this.userModel.findById(userId); + + if (!user) { + throw new NotFoundException('User not found'); + } + + if (!user.profileImage) { + throw new BadRequestException('User does not have a profile image'); + } + + this.storage.delete(user.profileImage); + + await this.userModel.findByIdAndUpdate(userId, { + profileImage: null, + }); +} + async uploadCompanyLogo( file: Express.Multer.File, companyId: string @@ -179,4 +197,22 @@ async uploadProfileImage( return company.logo; } + + async deleteCompanyImage(companyId: string): Promise { + const company = await this.companyModel.findById(companyId); + + if (!company) { + throw new NotFoundException('Company not found'); + } + + if (!company.logo) { + throw new BadRequestException('Company does not have an image'); + } + + this.storage.delete(company.logo); + + await this.companyModel.findByIdAndUpdate(companyId, { + image: null, + }); +} } \ No newline at end of file diff --git a/backend/src/modules/file/presentation/file.controller.ts b/backend/src/modules/file/presentation/file.controller.ts index 38235bd..f667e05 100644 --- a/backend/src/modules/file/presentation/file.controller.ts +++ b/backend/src/modules/file/presentation/file.controller.ts @@ -1,5 +1,5 @@ -import { Controller, Post, UploadedFile, UseInterceptors, UseGuards, Body, Req, Param, Get, Res, BadRequestException } from '@nestjs/common'; -import { ApiBearerAuth, ApiConsumes, ApiBody, ApiOperation, ApiTags } from '@nestjs/swagger'; +import { Controller, Post, UploadedFile, UseInterceptors, UseGuards, Body, Req, Param, Get, Res, BadRequestException, Delete } from '@nestjs/common'; +import { ApiBearerAuth, ApiConsumes, ApiBody, ApiOperation, ApiTags, ApiResponse, ApiParam } from '@nestjs/swagger'; import { FileInterceptor } from '@nestjs/platform-express'; import { JwtGuard } from '../../auth/guards/jwt.guard'; import { RolesGuard } from '../../auth/guards/roles.guard'; @@ -163,6 +163,23 @@ export class FileController { return this.fileService.uploadCompanyLogo(file, companyId); } + @Delete('profile') + @UseGuards(JwtGuard, RolesGuard) + @Roles(UserRole.ADMIN, UserRole.SUPPORT, UserRole.CLIENT) + @ApiOperation({ summary: 'Remover foto de perfil do usuário' }) + @ApiResponse({ status: 200, description: 'Imagem removida com sucesso' }) + @ApiResponse({ status: 400, description: 'Usuário não possui imagem' }) + @ApiResponse({ status: 404, description: 'Usuário não encontrado' }) + async deleteProfileImage( + @Req() req: Request & { user: { id: string } }, + ) { + const userId = req.user.id; + + await this.fileService.deleteUserProfileImage(userId); + + return { message: 'Image removed successfully' }; + } + @Get('company/:companyId') async getCompanyLogo( @Param('companyId') companyId: string, @@ -179,4 +196,20 @@ export class FileController { return res.sendFile(filePath, { root: './' }); } + + @Delete('company/:companyId') + @UseGuards(JwtGuard, RolesGuard) + @Roles(UserRole.ADMIN) + @ApiOperation({ summary: 'Remover imagem da empresa' }) + @ApiParam({ name: 'companyId' }) + @ApiResponse({ status: 200, description: 'Imagem removida com sucesso' }) + @ApiResponse({ status: 400, description: 'Empresa não possui imagem' }) + @ApiResponse({ status: 404, description: 'Empresa não encontrada' }) + async deleteCompanyImage( + @Param('companyId') companyId: string, + ) { + await this.fileService.deleteCompanyImage(companyId); + + return { message: 'Image removed successfully' }; + } } \ No newline at end of file