diff --git a/src/auth/auth.controller.ts b/src/auth/auth.controller.ts index dfdfe29..c61a09d 100644 --- a/src/auth/auth.controller.ts +++ b/src/auth/auth.controller.ts @@ -77,10 +77,8 @@ export class AuthController { @Get('validar-token') @UseGuards(AuthGuard('jwt')) - @ApiOperation({ - description: 'Endpoint utilizado para validar un token.', - }) + @ApiOperation({ description: 'Endpoint utilizado para validar un token.' }) validarToken() { - return true; + return { valido: true }; } } diff --git a/src/auth/auth.service.ts b/src/auth/auth.service.ts index 14e2a45..820a524 100644 --- a/src/auth/auth.service.ts +++ b/src/auth/auth.service.ts @@ -4,10 +4,14 @@ import { UnauthorizedException, } from '@nestjs/common'; import { JwtService } from '@nestjs/jwt'; +import { Operador } from '../operador/entity/operador.entity'; import { BcryptService } from '../bcrypt/bcrypt.service'; import { ModuloService } from '../modulo/modulo.service'; import { OperadorService } from '../operador/operador.service'; import { UsuarioService } from '../usuario/usuario.service'; +import { JwtPayloadAdmin } from './dto/jwt-payload-admin'; +import { JwtPayloadOperador } from './dto/jwt-payload-operador'; +import { JwtPayloadUsuario } from './dto/jwt-payload-usuario'; @Injectable() export class AuthService { @@ -20,19 +24,23 @@ export class AuthService { ) {} loginAdmin(admin: string, password: string) { - return this.operadorService.informacionAdmin(admin).then((data) => { - if ( - !data.operador || - !this.bcryptService.comparar(password, data.password) - ) - throw new BadRequestException( - 'Usuario y/o password incorrectos, ingresa unas credenciales válidas.', - ); - if (!data.activo) - throw new UnauthorizedException( - 'Esta cuenta se encuentra desactivada.', - ); - return { token: this.jwtService.sign(data.operador) }; + return this.operadorService.findInfoOperadorAdmin(admin).then((admin) => { + this.validacionBasica(admin, password); + + const JwtPayload: JwtPayloadAdmin = { + Operador: { + id_operador: admin.id_operador, + operador: admin.operador, + nombre: admin.nombre, + institucion: { + id_institucion: admin.institucion.id_institucion, + }, + tipoUsuario: { + id_tipo_usuario: admin.tipoUsuario.id_tipo_usuario, + }, + }, + }; + return { token: this.jwtService.sign(JwtPayload) }; }); } @@ -40,22 +48,27 @@ export class AuthService { const modulo = await this.moduloService.findInfoModuloById(id_modulo); return this.operadorService - .informacionOperador(modulo.institucion, operador) - .then((data) => { - if ( - !data.operador || - !this.bcryptService.comparar(password, data.password) - ) - throw new BadRequestException( - 'Usuario y/o password incorrectos, ingresa unas credenciales válidas.', - ); - if (!data.activo) - throw new UnauthorizedException( - 'Esta cuenta se encuentra desactivada.', - ); - if (data.operador.tipoUsuario.id_tipo_usuario === 4) - data.operador.id_modulo = modulo.id_modulo; - return { token: this.jwtService.sign(data.operador) }; + .findInfoOperador(modulo.institucion, operador) + .then((operador) => { + this.validacionBasica(operador, password); + + const JwtPayload: JwtPayloadOperador = { + Operador: { + id_operador: operador.id_operador, + operador: operador.operador, + nombre: operador.nombre, + institucion: { + id_institucion: operador.institucion.id_institucion, + }, + tipoUsuario: { + id_tipo_usuario: operador.tipoUsuario.id_tipo_usuario, + }, + }, + }; + + if (operador.tipoUsuario.id_tipo_usuario === 4) + JwtPayload.Modulo.id_modulo = modulo.id_modulo; + return { token: this.jwtService.sign(JwtPayload) }; }); } @@ -75,4 +88,13 @@ export class AuthService { return { token: this.jwtService.sign(data.usuario) }; }); } + + private validacionBasica(operador: Operador, password: string) { + if (!operador || !this.bcryptService.comparar(password, operador.password)) + throw new BadRequestException( + 'Usuario y/o password incorrectos, ingresa unas credenciales válidas.', + ); + if (!operador.activo) + throw new UnauthorizedException('Esta cuenta se encuentra desactivada.'); + } } diff --git a/src/auth/dto/jwt-payload-admin.ts b/src/auth/dto/jwt-payload-admin.ts index 8551935..5b34367 100644 --- a/src/auth/dto/jwt-payload-admin.ts +++ b/src/auth/dto/jwt-payload-admin.ts @@ -1,11 +1,9 @@ -export class JwtPayload { - nombre: string; - - id_operador: number; - - institucion: { id_institucion: number }; - - operador: string; - - tipoUsuario: { id_tipo_usuario: number }; +export interface JwtPayloadAdmin { + Operador: { + id_operador: number; + nombre: string; + operador: string; + institucion: { id_institucion: number }; + tipoUsuario: { id_tipo_usuario: number }; + }; } diff --git a/src/auth/dto/jwt-payload-operador.ts b/src/auth/dto/jwt-payload-operador.ts index 3c42a95..52b20c3 100644 --- a/src/auth/dto/jwt-payload-operador.ts +++ b/src/auth/dto/jwt-payload-operador.ts @@ -1,13 +1,10 @@ -export class JwtPayload { - nombre: string; - - id_modulo: number; - - id_operador: number; - - institucion: { id_institucion: number }; - - operador: string; - - tipoUsuario: { id_tipo_usuario: number }; +export interface JwtPayloadOperador { + Operador: { + id_operador: number; + nombre: string; + operador: string; + institucion: { id_institucion: number }; + tipoUsuario: { id_tipo_usuario: number }; + }; + Modulo?: { id_modulo: number }; } diff --git a/src/auth/dto/jwt-payload-usuario.ts b/src/auth/dto/jwt-payload-usuario.ts index 0a6ecbf..ea8db70 100644 --- a/src/auth/dto/jwt-payload-usuario.ts +++ b/src/auth/dto/jwt-payload-usuario.ts @@ -1,18 +1,8 @@ -export class JwtPayload { - nombre: string; - - id_usuario: number; - - instituciones: { - id_institucion_usuario: number; - institucionCarrera: { - id_institucion_carrera: number; - institucion: { id_institucion: number }; - carrera: { id_carrera: number }; - }; - }[]; - - tipoUsuario: { id_tipo_usuario: number }; - - usuario: string; +export interface JwtPayloadUsuario { + Usuario: { + id_usuario: number; + nombre: string; + usuario: string; + tipoUsuario: { id_tipo_usuario: number }; + }; } diff --git a/src/auth/dto/jwt-payload.ts b/src/auth/dto/jwt-payload.ts deleted file mode 100644 index fcc9a7b..0000000 --- a/src/auth/dto/jwt-payload.ts +++ /dev/null @@ -1,26 +0,0 @@ -export class JwtPayload { - nombre: string; - - tipoUsuario: { id_tipo_usuario: number }; - - id_modulo?: number; - - id_operador?: number; - - id_usuario?: number; - - operador?: string; - - usuario?: string; - - institucion?: { id_institucion: number }; - - instituciones?: { - id_institucion_usuario: number; - institucionCarrera: { - id_institucion_carrera: number; - institucion: { id_institucion: number }; - carrera: { id_carrera: number }; - }; - }[]; -} diff --git a/src/auth/strategy/jwt-strategy.service.ts b/src/auth/strategy/jwt-strategy.service.ts index e167c60..ea04239 100644 --- a/src/auth/strategy/jwt-strategy.service.ts +++ b/src/auth/strategy/jwt-strategy.service.ts @@ -8,7 +8,9 @@ import { UsuarioService } from '../../usuario/usuario.service'; import { Modulo } from '../../modulo/entity/modulo.entity'; import { Operador } from '../../operador/entity/operador.entity'; import { Usuario } from '../../usuario/entity/usuario.entity'; -import { JwtPayload } from '../dto/jwt-payload'; +import { JwtPayloadAdmin } from '../dto/jwt-payload-admin'; +import { JwtPayloadOperador } from '../dto/jwt-payload-operador'; +import { JwtPayloadUsuario } from '../dto/jwt-payload-usuario'; @Injectable() export class JwtStrategyService extends PassportStrategy(Strategy) { @@ -24,32 +26,32 @@ export class JwtStrategyService extends PassportStrategy(Strategy) { }); } - async validate(payload: JwtPayload) { + async validate( + payload: JwtPayloadAdmin | JwtPayloadOperador | JwtPayloadUsuario, + ) { const user: { modulo?: Modulo; usuario?: Usuario; operador?: Operador } = {}; - if (payload.id_usuario) + if ('Usuario' in payload) await this.usuarioService - .findById(payload.id_usuario, true, true) + .findById(payload.Usuario.id_usuario, true, true) .then((usuario) => (user.usuario = usuario)); - else if (payload.id_operador) + else if ('Operador' in payload) await this.operadorService - .findInfoOperadorById(payload.id_operador) + .findInfoOperadorById(payload.Operador.id_operador) .then(async (operador) => { if (!operador.activo) throw new ForbiddenException('Esta cuenta esta desactivada.'); - /* if (operador.tipoUsuario.id_tipo_usuario === 4) { - if (payload.id_modulo) + if ('Modulo' in payload) await this.moduloService - .findById(payload.id_modulo) + .findInfoModuloById(payload.Modulo.id_modulo) .then((modulo) => (user.modulo = modulo)); else throw new ForbiddenException( 'Credenciales no válidas, inicia sesión de nuevo.', ); } - */ user.operador = operador; }); return user; diff --git a/src/operador/entity/operador.entity.ts b/src/operador/entity/operador.entity.ts index a424fb3..4419c05 100644 --- a/src/operador/entity/operador.entity.ts +++ b/src/operador/entity/operador.entity.ts @@ -32,15 +32,11 @@ export class Operador { @Column({ type: String, nullable: false, length: 60 }) password: string; - @ManyToOne(() => Institucion, (institucion) => institucion.operadores, { - eager: true, - }) + @ManyToOne(() => Institucion, (institucion) => institucion.operadores) @JoinColumn({ name: 'id_institucion' }) institucion: Institucion; - @ManyToOne(() => TipoUsuario, (tipoUsuario) => tipoUsuario.operadores, { - eager: true, - }) + @ManyToOne(() => TipoUsuario, (tipoUsuario) => tipoUsuario.operadores) @JoinColumn({ name: 'id_tipo_usuario' }) tipoUsuario: TipoUsuario; diff --git a/src/operador/entity/views/full-informacion-operador.view.ts b/src/operador/entity/views/full-informacion-operador.view.ts index 73286ed..79a982c 100644 --- a/src/operador/entity/views/full-informacion-operador.view.ts +++ b/src/operador/entity/views/full-informacion-operador.view.ts @@ -18,7 +18,10 @@ import { TipoUsuario } from '../../../tipo-usuario/entity/tipo-usuario.entity'; .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'), + .innerJoin(TipoUsuario, 'tu', 'tu.id_tipo_usuario = o.id_tipo_usuario') + .orderBy('institucion') + .addOrderBy('tipo_usuario') + .addOrderBy('operador'), }) export class FullInformacionOperadorView { @ViewColumn() diff --git a/src/operador/operador.controller.ts b/src/operador/operador.controller.ts index 7f01fbb..d27723b 100644 --- a/src/operador/operador.controller.ts +++ b/src/operador/operador.controller.ts @@ -130,7 +130,22 @@ export class OperadorController { const admin: Operador = req.user.operador; this.validarUsuarioService.validarSuperAdminAdmin(admin); - return this.operadorService.findAll(query); + return this.operadorService.findFullInfoOperadorAll(query); + } + + @Serealize(OperadorOutputDto) + @Get('catalogo') + @UseGuards(AuthGuard('jwt')) + @ApiOperation({ + description: + 'Endpoint que retorna todo el catálogo de operadores de una institucion.', + }) + @ApiBearerAuth('jwt') + catalogo(@Request() req) { + const admin: Operador = req.user.operador; + + this.validarUsuarioService.validarSuperAdminAdmin(admin); + return this.operadorService.findAllByInstitucion(admin); } @Put('update-password') diff --git a/src/operador/operador.service.ts b/src/operador/operador.service.ts index 340ec32..1347ac4 100644 --- a/src/operador/operador.service.ts +++ b/src/operador/operador.service.ts @@ -4,7 +4,7 @@ import { NotFoundException, } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { Between, Repository } from 'typeorm'; +import { Between, FindOptionsWhere, Like, Not, Repository } from 'typeorm'; import { Institucion } from '../institucion/entity/institucion.entity'; import { Operador } from './entity/operador.entity'; import { FullInformacionOperadorView } from './entity/views/full-informacion-operador.view'; @@ -44,23 +44,16 @@ export class OperadorService { throw new ConflictException( 'No se puede asignar un tipo de usuario distinto a admin y operador', ); - // Ver que ningún admin tenga este usuario - return this.repository - .findOne({ - select: ['id_operador'], - where: { - operador, - tipoUsuario: { id_tipo_usuario: Between(2, 3) }, - }, - }) + // Ver si existe un admin con ese usaurio + return this.findInfoOperadorAdmin(operador) .then((existeAdmin) => { // Error si lo hay if (existeAdmin) throw new ConflictException( 'Ya existe un admin con ese nombre, intenta de nuevo con otro.', ); - // Ver que no haya un operador en esta institución con este usuario - return this.repository.findOne({ where: { institucion, operador } }); + // Ver que haya un operador en esta institución con este usuario + return this.findInfoOperador(institucion, operador); }) .then(async (existeOperador) => { // Error si lo hay @@ -104,7 +97,14 @@ export class OperadorService { })); } - async findAll(filtros: { + findAllByInstitucion(operador: Operador) { + return this.repository.find({ + select: ['id_operador', 'operador'], + where: { institucion: operador.institucion }, + }); + } + + async findFullInfoOperadorAll(filtros: { pagina: string; id_institucion?: string; id_tipo_usuario?: string; @@ -120,30 +120,74 @@ export class OperadorService { parseInt(filtros.id_tipo_usuario), ) : null; - const query = this.repository - .createQueryBuilder('o') - .innerJoinAndSelect('o.institucion', 'i') - .innerJoinAndSelect('o.tipoUsuario', 'tu') - .where('id_operador != 1 AND id_operador != 2') - .orderBy('i.institucion') - .addOrderBy('tu.tipo_usuario') - .addOrderBy('o.operador') - .take(25) - .skip((parseInt(filtros.pagina) - 1) * 25); + const busqueda: FindOptionsWhere = {}; - if (filtros.operador) - query.andWhere('operador LIKE :operador', { - operador: `${filtros.operador}%`, + if (filtros.operador) busqueda.operador = Like(`${filtros.operador}%`); + if (institucion) busqueda.id_institucion = institucion.id_institucion; + if (tipoUsuario) busqueda.id_tipo_usuario = tipoUsuario.id_tipo_usuario; + return this.fullInformacionOperadorView + .findAndCount({ + where: [ + busqueda, + { id_tipo_usuario: Not(1) }, + { id_tipo_usuario: Not(2) }, + ], + take: 25, + skip: (parseInt(filtros.pagina) - 1) * 25, + }) + .then((infoOperadores) => { + const operadores: Operador[] = []; + + for (let i = 0; i < infoOperadores[0].length; i++) + operadores.push( + this.repository.create({ + id_operador: infoOperadores[0][i].id_operador, + activo: infoOperadores[0][i].activo, + nombre: infoOperadores[0][i].nombre, + operador: infoOperadores[0][i].operador, + institucion: { + id_institucion: infoOperadores[0][i].id_operador, + institucion: infoOperadores[0][i].institucion, + }, + tipoUsuario: { + id_tipo_usuario: infoOperadores[0][i].id_tipo_usuario, + tipo_usuario: infoOperadores[0][i].tipo_usuario, + }, + }), + ); + return [operadores]; }); - if (institucion) - query.andWhere('i.id_institucion = :id_institucion', { - id_institucion: institucion.id_institucion, - }); - if (tipoUsuario) - query.andWhere('tu.id_tipo_usuario = :id_tipo_usuario', { - id_tipo_usuario: tipoUsuario.id_tipo_usuario, - }); - return query.getManyAndCount(); + } + + findInfoOperador(institucion: Institucion, operador: string) { + return this.repository.findOne({ + select: { + id_operador: true, + activo: true, + nombre: true, + password: true, + institucion: { id_institucion: true }, + tipoUsuario: { id_tipo_usuario: true }, + }, + where: { operador, institucion }, + }); + } + + findInfoOperadorAdmin(admin: string) { + return this.repository.findOne({ + select: { + id_operador: true, + activo: true, + nombre: true, + password: true, + institucion: { id_institucion: true }, + tipoUsuario: { id_tipo_usuario: true }, + }, + where: { + operador: admin, + tipoUsuario: { id_tipo_usuario: Between(2, 3) }, + }, + }); } findInfoOperadorById(id_operador: number) { @@ -164,62 +208,6 @@ export class OperadorService { }); } - informacionAdmin(admin: string) { - return this.fullInformacionOperadorView - .findOne({ - where: { - operador: admin, - id_tipo_usuario: Between(2, 3), - }, - }) - .then((admin) => { - if (!admin) return { operador: null, activo: null, password: null }; - return { - operador: { - id_operador: admin.id_operador, - nombre: admin.nombre, - operador: admin.operador, - institucion: admin.id_institucion - ? { id_institucion: admin.id_institucion } - : null, - tipoUsuario: { id_tipo_usuario: admin.id_tipo_usuario }, - }, - activo: admin.activo, - password: admin.password, - }; - }); - } - - informacionOperador(institucion: Institucion, operador: string) { - return this.fullInformacionOperadorView - .findOne({ - where: { operador, id_institucion: institucion.id_institucion }, - }) - .then((operador) => { - if (!operador) return { operador: null, activo: null, password: null }; - - const o: { - id_operador: number; - nombre: string; - operador: string; - institucion: { id_institucion: number }; - tipoUsuario: { id_tipo_usuario: number }; - id_modulo?: number; - } = { - id_operador: operador.id_operador, - nombre: operador.nombre, - operador: operador.operador, - institucion: { id_institucion: operador.id_institucion }, - tipoUsuario: { id_tipo_usuario: operador.id_tipo_usuario }, - }; - return { - operador: o, - activo: operador.activo, - password: operador.password, - }; - }); - } - passwordReset(admin: Operador, id_operador: number, password?: string) { return this.findInfoOperadorById(id_operador) .then((operador) => {