utn-cli 2.0.83 → 2.0.84

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "utn-cli",
3
- "version": "2.0.83",
3
+ "version": "2.0.84",
4
4
  "description": "Herramienta CLI unificada para la gestión de plantillas en SIGU.",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -38,6 +38,14 @@ Router.get('/UsuariosActuales', async (solicitud, respuesta, next) => {
38
38
  }
39
39
  });
40
40
 
41
+ Router.get('/obtenerGoogleClientId', async (solicitud, respuesta, next) => {
42
+ try {
43
+ return respuesta.json({ body: await Miscelaneo.googleClientId(), error: undefined });
44
+ } catch (error) {
45
+ next(error);
46
+ }
47
+ });
48
+
41
49
  Router.post('/Verificar2FA', async (solicitud, respuesta, next) => {
42
50
  try {
43
51
  return respuesta.json({ body: await Miscelaneo.Verificar2FA(solicitud), error: undefined });
@@ -119,6 +127,14 @@ Router.get('/validarTokenV2', async (solicitud, respuesta, next) => {
119
127
  return respuesta.json({ body: await Miscelaneo.validarTokenV2(solicitud.headers.authorization), error: undefined });
120
128
  });
121
129
 
130
+ Router.post('/AutenticarConGoogle', async (solicitud, respuesta, next) => {
131
+ try {
132
+ return respuesta.json({ body: await Miscelaneo.AutenticarConGoogle(solicitud), error: undefined });
133
+ } catch (error) {
134
+ next(error);
135
+ }
136
+ });
137
+
122
138
  Router.post('/Autenticar', async (solicitud, respuesta, next) => {
123
139
  try {
124
140
  return respuesta.json({ body: await Miscelaneo.Autenticar(solicitud), error: undefined });
@@ -751,6 +751,68 @@ class Miscelaneo {
751
751
  return;
752
752
  }
753
753
 
754
+ async AutenticarConGoogle(Solicitud) {
755
+ const { OAuth2Client } = require('google-auth-library');
756
+ const jwt = require('jsonwebtoken');
757
+ const clientId = await this.googleClientId();
758
+ const client = new OAuth2Client(clientId);
759
+ const ConexionSigu = await crearObjetoConexionSIGU();
760
+ const LastUser = await this.generarLastUser(Solicitud);
761
+
762
+ try {
763
+ const ticket = await client.verifyIdToken({
764
+ idToken: Solicitud.body.token,
765
+ audience: clientId,
766
+ });
767
+ const payload = ticket.getPayload();
768
+ const email = payload['email'];
769
+
770
+ const resultadosEmail = await ConexionSigu.query("SELECT `Identificador` FROM `SIGU`.`SIGU_CorreosPersona` WHERE `CorreoElectronico` = ? AND `Principal` = TRUE LIMIT 1", [email]);
771
+
772
+ if (resultadosEmail[0].length === 0) {
773
+ console.log("El correo de Google", email, "no está registrado como principal en SIGU");
774
+ return { error: "Su cuenta de Google no está vinculada a ningún usuario de SIGU." };
775
+ }
776
+
777
+ const Identificador = resultadosEmail[0][0]['Identificador'];
778
+ const resultadosUsuario = await ConexionSigu.query("SELECT `Identificacion` FROM `SIGU`.`SIGU_Personas` WHERE `Identificador` = ? AND `Activo` = TRUE", [Identificador]);
779
+
780
+ if (resultadosUsuario[0].length === 0) {
781
+ return { error: "El usuario asociado a esta cuenta no está activo." };
782
+ }
783
+
784
+ const Identificacion = resultadosUsuario[0][0]['Identificacion'];
785
+
786
+ // Generar Token
787
+ const Token = await jwt.sign({ Identificador: Identificador, uid: Identificador }, await this.palabraSecretaParaTokens(), { expiresIn: '2h' });
788
+ await ConexionSigu.query("INSERT INTO `SIGU`.`SIGU_Sesiones` VALUES (?, ?, ?, NOW(4), ?) ON DUPLICATE KEY UPDATE `Token` = ?, `LastUser` = ?", [Identificador, Solicitud.headers.host.trim(), Token, LastUser, Token, LastUser]);
789
+ await ConexionSigu.query("DELETE FROM `SIGU`.`SIGU_SesionesFallidas` WHERE `Identificador` = ?", [Identificador]);
790
+
791
+ // OBTENER IP DEL USUARIO
792
+ const ipUsuario = (Solicitud.headers['x-forwarded-for'] || '').split(',').shift() || Solicitud.socket?.remoteAddress || Solicitud.connection?.remoteAddress || '-';
793
+
794
+ // SI LA IP YA EXISTE CONTINUA
795
+ await ConexionSigu.query("\
796
+ INSERT INTO `SIGU`.`SIGU_DireccionesUsadasPorLosUsuarios` \
797
+ (`DireccionUsadaPorElUsuario`, `Identificador`, `LastUpdate`, `LastUser`) \
798
+ VALUES (?, ?, NOW(4), ?) \
799
+ ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4), `LastUser` = ?;", [
800
+ ipUsuario,
801
+ Identificador,
802
+ LastUser,
803
+ LastUser
804
+ ]);
805
+
806
+ return { Token, Dominio: ((process.env.ENV || 'local') === 'production' ? '.sigu.utn.ac.cr' : '.181.193.85.44.nip.io') };
807
+
808
+ } catch (error) {
809
+ console.error("Error en AutenticarConGoogle:", error);
810
+ return { error: "Error al autenticar con Google" };
811
+ } finally {
812
+ if (ConexionSigu) await ConexionSigu.end();
813
+ }
814
+ }
815
+
754
816
  async Autenticar(Solicitud) {
755
817
  const crypto = require('crypto');
756
818
  const bcrypt = require('bcryptjs');
@@ -986,7 +1048,7 @@ class Miscelaneo {
986
1048
  `a`.`Tipo`, IF(`a`.`Icono` <> '', CONCAT('https://storage.sigu.utn.ac.cr/images/cards/', `a`.`Icono`), '') AS `Icono`, `a`.`Color`, `a`.`Correo`,\
987
1049
  `a`.`Version`, `a`.`FechaDePublicacion`, `a`.`AcuerdoDeNivelDeServicio`, `a`.`DiccionarioDeDatos`, `a`.`Repositorios`,\
988
1050
  `a`.`EnlaceDelVideo`,`a`.`EnlaceDelManual`\
989
- , `a`.`Estado`, REGEXP_SUBSTR(`a`.`Repositorios`, '[^,]*front[^,]*') AS `Frontend`\
1051
+ , `a`.`Estado`, REGEXP_SUBSTR(SUBSTRING_INDEX(`a`.`Repositorios`, '/', -1), '[^,]*front[^,]*') AS `Frontend`\
990
1052
  FROM `SIGU`.`SIGU_ModulosV2` `a`\
991
1053
  WHERE `a`.`Nombre` = ?", [this.NombreCanonicoDelModulo]);
992
1054
  return Modulos.map((linea) => {
@@ -1547,7 +1609,7 @@ class Miscelaneo {
1547
1609
  console.log(error);
1548
1610
  return;
1549
1611
  }
1550
- return ejecutarConsultaSIGU("SELECT `a`.`Identificador`, `a`.`Identificacion`\
1612
+ return await ejecutarConsultaSIGU("SELECT `a`.`Identificador`, `a`.`Identificacion`\
1551
1613
  , `a`.`Nombre`, `a`.`PrimerApellido`, `a`.`SegundoApellido`\
1552
1614
  , (SELECT GROUP_CONCAT(`b`.`CuentaIBAN`) FROM `SIGU`.`SIGU_CuentasBancariasPersonas` `b` WHERE `b`.`Estado` = TRUE AND `a`.`Identificador` = `b`.`Identificador`) AS `CuentasIBAN`\
1553
1615
  FROM `SIGU`.`SIGU_Personas` `a` WHERE `a`.`Identificador` = ?"
@@ -1568,28 +1630,33 @@ class Miscelaneo {
1568
1630
  (SELECT `Identificador` FROM `SIGU`.`SIGU_RolesPersonas` WHERE `PerfilGeneralId` = 1 /*El perfil 1 parece ser para Estudiantes*/)");
1569
1631
  }
1570
1632
 
1571
- obtenerBeneficios() {
1572
- return ejecutarConsultaSIGU("SELECT `BeneficioId`, `Beneficio`, `Estado` FROM `SIGU`.`SIGU_Beneficios`");
1633
+ async obtenerBeneficios() {
1634
+ return await ejecutarConsultaSIGU("SELECT `BeneficioId`, `Beneficio`, `Estado` FROM `SIGU`.`SIGU_Beneficios`");
1635
+ }
1636
+
1637
+ async obtenerIdentificacion(Identificador) {
1638
+ return await ejecutarConsultaSIGU("SELECT `Identificacion` FROM `SIGU`.`SIGU_Personas` WHERE `Identificador` = ?", [Identificador]);
1573
1639
  }
1574
1640
 
1575
- obtenerIdentificacion(Identificador) {
1576
- return ejecutarConsultaSIGU("SELECT `Identificacion` FROM `SIGU`.`SIGU_Personas` WHERE `Identificador` = ?", [Identificador]);
1641
+ async obtenerPeriodos() {
1642
+ return await ejecutarConsultaSIGU("SELECT `PeriodoId`, `CodigoPeriodo`, `Anio`, `Periodo`, `FechaInicio`, `FechaFinal`, `Tipo`, `Estado` FROM `SIGU`.`SIGU_Periodos` ORDER BY `Anio` DESC, `CodigoPeriodo` DESC");
1577
1643
  }
1578
1644
 
1579
- obtenerPeriodos() {
1580
- return ejecutarConsultaSIGU("SELECT `PeriodoId`, `CodigoPeriodo`, `Anio`, `Periodo`, `FechaInicio`, `FechaFinal`, `Tipo`, `Estado` FROM `SIGU`.`SIGU_Periodos` ORDER BY `Anio` DESC, `CodigoPeriodo` DESC");
1645
+ async obtenerAnios() {
1646
+ return await ejecutarConsultaSIGU("SELECT DISTINCT `Anio` FROM `SIGU`.`SIGU_Periodos`");
1581
1647
  }
1582
1648
 
1583
- obtenerAnios() {
1584
- return ejecutarConsultaSIGU("SELECT DISTINCT `Anio` FROM `SIGU`.`SIGU_Periodos`");
1649
+ async obtenerSedes() {
1650
+ return await ejecutarConsultaSIGU("SELECT `SedesId`, `CodigoAvatar`, `Descripcion`, `Siglas` FROM `SIGU`.`SIGU_Sedes` ORDER BY `Descripcion`");
1585
1651
  }
1586
1652
 
1587
- obtenerSedes() {
1588
- return ejecutarConsultaSIGU("SELECT `SedesId`, `CodigoAvatar`, `Descripcion`, `Siglas` FROM `SIGU`.`SIGU_Sedes` ORDER BY `Descripcion`");
1653
+ async obtenerRecintos() {
1654
+ return await ejecutarConsultaSIGU("SELECT `a`.`RecintoId`, CONCAT(`b`.`Descripcion`, '/', `a`.`Recinto`) AS `Recinto` FROM `SIGU`.`SIGU_Recintos` `a` LEFT JOIN `SIGU`.`SIGU_Sedes` `b` ON (`a`.`SedeId` = `b`.`SedesId`) ORDER BY `Recinto`");
1589
1655
  }
1590
1656
 
1591
- obtenerRecintos() {
1592
- return ejecutarConsultaSIGU("SELECT `a`.`RecintoId`, CONCAT(`b`.`Descripcion`, '/', `a`.`Recinto`) AS `Recinto` FROM `SIGU`.`SIGU_Recintos` `a` LEFT JOIN `SIGU`.`SIGU_Sedes` `b` ON (`a`.`SedeId` = `b`.`SedesId`) ORDER BY `Recinto`");
1657
+ async googleClientId() {
1658
+ const clientId = await ejecutarConsultaSIGU("SELECT `Valor` FROM `SIGU`.`SIGU_VariablesDeSistema` WHERE `Nombre` = 'Google-ClientId'");
1659
+ return clientId[0]?.['Valor'] || '';
1593
1660
  }
1594
1661
 
1595
1662
  async palabraSecretaParaTokens() {
@@ -2535,3 +2602,4 @@ class Miscelaneo {
2535
2602
  }
2536
2603
 
2537
2604
  module.exports = new Miscelaneo();
2605
+ eo();