utn-cli 2.0.33 → 2.0.35
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 +1 -1
- package/templates/backend/rutas/API.js +7 -0
- package/templates/backend/rutas/Servicio1.js +21 -0
- package/templates/backend/rutas/misc.js +8 -0
- package/templates/backend/servicios/API.js +27 -0
- package/templates/backend/servicios/Nucleo/Miscelaneas.js +211 -38
- package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.css +69 -51
- package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.html +6 -3
- package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.ts +12 -8
package/package.json
CHANGED
|
@@ -4,6 +4,13 @@ const Router = express.Router();
|
|
|
4
4
|
const Miscelaneo = require('../servicios/Nucleo/Miscelaneas.js');
|
|
5
5
|
const { moitoreo } = require('../servicios/Nucleo/Monitoreo.js');
|
|
6
6
|
|
|
7
|
+
// Router.post("/DescargarArchivo", async (solicitud, respuesta) => {
|
|
8
|
+
// if (await Miscelaneo.validarIdentificadorAPI(solicitud.headers)) {
|
|
9
|
+
// return Miscelaneo.descargarArchivo(respuesta, solicitud.body);
|
|
10
|
+
// }
|
|
11
|
+
// return respuesta.status(401).json();
|
|
12
|
+
// });
|
|
13
|
+
|
|
7
14
|
Router.post('/monitoreo/', async (solicitud, respuesta, next) => {
|
|
8
15
|
try {
|
|
9
16
|
if (await Miscelaneo.validarTokenV2(solicitud.headers.authorization) && await Miscelaneo.validarAccesoDelOrigen(solicitud)) {
|
|
@@ -4,6 +4,7 @@ const Router = express.Router();
|
|
|
4
4
|
const Servicio1 = require('../servicios/Servicio1.js');
|
|
5
5
|
const Miscelaneo = require('../servicios/Nucleo/Miscelaneas.js');
|
|
6
6
|
const ManejadorDeErrores = require('../servicios/Nucleo/ManejadorDeErrores.js');
|
|
7
|
+
// const API = require('../servicios/API.js')
|
|
7
8
|
|
|
8
9
|
Router.get('/funcionDeEjemplo', async (solicitud, respuesta, next) => {
|
|
9
10
|
try {
|
|
@@ -22,6 +23,26 @@ Router.get('/funcionDeEjemplo', async (solicitud, respuesta, next) => {
|
|
|
22
23
|
}
|
|
23
24
|
});
|
|
24
25
|
|
|
26
|
+
// Router.get("/descargarArchivo/:ArchivoId", async (solicitud, respuesta, next) => {
|
|
27
|
+
// try {
|
|
28
|
+
// if (await Miscelaneo.validarToken(solicitud.headers.authorization) && await Miscelaneo.validarAccesoDelOrigen(solicitud)) {
|
|
29
|
+
// try {
|
|
30
|
+
// let Datos = { ArchivoId: solicitud.params.ArchivoId };
|
|
31
|
+
// Datos.Token = solicitud.headers.authorization;
|
|
32
|
+
// await API.DescargarArchivo(Datos, respuesta);
|
|
33
|
+
// return;
|
|
34
|
+
// } catch (error) {
|
|
35
|
+
// const MensajeDeError = "No fue posible obtener el archivo";
|
|
36
|
+
// console.error(new ManejadorDeErrores(MensajeDeError, ManejadorDeErrores.obtenerNumeroDeLinea(), true, `Dirección IP: ${solicitud.ip}`));
|
|
37
|
+
// return respuesta.status(500).json({ body: undefined, error: MensajeDeError });
|
|
38
|
+
// }
|
|
39
|
+
// }
|
|
40
|
+
// return respuesta.status(401).json({ body: undefined, error: ManejadorDeErrores.mensajeDeError401() });
|
|
41
|
+
// } catch (error) {
|
|
42
|
+
// next(error)
|
|
43
|
+
// }
|
|
44
|
+
// });
|
|
45
|
+
|
|
25
46
|
// Router.get("/listar/:PaginadorAccion/:PaginadorIndice/:PaginadorTamanio/:PaginadorFiltro/:PaginadorColumnaParaFiltrar/:PaginadorColumnasParaFiltrar/:ColumnaParaOrdenar/:TipoDeOrden", async (solicitud, respuesta, next) => {
|
|
26
47
|
// try {
|
|
27
48
|
// if (await Miscelaneo.validarTokenV2(solicitud.headers.authorization) && await Miscelaneo.validarAccesoDelOrigen(solicitud)) {
|
|
@@ -4,6 +4,14 @@ const Router = express.Router();
|
|
|
4
4
|
const Miscelaneo = require('./../servicios/Nucleo/Miscelaneas.js');
|
|
5
5
|
const ManejadorDeErrores = require('../servicios/Nucleo/ManejadorDeErrores.js');
|
|
6
6
|
|
|
7
|
+
Router.post('/Verificar2FA', async (solicitud, respuesta, next) => {
|
|
8
|
+
try {
|
|
9
|
+
return respuesta.json({ body: await Miscelaneo.Verificar2FA(solicitud), error: undefined });
|
|
10
|
+
} catch (error) {
|
|
11
|
+
next(error);
|
|
12
|
+
}
|
|
13
|
+
});
|
|
14
|
+
|
|
7
15
|
Router.get('/DatosParaReporteCSV', async (solicitud, respuesta, next) => {
|
|
8
16
|
try {
|
|
9
17
|
if (await Miscelaneo.validarTokenV2(solicitud.headers.authorization) && await Miscelaneo.validarAccesoDelOrigen(solicitud)) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const Miscelaneo = require('./../servicios/Nucleo/Miscelaneas.js');
|
|
2
|
+
const { Readable } = require('stream');
|
|
2
3
|
|
|
3
4
|
class API {
|
|
4
5
|
|
|
@@ -6,6 +7,32 @@ class API {
|
|
|
6
7
|
|
|
7
8
|
};
|
|
8
9
|
|
|
10
|
+
// async DescargarArchivo(Datos, Respuesta) {
|
|
11
|
+
// let URL = undefined;
|
|
12
|
+
// switch (process.env.ENV) {
|
|
13
|
+
// case 'desarrollo':
|
|
14
|
+
// URL = 'http://dgdh-oferentes-backend-desarrollo.181.193.85.44.nip.io';
|
|
15
|
+
// break;
|
|
16
|
+
// case 'calidad':
|
|
17
|
+
// URL = 'http://dgdh-oferentes-backend-calidad.181.193.85.44.nip.io';
|
|
18
|
+
// break;
|
|
19
|
+
// case 'pruebas':
|
|
20
|
+
// URL = 'http://dgdh-oferentes-backend-pruebas.181.193.85.44.nip.io';
|
|
21
|
+
// break;
|
|
22
|
+
// case 'production':
|
|
23
|
+
// URL = 'https://dgdh-oferentes-backend.sigu.utn.ac.cr';
|
|
24
|
+
// break;
|
|
25
|
+
// default:
|
|
26
|
+
// URL = 'http://localhost:81';
|
|
27
|
+
// }
|
|
28
|
+
// URL += '/api/DescargarArchivo';
|
|
29
|
+
// let resultado = await Miscelaneo.consumirBackend(URL, Datos, 'stream');
|
|
30
|
+
// Respuesta.setHeader('Content-Type', resultado.headers.get('content-type'));
|
|
31
|
+
// Respuesta.setHeader('Content-Disposition', resultado.headers.get('content-disposition'));
|
|
32
|
+
// const nodeStream = Readable.fromWeb(resultado.body);
|
|
33
|
+
// nodeStream.pipe(Respuesta);
|
|
34
|
+
// };
|
|
35
|
+
|
|
9
36
|
// async cursosPorPersonaAnioYPeriodo(Cuerpo) {
|
|
10
37
|
// let URL = undefined;
|
|
11
38
|
// switch (process.env.ENV) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const { ejecutarConsulta, ejecutarConsultaSIGU, ejecutarConsultaCumulo } = require('./db.js');
|
|
1
|
+
const { ejecutarConsulta, ejecutarConsultaSIGU, ejecutarConsultaCumulo, crearObjetoConexionSIGU } = require('./db.js');
|
|
2
2
|
const ManejadorDeErrores = require('./ManejadorDeErrores.js');
|
|
3
3
|
const InformacionDelModulo = require('../InformacionDelModulo.js');
|
|
4
4
|
const { envioDeCorreo } = require('./EnvioDeCorreos.js');
|
|
@@ -68,7 +68,7 @@ class Miscelaneo {
|
|
|
68
68
|
obtenerNombreCanonicoDelModulo() {
|
|
69
69
|
return this.NombreCanonicoDelModulo;
|
|
70
70
|
}
|
|
71
|
-
|
|
71
|
+
|
|
72
72
|
obtenerVersionDelModulo() {
|
|
73
73
|
return this.Version;
|
|
74
74
|
}
|
|
@@ -351,7 +351,7 @@ class Miscelaneo {
|
|
|
351
351
|
});
|
|
352
352
|
await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_SolicitudesDeRestablecimientoDeClave` VALUES (?, ?, ?, NOW(4), ?)"
|
|
353
353
|
, [CorreoElectronico[0]['Identificador'], Solicitud.body.Identificacion
|
|
354
|
-
|
|
354
|
+
, SolicitudTextual, LastUser]);
|
|
355
355
|
await envioDeCorreo(CorreoElectronico[0]['CorreoElectronico'], "Solicitud de restablecimiento de clave",
|
|
356
356
|
"<p>Estimada persona usuaria,<br /><br />"
|
|
357
357
|
+ "Se ha realizado una solicitud de cambio de clave para su cuenta de acceso a SIGU.</p>"
|
|
@@ -364,49 +364,222 @@ class Miscelaneo {
|
|
|
364
364
|
return;
|
|
365
365
|
}
|
|
366
366
|
|
|
367
|
+
|
|
367
368
|
async Autenticar(Solicitud) {
|
|
368
369
|
const crypto = require('crypto');
|
|
369
370
|
const bcrypt = require('bcryptjs');
|
|
370
371
|
const jwt = require('jsonwebtoken');
|
|
371
372
|
const LastUser = await this.generarLastUser(Solicitud);
|
|
372
|
-
const
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
const
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
, [
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
373
|
+
const ConexionSigu = await crearObjetoConexionSIGU();
|
|
374
|
+
|
|
375
|
+
try {
|
|
376
|
+
const resultados = await ConexionSigu.query("SELECT `Identificador`, `Clave` FROM `SIGU`.`SIGU_Personas` WHERE `Activo` = TRUE AND `Identificacion` = ?", [Solicitud.body.Identificacion]);
|
|
377
|
+
const Identificador = resultados[0][0]['Identificador'];
|
|
378
|
+
const Resultado = await bcrypt.compare(crypto.createHash('md5').update(Solicitud.body.Clave).digest("hex"), resultados[0][0]['Clave']);
|
|
379
|
+
|
|
380
|
+
if (Resultado) {
|
|
381
|
+
console.log("La clave brindada para el usuario", Solicitud.body.Identificacion, "coincide");
|
|
382
|
+
const Token = await jwt.sign({ Identificador: Identificador, uid: Identificador }, await this.palabraSecretaParaTokens(), { expiresIn: '2h' });
|
|
383
|
+
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]
|
|
384
|
+
);
|
|
385
|
+
await ConexionSigu.query("DELETE FROM `SIGU`.`SIGU_SesionesFallidas` WHERE `Identificador` = ?", [Identificador]);
|
|
386
|
+
const permisos = await ConexionSigu.query("\
|
|
387
|
+
WITH RECURSIVE`ModulosJerarquia` AS( \
|
|
388
|
+
SELECT`Nombre`, `Padre` \
|
|
389
|
+
FROM`SIGU`.`SIGU_ModulosV2` \
|
|
390
|
+
WHERE`Nombre` COLLATE utf8mb4_spanish_ci IN(\
|
|
391
|
+
SELECT`Modulo` \
|
|
392
|
+
FROM`SIGU`.`SIGU_PermisosV2` \
|
|
393
|
+
WHERE`Nombre` LIKE '%Público%' \
|
|
394
|
+
) \
|
|
395
|
+
UNION ALL \
|
|
396
|
+
SELECT`m`.`Nombre`, `m`.`Padre` \
|
|
397
|
+
FROM`SIGU`.`SIGU_ModulosV2` `m` \
|
|
398
|
+
INNER JOIN`ModulosJerarquia` `mj` \
|
|
399
|
+
ON`mj`.`Padre` COLLATE utf8mb4_spanish_ci = \
|
|
400
|
+
`m`.`Nombre` COLLATE utf8mb4_spanish_ci \
|
|
401
|
+
) \
|
|
402
|
+
SELECT DISTINCT \
|
|
403
|
+
`p`.`PermisoId` \
|
|
404
|
+
FROM`ModulosJerarquia` `mj` \
|
|
405
|
+
JOIN`SIGU`.`SIGU_PermisosV2` `p` \
|
|
406
|
+
ON`p`.`Modulo` COLLATE utf8mb4_spanish_ci = \
|
|
407
|
+
`mj`.`Nombre` COLLATE utf8mb4_spanish_ci; \
|
|
408
|
+
");
|
|
409
|
+
|
|
410
|
+
for (const permiso of permisos[0]) {
|
|
411
|
+
await ConexionSigu.query(" \
|
|
412
|
+
INSERT INTO `SIGU`.`SIGU_PermisosPersonasV2` \
|
|
413
|
+
(`PermisoId`, `Identificador`, `LastUpdate`, `LastUser`) \
|
|
414
|
+
VALUES (?, ?, NOW(4), USER()) \
|
|
415
|
+
ON DUPLICATE KEY UPDATE \
|
|
416
|
+
`LastUser` = USER(), \
|
|
417
|
+
`LastUpdate` = NOW(4);", [permiso.PermisoId, Identificador]);
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// OBTENER IP DEL USUARIO
|
|
421
|
+
const ipUsuario = (Solicitud.headers['x-forwarded-for'] || '').split(',').shift() || Solicitud.socket?.remoteAddress || Solicitud.connection?.remoteAddress || '-';
|
|
422
|
+
|
|
423
|
+
// VERIFICAR SI LA IP YA EXISTE
|
|
424
|
+
const ipExiste = await ConexionSigu.query("\
|
|
425
|
+
SELECT COUNT(*) AS Total \
|
|
426
|
+
FROM `SIGU`.`SIGU_DireccionesUsadasPorLosUsuarios` \
|
|
427
|
+
WHERE `Identificador` = ? AND `DireccionUsadaPorElUsuario` = ?", [Identificador, ipUsuario]);
|
|
428
|
+
if (ipExiste[0][0].Total === 0) {
|
|
429
|
+
console.log("IP nueva detectada para el usuario, iniciando 2FA");
|
|
430
|
+
|
|
431
|
+
// GENERAR CODIGO 2FA
|
|
432
|
+
let Codigo2FA = await ConexionSigu.query("SELECT UUID() AS `Dato`");
|
|
433
|
+
Codigo2FA = Codigo2FA[0][0].Dato;
|
|
434
|
+
|
|
435
|
+
// GUARDAR CODIGO 2FA
|
|
436
|
+
await ConexionSigu.query(" \
|
|
437
|
+
REPLACE INTO `SIGU`.`SIGU_CodigosDe2FAParaLosUsuarios` \
|
|
438
|
+
VALUES (?, ?, NOW(4), ?)", [
|
|
439
|
+
Identificador,
|
|
440
|
+
Codigo2FA,
|
|
441
|
+
LastUser
|
|
442
|
+
]);
|
|
443
|
+
|
|
444
|
+
// OBTENER CORREO
|
|
445
|
+
const CorreoElectronico = await ConexionSigu.query(
|
|
446
|
+
"SELECT `CorreoElectronico` \
|
|
447
|
+
FROM `SIGU`.`SIGU_CorreosPersona` \
|
|
448
|
+
WHERE `Identificador` = ? \
|
|
449
|
+
AND `Principal` = TRUE"
|
|
450
|
+
, [Identificador]);
|
|
451
|
+
|
|
452
|
+
// ENVIAR CORREO
|
|
453
|
+
console.log(CorreoElectronico[0][0].CorreoElectronico)
|
|
454
|
+
await envioDeCorreo(
|
|
455
|
+
CorreoElectronico[0][0].CorreoElectronico,
|
|
456
|
+
"Código de verificación 2FA",
|
|
457
|
+
"<p>Hemos recibido su solicitud de acceso para 2FA.</p>" +
|
|
458
|
+
"<p>Para continuar con el proceso, por favor utilice el siguiente código único de verificación:</p>" +
|
|
459
|
+
"<h2>" + Codigo2FA + "</h2>" +
|
|
460
|
+
"<p>Si usted no inició este proceso, puede ignorar este mensaje.</p>"
|
|
461
|
+
);
|
|
462
|
+
return { Requiere2FA: true };
|
|
463
|
+
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
// SI LA IP YA EXISTE CONTINUA
|
|
467
|
+
await ConexionSigu.query("\
|
|
468
|
+
INSERT INTO `SIGU`.`SIGU_DireccionesUsadasPorLosUsuarios` \
|
|
469
|
+
(`DireccionUsadaPorElUsuario`, `Identificador`, `LastUpdate`, `LastUser`) \
|
|
470
|
+
VALUES (?, ?, NOW(4), ?) \
|
|
471
|
+
ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4), `LastUser` = ?;", [
|
|
472
|
+
ipUsuario,
|
|
473
|
+
Identificador,
|
|
474
|
+
LastUser,
|
|
475
|
+
LastUser
|
|
476
|
+
]);
|
|
477
|
+
return { Token, Dominio: ((process.env.ENV || 'local') === 'production' ? '.sigu.utn.ac.cr' : '.181.193.85.44.nip.io') };
|
|
478
|
+
|
|
402
479
|
} else {
|
|
403
|
-
|
|
404
|
-
|
|
480
|
+
console.log("La clave brindada para el usuario", Solicitud.body.Identificacion, "no conincide");
|
|
481
|
+
|
|
482
|
+
const Resultados2 = await ConexionSigu.query("SELECT COUNT(*) AS `Total` FROM `SIGU`.`SIGU_ClavesTemporalesDeLasPersonas` WHERE `Identificador` = ? AND `Clave` = ?", [Identificador, Solicitud.body.Clave]);
|
|
483
|
+
|
|
484
|
+
if (Resultados2[0][0]['Total'] > 0) {
|
|
485
|
+
console.log("La clave brindada para el usuario", Solicitud.body.Identificacion, "no conincide, pero coincide la clave temporal");
|
|
486
|
+
await ConexionSigu.query("UPDATE `SIGU`.`SIGU_Personas` SET `Clave` = ?, `LastUpdate` = NOW(4), `LastUser` = ? WHERE `Identificacion` = ?"
|
|
487
|
+
, [await bcrypt.hash(require('crypto').createHash('md5').update(Solicitud.body.Clave).digest("hex"), 10), LastUser, Solicitud.body.Identificacion]);
|
|
488
|
+
|
|
489
|
+
await ConexionSigu.query("DELETE FROM `SIGU`.`SIGU_ClavesTemporalesDeLasPersonas`WHERE `Identificador` = ?", [Identificador]);
|
|
490
|
+
return await this.Autenticar(Solicitud);
|
|
491
|
+
|
|
492
|
+
} else {
|
|
493
|
+
await ConexionSigu.query("INSERT INTO `SIGU`.`SIGU_SesionesFallidas` VALUES (?, ?, NOW(4))"
|
|
494
|
+
, [Identificador, Solicitud.headers.host.trim()]);
|
|
495
|
+
}
|
|
405
496
|
}
|
|
497
|
+
} catch (error) {
|
|
498
|
+
console.log(error);
|
|
499
|
+
return;
|
|
500
|
+
} finally {
|
|
501
|
+
if (ConexionSigu) await ConexionSigu.end();
|
|
406
502
|
}
|
|
407
503
|
return;
|
|
408
504
|
}
|
|
409
505
|
|
|
506
|
+
async Verificar2FA(Solicitud) {
|
|
507
|
+
const jwt = require('jsonwebtoken');
|
|
508
|
+
const ConexionSigu = await crearObjetoConexionSIGU();
|
|
509
|
+
const LastUser = await this.generarLastUser(Solicitud);
|
|
510
|
+
try {
|
|
511
|
+
const { Identificacion, Codigo } = Solicitud.body;
|
|
512
|
+
const resultados = await ConexionSigu.query(
|
|
513
|
+
"SELECT `Identificador` FROM `SIGU`.`SIGU_Personas` WHERE `Activo` = TRUE AND `Identificacion` = ?", [Identificacion]);
|
|
514
|
+
|
|
515
|
+
if (!resultados[0].length) {
|
|
516
|
+
return { error: "Usuario no encontrado" };
|
|
517
|
+
}
|
|
518
|
+
const Identificador = resultados[0][0]['Identificador'];
|
|
519
|
+
// Validar código 2FA
|
|
520
|
+
const codigoValido = await ConexionSigu.query(" \
|
|
521
|
+
SELECT COUNT(*) AS Total \
|
|
522
|
+
FROM `SIGU`.`SIGU_CodigosDe2FAParaLosUsuarios` \
|
|
523
|
+
WHERE `Identificador` = ? \
|
|
524
|
+
AND `CodigoDe2FAParaElUsuario` = ?", [Identificador, Codigo]);
|
|
525
|
+
|
|
526
|
+
if (codigoValido[0][0].Total === 0) {
|
|
527
|
+
// Eliminar código usado cuando falle
|
|
528
|
+
await ConexionSigu.query(" \
|
|
529
|
+
DELETE FROM `SIGU`.`SIGU_CodigosDe2FAParaLosUsuarios` \
|
|
530
|
+
WHERE `Identificador` = ? ", [Identificador]);
|
|
531
|
+
return { error: "Código inválido" };
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
// Eliminar código usado
|
|
535
|
+
await ConexionSigu.query(" \
|
|
536
|
+
DELETE FROM `SIGU`.`SIGU_CodigosDe2FAParaLosUsuarios` WHERE `Identificador` = ?", [Identificador]);
|
|
537
|
+
|
|
538
|
+
// Obtener IP del usuario
|
|
539
|
+
const ipUsuario = (Solicitud.headers['x-forwarded-for'] || '').split(',').shift() || Solicitud.socket?.remoteAddress || Solicitud.connection?.remoteAddress || '-';
|
|
540
|
+
|
|
541
|
+
// Guardar IP autorizada
|
|
542
|
+
await ConexionSigu.query(" \
|
|
543
|
+
INSERT INTO `SIGU`.`SIGU_DireccionesUsadasPorLosUsuarios` (`DireccionUsadaPorElUsuario`, `Identificador`, `LastUpdate`, `LastUser`) \
|
|
544
|
+
VALUES (?, ?, NOW(4), ?) \
|
|
545
|
+
ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4), `LastUser` = ?;", [
|
|
546
|
+
ipUsuario,
|
|
547
|
+
Identificador,
|
|
548
|
+
LastUser,
|
|
549
|
+
LastUser
|
|
550
|
+
]);
|
|
551
|
+
|
|
552
|
+
// Generar token
|
|
553
|
+
const Token = await jwt.sign(
|
|
554
|
+
{ Identificador: Identificador, uid: Identificador },
|
|
555
|
+
await this.palabraSecretaParaTokens(),
|
|
556
|
+
{ expiresIn: '2h' }
|
|
557
|
+
);
|
|
558
|
+
|
|
559
|
+
// Registrar sesión
|
|
560
|
+
await ConexionSigu.query(" \
|
|
561
|
+
INSERT INTO `SIGU`.`SIGU_Sesiones` \
|
|
562
|
+
VALUES (?, ?, ?, NOW(4), ?) \
|
|
563
|
+
ON DUPLICATE KEY UPDATE `Token` = ?, `LastUser` = ?", [
|
|
564
|
+
Identificador,
|
|
565
|
+
Solicitud.headers.host.trim(),
|
|
566
|
+
Token,
|
|
567
|
+
LastUser,
|
|
568
|
+
Token,
|
|
569
|
+
LastUser
|
|
570
|
+
]);
|
|
571
|
+
return {
|
|
572
|
+
Token,
|
|
573
|
+
Dominio: ((process.env.ENV || 'local') === 'production' ? '.sigu.utn.ac.cr' : '.181.193.85.44.nip.io')
|
|
574
|
+
};
|
|
575
|
+
} catch (error) {
|
|
576
|
+
console.log(error);
|
|
577
|
+
return { error: "Error verificando 2FA" };
|
|
578
|
+
} finally {
|
|
579
|
+
if (ConexionSigu) await ConexionSigu.end();
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
410
583
|
async ListadoDePaisesParaCrearCuenta() {
|
|
411
584
|
const Resultado = await ejecutarConsultaSIGU("SELECT REPLACE(MID(`COLUMN_TYPE`, 6, CHAR_LENGTH(`COLUMN_TYPE`) - 6), \"'\", '') AS `Datos` FROM `information_schema`.`COLUMNS`\
|
|
412
585
|
WHERE `TABLE_SCHEMA` = 'SIGU' AND `TABLE_NAME` = 'SIGU_Personas' AND\
|
|
@@ -538,7 +711,7 @@ class Miscelaneo {
|
|
|
538
711
|
+ "<p><b>Detalle de la incidencia: </b>" + Datos.detalle + "</p><br />"
|
|
539
712
|
+ "<p><b>Resultado esperado: </b>" + Datos.resultado + "</p><br />"
|
|
540
713
|
+ "<p><b>Información de contacto: </b>" + Datos.concato + "</p><br />"
|
|
541
|
-
+ "<p><b>Información del usuario: </b>" + await this.
|
|
714
|
+
+ "<p><b>Información del usuario: </b>" + await this.obtenerDatosDelUsuario(Solicitud.headers.authorization) + "</p><br />"
|
|
542
715
|
, [DatosDelArchivo.rutaDeArchivo]);
|
|
543
716
|
return;
|
|
544
717
|
}
|
|
@@ -549,7 +722,7 @@ class Miscelaneo {
|
|
|
549
722
|
"<p><b>Sistema: </b>" + this.NombreCanonicoDelModulo + "</p><br />"
|
|
550
723
|
+ "<p><b>Asunto: </b>Reporte de sugerencia</p><br />"
|
|
551
724
|
+ "<p><b>Detalle de la sugerencia: </b>" + Datos.detalle + "</p><br />"
|
|
552
|
-
+ "<p><b>Información del usuario: </b>" + await this.
|
|
725
|
+
+ "<p><b>Información del usuario: </b>" + await this.obtenerDatosDelUsuario(Solicitud.headers.authorization) + "</p><br />");
|
|
553
726
|
return;
|
|
554
727
|
}
|
|
555
728
|
|
|
@@ -1068,7 +1241,7 @@ class Miscelaneo {
|
|
|
1068
1241
|
if (!Resultado) {
|
|
1069
1242
|
throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorVerificacionDeToken(), ManejadorDeErrores.obtenerNumeroDeLinea(), encabezadoDeAutorizacion);
|
|
1070
1243
|
}
|
|
1071
|
-
Resultado.token = token;
|
|
1244
|
+
// Resultado.token = token;
|
|
1072
1245
|
const DatosDeLaPersona = await ejecutarConsultaSIGU("SELECT `Identificacion`, `Nombre`, `PrimerApellido`,\
|
|
1073
1246
|
`SegundoApellido`, CONCAT(`FechaNacimiento`) AS `FechaDeNacimiento`\
|
|
1074
1247
|
FROM `SIGU`.`SIGU_Personas` WHERE `Identificador` = ?", [Resultado.uid]);
|
package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.css
CHANGED
|
@@ -3,88 +3,106 @@ button:focus {
|
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
.contenedor {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
padding
|
|
10
|
-
|
|
11
|
-
|
|
6
|
+
max-height: 80vh;
|
|
7
|
+
display: flex;
|
|
8
|
+
flex-direction: column;
|
|
9
|
+
padding: 20px;
|
|
10
|
+
/* Padding uniforme en todos los lados */
|
|
12
11
|
background-color: white;
|
|
12
|
+
overflow: hidden;
|
|
13
|
+
box-sizing: border-box;
|
|
13
14
|
}
|
|
14
15
|
|
|
15
|
-
.
|
|
16
|
-
width:
|
|
17
|
-
|
|
18
|
-
margin-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
.lista {
|
|
17
|
+
width: 100%;
|
|
18
|
+
/* Ocupa todo el ancho disponible del contenedor */
|
|
19
|
+
margin-bottom: 15px;
|
|
20
|
+
max-height: 300px;
|
|
21
|
+
overflow-y: auto;
|
|
22
|
+
overflow-x: hidden;
|
|
22
23
|
display: flex;
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
gap: 8px;
|
|
26
|
+
/* Espacio uniforme entre archivos */
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
29
|
+
/* Estilo de la fila de archivo */
|
|
30
|
+
.lista .archivo {
|
|
31
|
+
border: solid 1px #007bff;
|
|
32
|
+
border-radius: 8px;
|
|
33
|
+
display: flex;
|
|
34
|
+
justify-content: space-between;
|
|
35
|
+
align-items: center;
|
|
36
|
+
padding: 8px 15px;
|
|
37
|
+
/* Espacio interno simétrico */
|
|
38
|
+
box-sizing: border-box;
|
|
30
39
|
}
|
|
31
40
|
|
|
32
|
-
.
|
|
33
|
-
|
|
34
|
-
|
|
41
|
+
.lista .archivo p {
|
|
42
|
+
margin: 0;
|
|
43
|
+
flex: 1;
|
|
44
|
+
/* El texto toma el espacio restante */
|
|
45
|
+
text-align: left;
|
|
46
|
+
padding-right: 10px;
|
|
35
47
|
}
|
|
36
48
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
49
|
+
/* Zona de Arrastre */
|
|
50
|
+
.zona-archivo {
|
|
51
|
+
width: 100%;
|
|
52
|
+
/* Centrado automático */
|
|
53
|
+
height: 100px;
|
|
54
|
+
border: 2px dashed #3498db;
|
|
55
|
+
border-radius: 8px;
|
|
56
|
+
display: flex;
|
|
57
|
+
justify-content: center;
|
|
58
|
+
align-items: center;
|
|
40
59
|
cursor: pointer;
|
|
41
|
-
|
|
60
|
+
transition: background 0.3s;
|
|
61
|
+
box-sizing: border-box;
|
|
42
62
|
}
|
|
43
63
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
margin-right: 5%;
|
|
64
|
+
/* Centrado del mensaje vacío */
|
|
65
|
+
.mensaje-vacio {
|
|
47
66
|
display: flex;
|
|
48
|
-
|
|
67
|
+
justify-content: center;
|
|
68
|
+
align-items: center;
|
|
69
|
+
padding: 40px 0;
|
|
70
|
+
/* Margen superior e inferior igual */
|
|
71
|
+
color: #7f8c8d;
|
|
72
|
+
width: 100%;
|
|
49
73
|
}
|
|
50
74
|
|
|
51
|
-
.
|
|
52
|
-
|
|
53
|
-
margin-bottom: 2%;
|
|
54
|
-
padding-left: 4%;
|
|
75
|
+
.mensaje-vacio p {
|
|
76
|
+
margin: 0;
|
|
55
77
|
}
|
|
56
78
|
|
|
57
|
-
.
|
|
58
|
-
|
|
59
|
-
;
|
|
60
|
-
border-radius: 10px;
|
|
61
|
-
width: 100%;
|
|
79
|
+
.pie {
|
|
80
|
+
margin-top: 20px;
|
|
62
81
|
display: flex;
|
|
63
|
-
justify-content:
|
|
64
|
-
|
|
65
|
-
|
|
82
|
+
justify-content: flex-end;
|
|
83
|
+
/* Alinea botones a la derecha */
|
|
84
|
+
gap: 10px;
|
|
66
85
|
}
|
|
67
86
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
width: 70%;
|
|
72
|
-
padding: 1%;
|
|
87
|
+
/* Estilizador de Scrollbar */
|
|
88
|
+
.lista::-webkit-scrollbar {
|
|
89
|
+
width: 6px;
|
|
73
90
|
}
|
|
74
91
|
|
|
75
|
-
.lista
|
|
76
|
-
|
|
92
|
+
.lista::-webkit-scrollbar-thumb {
|
|
93
|
+
background: #bdc3c7;
|
|
94
|
+
border-radius: 10px;
|
|
77
95
|
}
|
|
78
96
|
|
|
97
|
+
/* Iconos */
|
|
79
98
|
.descargar {
|
|
80
99
|
color: #007bff;
|
|
81
|
-
margin-right: 5%;
|
|
82
100
|
}
|
|
83
101
|
|
|
84
102
|
.eliminar {
|
|
85
|
-
color:
|
|
103
|
+
color: #e74c3c;
|
|
86
104
|
}
|
|
87
105
|
|
|
88
106
|
.deshabilitado {
|
|
89
|
-
color:
|
|
107
|
+
color: #bdc3c7;
|
|
90
108
|
}
|
package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.html
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
<div class="lista">
|
|
3
3
|
@for(archivo of ListaArchivos;track $index){
|
|
4
4
|
<div class="archivo">
|
|
5
|
-
<p>{{archivo.Nombre}}
|
|
5
|
+
<p style="text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;">{{archivo.Nombre}}
|
|
6
|
+
</p>
|
|
6
7
|
<button mat-icon-button (click)="DescargarArchivo(archivo.ArchivoId,archivo.Nombre)" matTooltip="Descargar">
|
|
7
8
|
<!--pone deshabilitado si es estado coincide con el indicado -->
|
|
8
9
|
<mat-icon class="descargar">download</mat-icon>
|
|
@@ -29,11 +30,13 @@
|
|
|
29
30
|
</div>
|
|
30
31
|
} @else {
|
|
31
32
|
@if(ListaArchivos.length === 0) {
|
|
32
|
-
<
|
|
33
|
+
<div class="mensaje-vacio">
|
|
34
|
+
<p>Sin archivos adjuntos</p>
|
|
35
|
+
</div>
|
|
33
36
|
}
|
|
34
37
|
}
|
|
35
38
|
<div class="pie">
|
|
36
39
|
<button mat-button [disabled]="!EsEditable" (click)="SubirArchivo()">Guardar</button>
|
|
37
40
|
<button mat-button (click)="Cancelar()">Cerrar</button>
|
|
38
41
|
</div>
|
|
39
|
-
</div>
|
|
42
|
+
</div>
|
package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.ts
CHANGED
|
@@ -21,10 +21,17 @@ export class SubirArchivoComponent implements OnInit {
|
|
|
21
21
|
Etiqueta = this.data.Etiqueta + this.Permiso;
|
|
22
22
|
EsEditable = this.data.EsEditable;
|
|
23
23
|
Token: any;
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
) { }
|
|
24
|
+
public RutaParaListar: string = 'misc/listarArchivos/';
|
|
25
|
+
public RutaParaDescargar: string = 'misc/descargarArchivo/';
|
|
26
|
+
constructor(private datosGlobalesService: DatosGlobalesService, private http: HttpClient) { }
|
|
27
|
+
|
|
27
28
|
ngOnInit(): void {
|
|
29
|
+
if (this.data.RutaParaListar) {
|
|
30
|
+
this.RutaParaListar = this.data.RutaParaListar;
|
|
31
|
+
}
|
|
32
|
+
if (this.data.RutaParaDescargar) {
|
|
33
|
+
this.RutaParaDescargar = this.data.RutaParaDescargar;
|
|
34
|
+
}
|
|
28
35
|
this.ListarArchivos(this.Etiqueta)
|
|
29
36
|
}
|
|
30
37
|
|
|
@@ -33,7 +40,6 @@ export class SubirArchivoComponent implements OnInit {
|
|
|
33
40
|
event.stopPropagation();
|
|
34
41
|
const archivoZona = event.target as HTMLElement;
|
|
35
42
|
archivoZona.classList.add('arrastrar');
|
|
36
|
-
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
ArrastrarAfuera(event: DragEvent) {
|
|
@@ -44,10 +50,8 @@ export class SubirArchivoComponent implements OnInit {
|
|
|
44
50
|
Soltar(event: DragEvent) {
|
|
45
51
|
event.preventDefault();
|
|
46
52
|
event.stopPropagation();
|
|
47
|
-
|
|
48
53
|
const archivoZona = event.target as HTMLElement;
|
|
49
54
|
archivoZona.classList.remove('arrastrar');
|
|
50
|
-
|
|
51
55
|
if (event.dataTransfer?.files.length && this.EsEditable) {
|
|
52
56
|
this.Archivo = event.dataTransfer.files[0];
|
|
53
57
|
}
|
|
@@ -89,7 +93,7 @@ export class SubirArchivoComponent implements OnInit {
|
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
ListarArchivos(Etiqueta: string) {
|
|
92
|
-
this.http.get(this.datosGlobalesService.ObtenerURL() +
|
|
96
|
+
this.http.get(this.datosGlobalesService.ObtenerURL() + this.RutaParaListar + Etiqueta)
|
|
93
97
|
.subscribe({
|
|
94
98
|
next: (data: any) => {
|
|
95
99
|
this.ListaArchivos = data.body;
|
|
@@ -101,7 +105,7 @@ export class SubirArchivoComponent implements OnInit {
|
|
|
101
105
|
}
|
|
102
106
|
|
|
103
107
|
DescargarArchivo(ArchivoId: string, Nombre: string) {
|
|
104
|
-
this.http.get(this.datosGlobalesService.ObtenerURL() +
|
|
108
|
+
this.http.get(this.datosGlobalesService.ObtenerURL() + this.RutaParaDescargar + ArchivoId + this.Permiso
|
|
105
109
|
, { responseType: 'blob' })
|
|
106
110
|
.subscribe((pdfBlob) => {
|
|
107
111
|
const url = window.URL.createObjectURL(pdfBlob);
|