utn-cli 2.0.82 → 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/commands/backend.js
CHANGED
|
@@ -92,7 +92,7 @@ async function inicializarProyectoBackend() {
|
|
|
92
92
|
|
|
93
93
|
await askAndReplace('CEDULA_DEL_DESARROLLADOR', '¿Cuál es el número de cédula del desarrollador?: ', rutaDeInformacionDelModulo, 'CEDULA_DEL_DESARROLLADOR');
|
|
94
94
|
|
|
95
|
-
const url_del_grupo = await askAndReplace('url_del_grupo', '¿Cuál es la URL del grupo en el Git?: ',
|
|
95
|
+
const url_del_grupo = await askAndReplace('url_del_grupo', '¿Cuál es la URL del grupo en el Git?: ', rutaDeInformacionDelModulo, 'url_del_grupo', (val) => {
|
|
96
96
|
reemplazarContenidoEnArchivo(path.join(process.cwd(), 'package.json'), 'url_del_grupo', val);
|
|
97
97
|
});
|
|
98
98
|
|
package/package.json
CHANGED
|
@@ -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 });
|
|
@@ -54,7 +54,7 @@ class InformacionDelModulo {
|
|
|
54
54
|
getUsuariosConAccesoInicial() {
|
|
55
55
|
// UsuariosConAccesoInicial es un arreglo de strings de la forma ['111050570', '111050570']
|
|
56
56
|
// Este arreglo se usa para asignar acceso a este módulo, suelen usarse las cédulas de los encargados del proyecto y el desarrollador
|
|
57
|
-
return ['111050570', '204540859', '602990078', '109840817', '206860639', '
|
|
57
|
+
return ['111050570', '204540859', '602990078', '109840817', '206860639', '801680123', 'CEDULA_DEL_DESARROLLADOR'];
|
|
58
58
|
};
|
|
59
59
|
getColorDelModulo() {
|
|
60
60
|
return 'COLOR_DEL_MODULO';
|
|
@@ -65,6 +65,9 @@ class InformacionDelModulo {
|
|
|
65
65
|
getVersion() {
|
|
66
66
|
return 'VERSION';
|
|
67
67
|
};
|
|
68
|
+
getUrlDelGrupo() {
|
|
69
|
+
return 'url_del_grupo';
|
|
70
|
+
};
|
|
68
71
|
}
|
|
69
72
|
|
|
70
73
|
module.exports = new InformacionDelModulo();
|
|
@@ -15,8 +15,9 @@ class Miscelaneo {
|
|
|
15
15
|
this.NombreDelRepositorioDeLaBaseDeDatos = InformacionDelModulo.getNombreDelRepositorioDeLaBaseDeDatos();
|
|
16
16
|
this.NombreDelRepositorioDelBackend = InformacionDelModulo.getNombreDelRepositorioDelBackend();
|
|
17
17
|
this.NombreDelRepositorioDelFrontend = InformacionDelModulo.getNombreDelRepositorioDelFrontend();
|
|
18
|
-
this.
|
|
19
|
-
|
|
18
|
+
this.UrlDelGrupo = InformacionDelModulo.getUrlDelGrupo();
|
|
19
|
+
this.Repositorios = this.UrlDelGrupo + '/' + this.NombreDelRepositorioDeLaBaseDeDatos + ',' + this.UrlDelGrupo + '/' + this.NombreDelRepositorioDelBackend
|
|
20
|
+
+ ',' + this.UrlDelGrupo + '/' + this.NombreDelRepositorioDelFrontend;
|
|
20
21
|
this.NombreDelPermiso = this.NombreCanonicoDelModulo + ' - ' + InformacionDelModulo.getNombreDelPermiso();
|
|
21
22
|
this.NombreDelPermisoV2 = InformacionDelModulo.getNombreDelPermiso();
|
|
22
23
|
this.DescripcionDelPermiso = InformacionDelModulo.getDescripcionDelPermiso();
|
|
@@ -750,6 +751,68 @@ class Miscelaneo {
|
|
|
750
751
|
return;
|
|
751
752
|
}
|
|
752
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
|
+
|
|
753
816
|
async Autenticar(Solicitud) {
|
|
754
817
|
const crypto = require('crypto');
|
|
755
818
|
const bcrypt = require('bcryptjs');
|
|
@@ -985,7 +1048,7 @@ class Miscelaneo {
|
|
|
985
1048
|
`a`.`Tipo`, IF(`a`.`Icono` <> '', CONCAT('https://storage.sigu.utn.ac.cr/images/cards/', `a`.`Icono`), '') AS `Icono`, `a`.`Color`, `a`.`Correo`,\
|
|
986
1049
|
`a`.`Version`, `a`.`FechaDePublicacion`, `a`.`AcuerdoDeNivelDeServicio`, `a`.`DiccionarioDeDatos`, `a`.`Repositorios`,\
|
|
987
1050
|
`a`.`EnlaceDelVideo`,`a`.`EnlaceDelManual`\
|
|
988
|
-
, `a`.`Estado`, REGEXP_SUBSTR(`a`.`Repositorios`, '[^,]*front[^,]*') AS `Frontend`\
|
|
1051
|
+
, `a`.`Estado`, REGEXP_SUBSTR(SUBSTRING_INDEX(`a`.`Repositorios`, '/', -1), '[^,]*front[^,]*') AS `Frontend`\
|
|
989
1052
|
FROM `SIGU`.`SIGU_ModulosV2` `a`\
|
|
990
1053
|
WHERE `a`.`Nombre` = ?", [this.NombreCanonicoDelModulo]);
|
|
991
1054
|
return Modulos.map((linea) => {
|
|
@@ -1179,10 +1242,10 @@ class Miscelaneo {
|
|
|
1179
1242
|
const Version = this.Version + "$$" + this.versionDelNucleo().split(' ')[0];
|
|
1180
1243
|
await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_ModulosV2` VALUES\
|
|
1181
1244
|
(?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(4), ?, 'DiccionarioDeDatos'\
|
|
1182
|
-
, ?, '-', '-', 'Activo', NOW(4), USER()) ON DUPLICATE KEY UPDATE `Version` = ?"
|
|
1245
|
+
, ?, '-', '-', 'Activo', NOW(4), USER()) ON DUPLICATE KEY UPDATE `Version` = ?, `Repositorios` = ?"
|
|
1183
1246
|
, [this.NombreCanonicoDelModulo, this.MenuPadre, this.DescripcionDelModulo, this.DetalleDelModulo
|
|
1184
1247
|
, this.TipoDeCard, this.IconoDelModulo, this.ColorDelModulo, this.CorreoParaReportes, Version, this.versionDelNucleo().split(' ')[0], this.Repositorios
|
|
1185
|
-
, Version]);
|
|
1248
|
+
, Version, this.Repositorios]);
|
|
1186
1249
|
await ejecutarConsultaSIGU("SELECT IFNULL(MAX(`PermisoId`), 0) + 1 INTO @`SiguientePermisoId` FROM `SIGU`.`SIGU_PermisosV2`;\
|
|
1187
1250
|
INSERT INTO `SIGU`.`SIGU_PermisosV2` VALUES\
|
|
1188
1251
|
(@`SiguientePermisoId`, ?, ?, ?, NOW(4), USER()) ON DUPLICATE KEY UPDATE `LastUser` = USER(), `Nombre` = ?, `Descripcion` = ?;"
|
|
@@ -1546,7 +1609,7 @@ class Miscelaneo {
|
|
|
1546
1609
|
console.log(error);
|
|
1547
1610
|
return;
|
|
1548
1611
|
}
|
|
1549
|
-
return ejecutarConsultaSIGU("SELECT `a`.`Identificador`, `a`.`Identificacion`\
|
|
1612
|
+
return await ejecutarConsultaSIGU("SELECT `a`.`Identificador`, `a`.`Identificacion`\
|
|
1550
1613
|
, `a`.`Nombre`, `a`.`PrimerApellido`, `a`.`SegundoApellido`\
|
|
1551
1614
|
, (SELECT GROUP_CONCAT(`b`.`CuentaIBAN`) FROM `SIGU`.`SIGU_CuentasBancariasPersonas` `b` WHERE `b`.`Estado` = TRUE AND `a`.`Identificador` = `b`.`Identificador`) AS `CuentasIBAN`\
|
|
1552
1615
|
FROM `SIGU`.`SIGU_Personas` `a` WHERE `a`.`Identificador` = ?"
|
|
@@ -1567,28 +1630,33 @@ class Miscelaneo {
|
|
|
1567
1630
|
(SELECT `Identificador` FROM `SIGU`.`SIGU_RolesPersonas` WHERE `PerfilGeneralId` = 1 /*El perfil 1 parece ser para Estudiantes*/)");
|
|
1568
1631
|
}
|
|
1569
1632
|
|
|
1570
|
-
obtenerBeneficios() {
|
|
1571
|
-
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]);
|
|
1572
1639
|
}
|
|
1573
1640
|
|
|
1574
|
-
|
|
1575
|
-
return ejecutarConsultaSIGU("SELECT `
|
|
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");
|
|
1576
1643
|
}
|
|
1577
1644
|
|
|
1578
|
-
|
|
1579
|
-
return ejecutarConsultaSIGU("SELECT
|
|
1645
|
+
async obtenerAnios() {
|
|
1646
|
+
return await ejecutarConsultaSIGU("SELECT DISTINCT `Anio` FROM `SIGU`.`SIGU_Periodos`");
|
|
1580
1647
|
}
|
|
1581
1648
|
|
|
1582
|
-
|
|
1583
|
-
return ejecutarConsultaSIGU("SELECT
|
|
1649
|
+
async obtenerSedes() {
|
|
1650
|
+
return await ejecutarConsultaSIGU("SELECT `SedesId`, `CodigoAvatar`, `Descripcion`, `Siglas` FROM `SIGU`.`SIGU_Sedes` ORDER BY `Descripcion`");
|
|
1584
1651
|
}
|
|
1585
1652
|
|
|
1586
|
-
|
|
1587
|
-
return ejecutarConsultaSIGU("SELECT `
|
|
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`");
|
|
1588
1655
|
}
|
|
1589
1656
|
|
|
1590
|
-
|
|
1591
|
-
|
|
1657
|
+
async googleClientId() {
|
|
1658
|
+
const clientId = await ejecutarConsultaSIGU("SELECT `Valor` FROM `SIGU`.`SIGU_VariablesDeSistema` WHERE `Nombre` = 'Google-ClientId'");
|
|
1659
|
+
return clientId[0]?.['Valor'] || '';
|
|
1592
1660
|
}
|
|
1593
1661
|
|
|
1594
1662
|
async palabraSecretaParaTokens() {
|
|
@@ -2534,3 +2602,4 @@ class Miscelaneo {
|
|
|
2534
2602
|
}
|
|
2535
2603
|
|
|
2536
2604
|
module.exports = new Miscelaneo();
|
|
2605
|
+
eo();
|