From 132d1b18d9bc2fa978e3377c03346bcd158e2404 Mon Sep 17 00:00:00 2001 From: lemuel Date: Sat, 15 Oct 2022 22:24:22 -0500 Subject: [PATCH] operador mejorado antes de meterme con auth --- src/app.module.ts | 4 +- src/auth/strategy/jwt-strategy.service.ts | 2 +- src/equipo-motivo/equipo-motivo.service.ts | 2 +- src/multa/multa.service.ts | 2 +- ...w.ts => full-informacion-operador.view.ts} | 16 ++- src/operador/operador.controller.ts | 5 - src/operador/operador.module.ts | 4 +- src/operador/operador.service.ts | 115 +++++++++--------- src/prestamo/prestamo.service.ts | 4 +- 9 files changed, 79 insertions(+), 75 deletions(-) rename src/operador/entity/views/{informacion-operador.view.ts => full-informacion-operador.view.ts} (70%) diff --git a/src/app.module.ts b/src/app.module.ts index b163bf9..2d8cd28 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -84,7 +84,7 @@ import { InformacionModuloView } from './modulo/entity/views/informacion-modulo. import { MinInformacionModuloView } from './modulo/entity/views/min-informacion-modulo.view'; import { FullInformacionMultaView } from './multa/entity/views/full-informacion-multa.view'; import { InformacionMultaView } from './multa/entity/views/informacion-multa.view'; -import { InformacionOperadorView } from './operador/entity/views/informacion-operador.view'; +import { FullInformacionOperadorView } from './operador/entity/views/full-informacion-operador.view'; import { FullInformacionPrestamoView } from './prestamo/entity/views/full-informacion-prestamo.view'; import { PrestamoInformacionView } from './prestamo/entity/views/prestamo-informacion.view'; import { InformacionPrestamoView } from './prestamo/entity/views/informacion-prestamo.view'; @@ -161,7 +161,7 @@ import { InformacionUsuarioView } from './usuario/entity/views/informacion-usuar MinInformacionModuloView, FullInformacionMultaView, InformacionMultaView, - InformacionOperadorView, + FullInformacionOperadorView, FullInformacionPrestamoView, PrestamoInformacionView, InformacionPrestamoView, diff --git a/src/auth/strategy/jwt-strategy.service.ts b/src/auth/strategy/jwt-strategy.service.ts index 003e6c9..e167c60 100644 --- a/src/auth/strategy/jwt-strategy.service.ts +++ b/src/auth/strategy/jwt-strategy.service.ts @@ -34,7 +34,7 @@ export class JwtStrategyService extends PassportStrategy(Strategy) { .then((usuario) => (user.usuario = usuario)); else if (payload.id_operador) await this.operadorService - .findById(payload.id_operador) + .findInfoOperadorById(payload.id_operador) .then(async (operador) => { if (!operador.activo) throw new ForbiddenException('Esta cuenta esta desactivada.'); diff --git a/src/equipo-motivo/equipo-motivo.service.ts b/src/equipo-motivo/equipo-motivo.service.ts index 4e68fad..ef4dae5 100644 --- a/src/equipo-motivo/equipo-motivo.service.ts +++ b/src/equipo-motivo/equipo-motivo.service.ts @@ -30,7 +30,7 @@ export class EquipoMotivoService { const ahora = moment(); const operador = typeof id_operador === 'number' - ? await this.operadorService.findById(id_operador) + ? await this.operadorService.findInfoOperadorById(id_operador) : id_operador; const status = typeof id_status === 'number' diff --git a/src/multa/multa.service.ts b/src/multa/multa.service.ts index dfd2ce0..4adb6b2 100644 --- a/src/multa/multa.service.ts +++ b/src/multa/multa.service.ts @@ -46,7 +46,7 @@ export class MultaService { : id_prestamo; const operador = typeof id_operador === 'number' - ? await this.operadorService.findById(id_operador) + ? await this.operadorService.findInfoOperadorById(id_operador) : id_operador; const data: DeepPartial = { descripcion, diff --git a/src/operador/entity/views/informacion-operador.view.ts b/src/operador/entity/views/full-informacion-operador.view.ts similarity index 70% rename from src/operador/entity/views/informacion-operador.view.ts rename to src/operador/entity/views/full-informacion-operador.view.ts index 2f2911d..73286ed 100644 --- a/src/operador/entity/views/informacion-operador.view.ts +++ b/src/operador/entity/views/full-informacion-operador.view.ts @@ -1,7 +1,7 @@ import { DataSource, ViewEntity, ViewColumn } from 'typeorm'; import { Institucion } from '../../../institucion/entity/institucion.entity'; -import { TipoUsuario } from '../../../tipo-usuario/entity/tipo-usuario.entity'; import { Operador } from '../operador.entity'; +import { TipoUsuario } from '../../../tipo-usuario/entity/tipo-usuario.entity'; @ViewEntity({ expression: (dataSource: DataSource) => @@ -14,9 +14,13 @@ import { Operador } from '../operador.entity'; .addSelect('o.nombre', 'nombre') .addSelect('o.operador', 'operador') .addSelect('o.password', 'password') - .from(Operador, 'o'), + .addSelect('i.institucion', 'institucion') + .addSelect('tu.tipo_usuario', 'tipo_usuario') + .from(Operador, 'o') + .innerJoin(Institucion, 'i', 'i.id_institucion = o.id_institucion') + .innerJoin(TipoUsuario, 'tu', 'tu.id_tipo_usuario = o.id_tipo_usuario'), }) -export class InformacionOperadorView { +export class FullInformacionOperadorView { @ViewColumn() id_operador: number; @@ -29,6 +33,9 @@ export class InformacionOperadorView { @ViewColumn() id_tipo_usuario: number; + @ViewColumn() + institucion: string; + @ViewColumn() nombre: string; @@ -37,4 +44,7 @@ export class InformacionOperadorView { @ViewColumn() password: string; + + @ViewColumn() + tipo_usuario: string; } diff --git a/src/operador/operador.controller.ts b/src/operador/operador.controller.ts index ef5d26e..7f01fbb 100644 --- a/src/operador/operador.controller.ts +++ b/src/operador/operador.controller.ts @@ -154,11 +154,6 @@ export class OperadorController { ); } - // @Get('reporte') - // @UseGuards(AuthGuard('jwt')) - // @ApiBearerAuth('jwt') - // reporte() {} - @Put() @UseGuards(AuthGuard('jwt')) @ApiOperation({ diff --git a/src/operador/operador.module.ts b/src/operador/operador.module.ts index 79d445a..a83687f 100644 --- a/src/operador/operador.module.ts +++ b/src/operador/operador.module.ts @@ -4,7 +4,7 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { OperadorController } from './operador.controller'; import { OperadorService } from './operador.service'; import { Operador } from './entity/operador.entity'; -import { InformacionOperadorView } from './entity/views/informacion-operador.view'; +import { FullInformacionOperadorView } from './entity/views/full-informacion-operador.view'; import { BcryptModule } from '../bcrypt/bcrypt.module'; import { InstitucionModule } from '../institucion/institucion.module'; import { NodemailerModule } from '../nodemailer/nodemailer.module'; @@ -18,7 +18,7 @@ import { ValidarUsuarioModule } from '../validar-usuario/validar-usuario.module' NodemailerModule, PassportModule.register({ defaultStrategy: 'jwt' }), TipoUsuarioModule, - TypeOrmModule.forFeature([Operador, InformacionOperadorView]), + TypeOrmModule.forFeature([Operador, FullInformacionOperadorView]), ValidarUsuarioModule, ], controllers: [OperadorController], diff --git a/src/operador/operador.service.ts b/src/operador/operador.service.ts index 1ee1075..340ec32 100644 --- a/src/operador/operador.service.ts +++ b/src/operador/operador.service.ts @@ -7,7 +7,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { Between, Repository } from 'typeorm'; import { Institucion } from '../institucion/entity/institucion.entity'; import { Operador } from './entity/operador.entity'; -import { InformacionOperadorView } from './entity/views/informacion-operador.view'; +import { FullInformacionOperadorView } from './entity/views/full-informacion-operador.view'; import { BcryptService } from '../bcrypt/bcrypt.service'; import { InstitucionService } from '../institucion/institucion.service'; import { NodemailerService } from '../nodemailer/nodemailer.service'; @@ -17,8 +17,8 @@ import { TipoUsuarioService } from '../tipo-usuario/tipo-usuario.service'; export class OperadorService { constructor( @InjectRepository(Operador) private repository: Repository, - @InjectRepository(InformacionOperadorView) - private informacionOperadorView: Repository, + @InjectRepository(FullInformacionOperadorView) + private fullInformacionOperadorView: Repository, private bcryptService: BcryptService, private institucionService: InstitucionService, private nodemailerService: NodemailerService, @@ -39,24 +39,38 @@ export class OperadorService { : id_institucion; const tipoUsuario = await this.tipoUsuarioService.findById(id_tipo_usuario); + // Solo se puede crear admins y operadores if (tipoUsuario.id_tipo_usuario < 3 || tipoUsuario.id_tipo_usuario > 4) throw new ConflictException( 'No se puede asignar un tipo de usuario distinto a admin y operador', ); - return this.findAdmin(operador, false) + // Ver que ningún admin tenga este usuario + return this.repository + .findOne({ + select: ['id_operador'], + where: { + operador, + tipoUsuario: { id_tipo_usuario: Between(2, 3) }, + }, + }) .then((existeAdmin) => { + // Error si lo hay if (existeAdmin) throw new ConflictException( 'Ya existe un admin con ese nombre, intenta de nuevo con otro.', ); - return this.findByOperador(institucion, operador, false); + // Ver que no haya un operador en esta institución con este usuario + return this.repository.findOne({ where: { institucion, operador } }); }) .then(async (existeOperador) => { + // Error si lo hay if (existeOperador) throw new ConflictException( 'Ya existe un operador en esta institución con ese nombre, intenta de nuevo con otro.', ); + // Crear password si no se mandó if (!password) password = this.bcryptService.generarPassword(); + // Crear registro return this.repository.save( this.repository.create({ correo, @@ -69,6 +83,7 @@ export class OperadorService { ); }) .then((operador) => + // Correo con credenciales this.nodemailerService.sendEmail({ email: operador.correo, subject: 'Credenciales Pc Puma', @@ -89,21 +104,6 @@ export class OperadorService { })); } - findAdmin(admin: string, validarNoExiste = true) { - return this.repository - .findOne({ - where: { - operador: admin, - tipoUsuario: { id_tipo_usuario: Between(2, 3) }, - }, - }) - .then((admin) => { - if (validarNoExiste && !admin) - throw new NotFoundException('No existe este admin.'); - return admin; - }); - } - async findAll(filtros: { pagina: string; id_institucion?: string; @@ -146,9 +146,17 @@ export class OperadorService { return query.getManyAndCount(); } - findById(id_operador: number) { + findInfoOperadorById(id_operador: number) { return this.repository - .findOne({ where: { id_operador } }) + .findOne({ + select: { + id_operador: true, + activo: true, + institucion: { id_institucion: true }, + tipoUsuario: { id_tipo_usuario: true }, + }, + where: { id_operador }, + }) .then((operador) => { if (!operador) throw new NotFoundException('No existe este id operador.'); @@ -156,27 +164,8 @@ export class OperadorService { }); } - async findByOperador( - id_institucion: number | Institucion, - operador: string, - validarNoExiste = true, - ) { - const institucion = - typeof id_institucion === 'number' - ? await this.institucionService.findInfoInstitucionById(id_institucion) - : id_institucion; - - return this.repository - .findOne({ where: { institucion, operador } }) - .then((operador) => { - if (validarNoExiste && !operador) - throw new NotFoundException('No existe este operador.'); - return operador; - }); - } - informacionAdmin(admin: string) { - return this.informacionOperadorView + return this.fullInformacionOperadorView .findOne({ where: { operador: admin, @@ -202,7 +191,7 @@ export class OperadorService { } informacionOperador(institucion: Institucion, operador: string) { - return this.informacionOperadorView + return this.fullInformacionOperadorView .findOne({ where: { operador, id_institucion: institucion.id_institucion }, }) @@ -232,14 +221,18 @@ export class OperadorService { } passwordReset(admin: Operador, id_operador: number, password?: string) { - return this.findById(id_operador) + return this.findInfoOperadorById(id_operador) .then((operador) => { this.validarUpdate(admin, operador); + // Si no se manda una password se genera una if (!password) password = this.bcryptService.generarPassword(); + // Encriptación operador.password = this.bcryptService.encriptar(password); + // Guardar return this.repository.save(operador); }) .then((operador) => + // Reenviar correo this.nodemailerService.sendEmail({ email: operador.correo, subject: 'Credenciales PC Puma', @@ -255,24 +248,23 @@ export class OperadorService { ), }), ) - .then((_) => ({ - message: 'Se cambió correctamente la constraseña.', - })); + .then((_) => ({ message: 'Se cambió correctamente la constraseña.' })); } update(admin: Operador, attrs: Partial) { - return this.findById(attrs.id_operador) + return this.findInfoOperadorById(attrs.id_operador) .then((operador) => { this.validarUpdate(admin, operador); + // Paso los valores enviados del front a mi objeto Object.assign(operador, attrs); + // Guardar return this.repository.save(operador); }) - .then((_) => ({ - message: 'Se guardaron los cambios correctamente.', - })); + .then((_) => ({ message: 'Se guardaron los cambios correctamente.' })); } validarUpdate(admin: Operador, operador: Operador) { + // Valido que el super admin solo puedar modificar admins if ( admin.tipoUsuario.id_tipo_usuario === 2 && operador.tipoUsuario.id_tipo_usuario != 3 @@ -280,12 +272,19 @@ export class OperadorService { throw new ConflictException( `El super admin solo puede modificar la infomración de los admins.`, ); - if ( - admin.tipoUsuario.id_tipo_usuario === 3 && - admin.institucion.id_institucion != operador.institucion.id_institucion - ) - throw new ConflictException( - `No puedes actualizar la información de este ${operador.tipoUsuario.tipo_usuario.toLowerCase()} porque no pertenece a tu institución.`, - ); + if (admin.tipoUsuario.id_tipo_usuario === 3) { + // Valido admin no pueda modificar admins + if (operador.tipoUsuario.id_tipo_usuario === 3) + throw new ConflictException( + `No puedes actualizar la información de otro admin.`, + ); + // Valido que admin solo pueda modificar operadores de su institución + if ( + admin.institucion.id_institucion != operador.institucion.id_institucion + ) + throw new ConflictException( + `No puedes actualizar la información de este operador porque no pertenece a tu institución.`, + ); + } } } diff --git a/src/prestamo/prestamo.service.ts b/src/prestamo/prestamo.service.ts index 323c499..dbbd85b 100644 --- a/src/prestamo/prestamo.service.ts +++ b/src/prestamo/prestamo.service.ts @@ -450,12 +450,12 @@ export class PrestamoService { ? await this.moduloService.findInfoModuloById(parseInt(filtros.id_modulo)) : null; const operadorEntrega = filtros.id_operador_entrega - ? await this.operadorService.findById( + ? await this.operadorService.findInfoOperadorById( parseInt(filtros.id_operador_entrega), ) : null; const operadorRegreso = filtros.id_operador_regreso - ? await this.operadorService.findById( + ? await this.operadorService.findInfoOperadorById( parseInt(filtros.id_operador_regreso), ) : null;