Refactor authentication and carousel services; enhance error handling and validation

This commit is contained in:
jorgemike
2025-05-13 19:42:36 -06:00
parent d6a63dae13
commit 6fe658f668
7 changed files with 131 additions and 37 deletions
+5 -4
View File
@@ -1,18 +1,19 @@
import { Body, Controller, Post, Request, UseGuards } from '@nestjs/common';
import { AuthGuard } from '@nestjs/passport';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Body, Controller, Post } from '@nestjs/common';
import { AuthService } from './auth.service';
import { LoginMiembroDto } from './dto/loginMiembro.dto';
import { RegistrarMiembroDto } from './dto/registrarMiembro.dto';
import { ApiTags } from '@nestjs/swagger';
import { ApiPostRegistro } from './auth.docs';
@Controller('auth')
@ApiTags('auth')
export class AuthController {
constructor(
private authService: AuthService,
) /* @InjectRepository(Usuario) private usuarioRepository: Repository<Usuario> */ {}
@Post('registro')
@ApiPostRegistro()
registrarUsuario(@Body() registrarMiembro: RegistrarMiembroDto) {
return this.authService.registrar(registrarMiembro);
}
+78
View File
@@ -0,0 +1,78 @@
import { applyDecorators } from '@nestjs/common';
import {
ApiOperation,
ApiResponse,
ApiTags,
ApiBody,
} from '@nestjs/swagger';
import { RegistrarMiembroDto } from './dto/registrarMiembro.dto';
export function ApiPostRegistro() {
return applyDecorators(
ApiTags('Auth'),
ApiOperation({
summary: 'Registrar nuevo miembro',
description:
'Registra un nuevo usuario en la plataforma. No se permite duplicidad de correo electrónico.',
}),
ApiBody({
type: RegistrarMiembroDto,
examples: {
requeridos: {
summary: 'Solo datos obligatorios',
description: 'Ejemplo básico con los campos mínimos requeridos para registrar un usuario.',
value: {
nombre: 'Luis',
apellido_paterno: 'Martínez',
apellido_materno: 'Lopez',
id_tipo_miembro: 1,
password: 'contraseñaSegura123',
cuenta: 421010101,
email: 'luis@example.com',
},
},
completo: {
summary: 'Todos los campos llenos',
description: 'Ejemplo de un usuario con carrera, semestre y descripción.',
value: {
nombre: 'Ana',
apellido_paterno: 'Torres',
apellido_materno: 'Hernández',
id_tipo_miembro: 2,
password: 'AnaSegura456',
descripcion: 'Estudiante interesada en programación web',
id_carrera: 3,
semestre: '4°',
cuenta: 421020202,
email: 'ana.torres@example.com',
},
},
invalido: {
summary: 'Ejemplo con datos inválidos',
description: 'Muestra un correo mal formado y una contraseña demasiado corta.',
value: {
nombre: 'Mario',
apellido_paterno: 'Gómez',
apellido_materno: 'Ramírez',
id_tipo_miembro: 1,
password: '123',
cuenta: 421000000,
email: 'mario-sin-arroba.com',
},
},
},
}),
ApiResponse({
status: 201,
description: 'Usuario registrado exitosamente.',
}),
ApiResponse({
status: 403,
description: 'El usuario ya existe.',
}),
ApiResponse({
status: 400,
description: 'Datos inválidos o faltantes.',
}),
);
}
+2 -10
View File
@@ -44,16 +44,8 @@ export class CarruselController {
},
}),
)
addImagenToCarrusel(
@Body() carruselDto: carruselDto,
@UploadedFile() file,
@Res() res,
) {
return this.carruselService.addImagenToCarrusel(
carruselDto,
file.filename,
res,
);
addImagenToCarrusel(@Body() carruselDto: carruselDto, @UploadedFile() file) {
return this.carruselService.addImagenToCarrusel(carruselDto, file.filename);
}
@Delete('delete/:id')
+39 -21
View File
@@ -1,4 +1,4 @@
import { Injectable } from '@nestjs/common';
import { BadRequestException, Injectable, InternalServerErrorException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Carrusel } from 'src/entities/carrusel.entity';
import { Repository } from 'typeorm';
@@ -13,31 +13,49 @@ export class CarruselService {
private carruselRepository: Repository<Carrusel>,
) {}
addImagenToCarrusel(
async addImagenToCarrusel(
carruselDto: carruselDto,
filename,
res: Response,
): Promise<Carrusel> {
filename: string,
): Promise<{ message: string; carrusel: Carrusel }> {
if (!filename) {
throw new BadRequestException({
message: 'No se ha subido la imagen',
});
}
if (!carruselDto.link) {
throw new BadRequestException({
message: 'El campo "link" es obligatorio',
});
}
if (carruselDto.link.length > 100) {
throw new BadRequestException({
message: 'El campo "link" no puede tener más de 100 caracteres',
});
}
carruselDto.ruta = `/public/carrusel/${filename}`;
const carruselCreate = this.carruselRepository.create(carruselDto);
return this.carruselRepository
.save(carruselCreate)
.then((carrusel) => {
res
.status(201)
.json({ message: 'Imagen agregada correctamente', carrusel });
return carrusel;
})
.catch((error) => {
res.status(500).json({
message: 'Error al agregar la imagen',
error,
});
throw error;
try {
const carrusel = await this.carruselRepository.save(carruselCreate);
return {
message: 'Imagen agregada correctamente',
carrusel,
};
} catch (error) {
console.error('❌ Error al guardar carrusel en base de datos');
console.table({
code: error.code,
message: error.message,
});
}
throw new InternalServerErrorException({
message: 'Ocurrió un error inesperado al guardar la imagen',
error: error.message,
});
}
}
async deleteImagenByRuta(id: number) {
try {
const res = await this.carruselRepository.findOne({
@@ -54,6 +72,6 @@ export class CarruselService {
}
getAllImages(): Promise<Carrusel[]> {
return this.carruselRepository.find()
return this.carruselRepository.find();
}
}
+1 -1
View File
@@ -9,7 +9,7 @@ export class Carrusel {
ruta: string
/* "/public/carrusel/carrusel1.jpg" */
@Column({length: 60})
@Column({length: 100})
link: string
/* "https://www.acatlan.unam.mx/" */
}
+1 -1
View File
@@ -59,7 +59,7 @@ export class EventosController {
this.eventoService.exportarParticipantes(id, res)
}
@Post('disponibles')
@Get('disponibles')
getEventosDisponibles (){
return this.eventoService.getEventosDisponibles()
}
+5
View File
@@ -20,7 +20,12 @@ async function bootstrap() {
prefix: '/public/',
});
app.enableCors();
await app.listen(AppModule.port);
const port = AppModule.port;
console.log(`Documentacion disponible en: http://localhost:${port}/api`);
console.log(`Servidor desplegado en: http://localhost:${port}`);
}
bootstrap();