utn-cli 1.0.0

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.
Files changed (140) hide show
  1. package/commands/backend.js +282 -0
  2. package/commands/db.js +49 -0
  3. package/commands/frontend.js +225 -0
  4. package/index.js +98 -0
  5. package/package.json +27 -0
  6. package/templates/backend/InformacionDelModulo.json +21 -0
  7. package/templates/backend/NOMBRE_DEL_CANONICO_DEL_PROYECTO.rest +74 -0
  8. package/templates/backend/README.md +0 -0
  9. package/templates/backend/gitignore +3 -0
  10. package/templates/backend/index.rest +288 -0
  11. package/templates/backend/package.json +30 -0
  12. package/templates/backend/reporte.pdf +0 -0
  13. package/templates/backend/rutas/API.js +49 -0
  14. package/templates/backend/rutas/Servicio1.js +184 -0
  15. package/templates/backend/rutas/misc.js +671 -0
  16. package/templates/backend/rutas/rutas.js +11 -0
  17. package/templates/backend/server.js +79 -0
  18. package/templates/backend/servicios/API.js +101 -0
  19. package/templates/backend/servicios/InformacionDelModulo.js +70 -0
  20. package/templates/backend/servicios/Nucleo/EnvioDeCorreos.js +45 -0
  21. package/templates/backend/servicios/Nucleo/ManejadorDeErrores.js +54 -0
  22. package/templates/backend/servicios/Nucleo/Miscelaneas.js +1901 -0
  23. package/templates/backend/servicios/Nucleo/Monitoreo.js +65 -0
  24. package/templates/backend/servicios/Nucleo/db.js +78 -0
  25. package/templates/backend/servicios/Servicio1.js +118 -0
  26. package/templates/backend/variables-calidad.env +6 -0
  27. package/templates/backend/variables-desarrollo.env +6 -0
  28. package/templates/backend/variables-pruebas.env +6 -0
  29. package/templates/bd/README.md +78 -0
  30. package/templates/bd/cumulodb-scripts/gitignore +1 -0
  31. package/templates/bd/docker-compose.yml +28 -0
  32. package/templates/bd/docker-scripts/1-crear estructura.sql +29 -0
  33. package/templates/bd/docker-scripts/2-cambios estructura original.sql +1 -0
  34. package/templates/bd/docker-scripts/3-insertar datos de prueba.sql +1 -0
  35. package/templates/bd/docker-scripts/4-crear eventos y rutinas.sql +1 -0
  36. package/templates/bd/docker-scripts/5-crear vistas.sql +1 -0
  37. package/templates/bd/docker-scripts/6-calidad.sql +1 -0
  38. package/templates/bd/docker-scripts/7-pruebas.sql +1 -0
  39. package/templates/bd/docker-scripts/8-local.sql +1 -0
  40. package/templates/bd/servidores-scripts/calidad.sql +1 -0
  41. package/templates/bd/servidores-scripts/datos_iniciales_produccion.sql +1 -0
  42. package/templates/bd/servidores-scripts/produccion.sql +1 -0
  43. package/templates/bd/servidores-scripts/pruebas.sql +1 -0
  44. package/templates/frontend/.vscode/extensions.json +4 -0
  45. package/templates/frontend/.vscode/launch.json +20 -0
  46. package/templates/frontend/.vscode/tasks.json +42 -0
  47. package/templates/frontend/Dockerfile +5 -0
  48. package/templates/frontend/README.md +59 -0
  49. package/templates/frontend/angular.json +101 -0
  50. package/templates/frontend/dist/frontend/3rdpartylicenses.txt +459 -0
  51. package/templates/frontend/dist/frontend/prerendered-routes.json +3 -0
  52. package/templates/frontend/docker-compose.yml +5 -0
  53. package/templates/frontend/editorconfig +17 -0
  54. package/templates/frontend/gitignore +45 -0
  55. package/templates/frontend/nginx.conf +12 -0
  56. package/templates/frontend/package.json +46 -0
  57. package/templates/frontend/public/favicon.ico +0 -0
  58. package/templates/frontend/src/app/Componentes/Nucleo/graficos/graficos.component.css +15 -0
  59. package/templates/frontend/src/app/Componentes/Nucleo/graficos/graficos.component.html +25 -0
  60. package/templates/frontend/src/app/Componentes/Nucleo/graficos/graficos.component.ts +80 -0
  61. package/templates/frontend/src/app/Componentes/Nucleo/iframe/iframe.ts +37 -0
  62. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-confirmacion/mensaje-confirmacion.component.css +5 -0
  63. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-confirmacion/mensaje-confirmacion.component.html +22 -0
  64. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-confirmacion/mensaje-confirmacion.ts +64 -0
  65. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-confirmacion-html/mensaje-confirmacion-html.component.css +5 -0
  66. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-confirmacion-html/mensaje-confirmacion-html.component.html +22 -0
  67. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-confirmacion-html/mensaje-confirmacion-html.ts +64 -0
  68. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-informacion/mensaje-informacion.component.css +5 -0
  69. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-informacion/mensaje-informacion.component.html +11 -0
  70. package/templates/frontend/src/app/Componentes/Nucleo/mensaje-informacion/mensaje-informacion.ts +46 -0
  71. package/templates/frontend/src/app/Componentes/Nucleo/mensajes/mensajes.component.css +11 -0
  72. package/templates/frontend/src/app/Componentes/Nucleo/mensajes/mensajes.component.html +17 -0
  73. package/templates/frontend/src/app/Componentes/Nucleo/mensajes/mensajes.component.ts +43 -0
  74. package/templates/frontend/src/app/Componentes/Nucleo/reporte-de-incidencias/reporte-de-incidencias.component.css +37 -0
  75. package/templates/frontend/src/app/Componentes/Nucleo/reporte-de-incidencias/reporte-de-incidencias.component.html +35 -0
  76. package/templates/frontend/src/app/Componentes/Nucleo/reporte-de-incidencias/reporte-de-incidencias.component.ts +103 -0
  77. package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.css +90 -0
  78. package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.html +39 -0
  79. package/templates/frontend/src/app/Componentes/Nucleo/subir-archivo/subir-archivo.component.ts +132 -0
  80. package/templates/frontend/src/app/Componentes/Nucleo/tabla/paginador-personalizado.ts +17 -0
  81. package/templates/frontend/src/app/Componentes/Nucleo/tabla/tabla.component.css +332 -0
  82. package/templates/frontend/src/app/Componentes/Nucleo/tabla/tabla.component.html +166 -0
  83. package/templates/frontend/src/app/Componentes/Nucleo/tabla/tabla.component.ts +228 -0
  84. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta/tarjeta.component.css +129 -0
  85. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta/tarjeta.component.html +35 -0
  86. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta/tarjeta.component.ts +46 -0
  87. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-modulo/tarjeta-modulo.component.css +92 -0
  88. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-modulo/tarjeta-modulo.component.html +17 -0
  89. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-modulo/tarjeta-modulo.component.ts +42 -0
  90. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-multiple/tarjeta-multiple.component.css +90 -0
  91. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-multiple/tarjeta-multiple.component.html +22 -0
  92. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-multiple/tarjeta-multiple.component.ts +46 -0
  93. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component.css +129 -0
  94. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component.html +20 -0
  95. package/templates/frontend/src/app/Componentes/Nucleo/tarjeta-reporte/tarjeta-reporte.component.ts +25 -0
  96. package/templates/frontend/src/app/Componentes/guardar-incapacidad/guardar-incapacidad.component.css +20 -0
  97. package/templates/frontend/src/app/Componentes/guardar-incapacidad/guardar-incapacidad.component.html +46 -0
  98. package/templates/frontend/src/app/Componentes/guardar-incapacidad/guardar-incapacidad.component.ts +64 -0
  99. package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.css +142 -0
  100. package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.html +90 -0
  101. package/templates/frontend/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.ts +139 -0
  102. package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.css +4 -0
  103. package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.html +17 -0
  104. package/templates/frontend/src/app/Paginas/contenedor-principal/contenedor-principal.component.ts +36 -0
  105. package/templates/frontend/src/app/Paginas/gestion-de-reportes/gestion-de-reportes.component.css +4 -0
  106. package/templates/frontend/src/app/Paginas/gestion-de-reportes/gestion-de-reportes.component.html +6 -0
  107. package/templates/frontend/src/app/Paginas/gestion-de-reportes/gestion-de-reportes.component.ts +36 -0
  108. package/templates/frontend/src/app/Paginas/gestion-graficos/gestion-graficos.component.css +13 -0
  109. package/templates/frontend/src/app/Paginas/gestion-graficos/gestion-graficos.component.html +13 -0
  110. package/templates/frontend/src/app/Paginas/gestion-graficos/gestion-graficos.component.ts +75 -0
  111. package/templates/frontend/src/app/Paginas/gestion-iframe1/gestion-iframe1.component.css +13 -0
  112. package/templates/frontend/src/app/Paginas/gestion-iframe1/gestion-iframe1.component.html +3 -0
  113. package/templates/frontend/src/app/Paginas/gestion-iframe1/gestion-iframe1.component.ts +14 -0
  114. package/templates/frontend/src/app/Paginas/gestion-tabla/gestion-tabla.component.css +13 -0
  115. package/templates/frontend/src/app/Paginas/gestion-tabla/gestion-tabla.component.html +24 -0
  116. package/templates/frontend/src/app/Paginas/gestion-tabla/gestion-tabla.component.ts +300 -0
  117. package/templates/frontend/src/app/Paginas/gestion-tabla-XYZ/gestion-tabla-XYZ.component.css +13 -0
  118. package/templates/frontend/src/app/Paginas/gestion-tabla-XYZ/gestion-tabla-XYZ.component.html +43 -0
  119. package/templates/frontend/src/app/Paginas/gestion-tabla-XYZ/gestion-tabla-XYZ.component.ts +305 -0
  120. package/templates/frontend/src/app/Paginas/gestion-tabla-jefe/gestion-tabla-jefe.component.css +13 -0
  121. package/templates/frontend/src/app/Paginas/gestion-tabla-jefe/gestion-tabla-jefe.component.html +25 -0
  122. package/templates/frontend/src/app/Paginas/gestion-tabla-jefe/gestion-tabla-jefe.component.ts +245 -0
  123. package/templates/frontend/src/app/analytics.module.ts +45 -0
  124. package/templates/frontend/src/app/app.component.css +0 -0
  125. package/templates/frontend/src/app/app.component.html +1 -0
  126. package/templates/frontend/src/app/app.component.ts +10 -0
  127. package/templates/frontend/src/app/app.config.server.ts +14 -0
  128. package/templates/frontend/src/app/app.config.ts +27 -0
  129. package/templates/frontend/src/app/app.routes.ts +16 -0
  130. package/templates/frontend/src/app/auth.interceptor.ts +26 -0
  131. package/templates/frontend/src/app/datos-globales.service.ts +45 -0
  132. package/templates/frontend/src/assets/Puntos.svg +94 -0
  133. package/templates/frontend/src/index.html +36 -0
  134. package/templates/frontend/src/main.server.ts +7 -0
  135. package/templates/frontend/src/main.ts +6 -0
  136. package/templates/frontend/src/styles.css +14 -0
  137. package/templates/frontend/tsconfig.app.json +15 -0
  138. package/templates/frontend/tsconfig.json +27 -0
  139. package/templates/frontend/tsconfig.spec.json +15 -0
  140. package/utils/index.js +105 -0
@@ -0,0 +1,1901 @@
1
+ const { ejecutarConsulta, ejecutarConsultaSIGU, ejecutarConsultaCumulo } = require('./db.js');
2
+ const ManejadorDeErrores = require('./ManejadorDeErrores.js');
3
+ const InformacionDelModulo = require('../InformacionDelModulo.js');
4
+ const { envioDeCorreo } = require('./EnvioDeCorreos.js');
5
+
6
+ class Miscelaneo {
7
+
8
+ constructor() {
9
+ this.NombreDelModulo = InformacionDelModulo.getNombreDelModulo();
10
+ this.DescripcionDelModulo = InformacionDelModulo.getDescripcionDelModulo();
11
+ this.DetalleDelModulo = InformacionDelModulo.getDetalleDelModulo();
12
+ this.NombreCanonicoDelModulo = InformacionDelModulo.getNombreCanonicoDelModulo();
13
+ this.TipoDeCard = InformacionDelModulo.getTipoDeCard();
14
+ this.NombreDelRol = this.NombreCanonicoDelModulo + ' - ' + InformacionDelModulo.getNombreDelRol();
15
+ this.NombreDelRepositorioDeLaBaseDeDatos = InformacionDelModulo.getNombreDelRepositorioDeLaBaseDeDatos();
16
+ this.NombreDelRepositorioDelBackend = InformacionDelModulo.getNombreDelRepositorioDelBackend();
17
+ this.NombreDelRepositorioDelFrontend = InformacionDelModulo.getNombreDelRepositorioDelFrontend();
18
+ this.Repositorios = this.NombreDelRepositorioDeLaBaseDeDatos + ',' + this.NombreDelRepositorioDelBackend
19
+ + ',' + this.NombreDelRepositorioDelFrontend;
20
+ this.NombreDelPermiso = this.NombreCanonicoDelModulo + ' - ' + InformacionDelModulo.getNombreDelPermiso();
21
+ this.NombreDelPermisoV2 = InformacionDelModulo.getNombreDelPermiso();
22
+ this.DescripcionDelPermiso = InformacionDelModulo.getDescripcionDelPermiso();
23
+ this.MenuPadre = InformacionDelModulo.getMenuPadre();
24
+ this.BackEndsQueConsumeEsteModulo = InformacionDelModulo.getBackEndsQueConsumeEsteModulo();
25
+ this.PerfilGeneral = InformacionDelModulo.getPerfilGeneral();
26
+ this.UsuariosConAccesoInicial = InformacionDelModulo.getUsuariosConAccesoInicial();
27
+ this.IconoDelModulo = this.NombreCanonicoDelModulo + '.svg';
28
+ this.ColorDelModulo = InformacionDelModulo.getColorDelModulo();
29
+ this.CorreoParaReportes = InformacionDelModulo.getCorreoParaReportes();
30
+ this.Version = InformacionDelModulo.getVersion();
31
+
32
+ // Declaración de variables
33
+ // A estas variables no es necesario darles un valor inicial
34
+ this.UUID = 'UUID';
35
+ this.Enlace = undefined;
36
+ this.RolId = 0;
37
+ this.PermisoId = 0;
38
+ this.EnlaceDePortal = undefined;
39
+ this.EnlaceDePerfil = undefined;
40
+ this.EnlaceDeAcceso = undefined;
41
+ };
42
+
43
+ async convertirTextoEnArchivoLocal(Texto, Token, NombreDelArchivo, Etiquetas) {
44
+ let EnlaceDelBack = 'http';
45
+ EnlaceDelBack = EnlaceDelBack + ((process.env.ENV || 'local') === 'production' ? 's' : '');
46
+ EnlaceDelBack = EnlaceDelBack + '://';
47
+ EnlaceDelBack = EnlaceDelBack + (['desarrollo', 'calidad', 'pruebas', 'production'].includes(process.env.ENV) ? this.NombreDelRepositorioDelBackend : 'localhost');
48
+ EnlaceDelBack = EnlaceDelBack + '/misc/cargarArchivo/' + Etiquetas;
49
+ // let EnlaceDelBack = `${Solicitud.protocol}://${Solicitud.get('host')}` + '/misc/cargarArchivo/' + Etiquetas;
50
+ const Encabezados = {
51
+ 'Authorization': Token,
52
+ 'Referrer': this.NombreDelRepositorioDelBackend,
53
+ 'Origin': EnlaceDelBack
54
+ };
55
+ const blob = new Blob([Texto], { type: 'text/plain' });
56
+ const formData = new FormData();
57
+ formData.append('archivo', blob, NombreDelArchivo);
58
+ try {
59
+ const response = await fetch(EnlaceDelBack, {
60
+ method: 'POST',
61
+ headers: Encabezados,
62
+ body: formData,
63
+ redirect: 'error'
64
+ });
65
+ if (!response.ok) {
66
+ const errorTexto = await response.text();
67
+ throw new Error(`Error del servidor (${response.status}): ${errorTexto}`);
68
+ }
69
+ return await response.json();
70
+ } catch (error) {
71
+ console.error(error.message);
72
+ }
73
+ }
74
+
75
+ async RegistrarElServicio(Servicio) {
76
+ try {
77
+ await ejecutarConsultaSIGU("REPLACE INTO `SIGU`.`SIGU_ModulosV2Secciones` (`Modulo`, `Descripcion`) VALUES (?, ?)"
78
+ , [this.NombreCanonicoDelModulo, Servicio]);
79
+ console.log(`Servicio ${Servicio} registrado correctamente`);
80
+ } catch (error) {
81
+ console.error(error.message);
82
+ }
83
+ }
84
+
85
+ async DatosParaReporteCSV() {
86
+ return this.convertirACSV(await this.DatosParaGraficoDeBarras());
87
+ }
88
+
89
+ async DatosParaGraficoDeBarras() {
90
+ return await ejecutarConsultaSIGU("SELECT MONTHNAME(`FechaNacimiento`) AS `EjeHorizontal`, `Sexo` AS `Etiqueta`, COUNT(*) AS `Total` FROM `SIGU`.`SIGU_Personas` WHERE MONTH(`FechaNacimiento`) > 0 AND `Sexo` <> '' GROUP BY MONTHNAME(`FechaNacimiento`), `Sexo` ORDER BY MONTH(`FechaNacimiento`)");
91
+ }
92
+
93
+ async DatosParaGraficoDePie() {
94
+ return await ejecutarConsultaSIGU("SELECT `Tipo` AS `Etiqueta`, COUNT(*) AS `Total` FROM `SIGU`.`SIGU_ModulosV2` GROUP BY `Tipo`");
95
+ }
96
+
97
+ JSONAHTML(input, title = 'Reporte') {
98
+ // intentar parsear si es string JSON
99
+ let obj = input;
100
+ if (typeof input === 'string') {
101
+ try { obj = JSON.parse(input); }
102
+ catch (e) { /* no es JSON, lo tratamos como texto primitivo */ }
103
+ }
104
+
105
+ const escapeHtml = (s) =>
106
+ String(s)
107
+ .replace(/&/g, '&amp;')
108
+ .replace(/</g, '&lt;')
109
+ .replace(/>/g, '&gt;')
110
+ .replace(/"/g, '&quot;')
111
+ .replace(/'/g, '&#39;');
112
+
113
+ const isPrimitive = v => v === null || v === undefined || typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean';
114
+
115
+ const seen = new WeakSet();
116
+
117
+ function renderValue(v) {
118
+ if (v === null || v === undefined || v === '') return '—';
119
+ if (isPrimitive(v)) return escapeHtml(String(v));
120
+ if (Array.isArray(v)) return renderArray(v);
121
+ return renderObject(v);
122
+ }
123
+
124
+ function renderObject(o) {
125
+ if (seen.has(o)) return '<em>(referencia circular)</em>';
126
+ seen.add(o);
127
+
128
+ // si es objeto vacío
129
+ const keys = Object.keys(o);
130
+ if (keys.length === 0) {
131
+ seen.delete(o);
132
+ return '—';
133
+ }
134
+
135
+ // construir filas key / value
136
+ let rows = '';
137
+ for (const k of keys) {
138
+ rows += `
139
+ <tr>
140
+ <th>${escapeHtml(k)}</th>
141
+ <td>${renderValue(o[k])}</td>
142
+ </tr>
143
+ `;
144
+ }
145
+
146
+ seen.delete(o);
147
+ return `<table border='1'><tbody>${rows}</tbody></table>`;
148
+ }
149
+
150
+ function renderArray(arr) {
151
+ if (arr.length === 0) return '—';
152
+
153
+ // si todos son primitivos => lista simple
154
+ if (arr.every(isPrimitive)) {
155
+ return `<div>${arr.map(x => `<span>${escapeHtml(String(x))}</span>`).join(' ')}</div>`;
156
+ }
157
+
158
+ // si todos son objetos => tabla con columnas (union de keys)
159
+ if (arr.every(it => typeof it === 'object' && it !== null && !Array.isArray(it))) {
160
+ const columns = Array.from(new Set(arr.flatMap(item => Object.keys(item))));
161
+ const header = columns.map(c => `<th>${escapeHtml(c)}</th>`).join('');
162
+ const body = arr.map(item => {
163
+ const cells = columns.map(c => `<td>${item.hasOwnProperty(c) ? renderValue(item[c]) : ''}</td>`).join('');
164
+ return `<tr>${cells}</tr>`;
165
+ }).join('');
166
+ return `<table border='1'><thead><tr>${header}</tr></thead><tbody>${body}</tbody></table>`;
167
+ }
168
+
169
+ // mezcla de tipos: render por ítem
170
+ return `<div>${arr.map(it => `<div>${renderValue(it)}</div>`).join('')}</div>`;
171
+ }
172
+
173
+ // construir contenido (una sección por clave del primer nivel)
174
+ let content = '';
175
+ if (typeof obj === 'object' && obj !== null && !Array.isArray(obj)) {
176
+ const topKeys = Object.keys(obj);
177
+ for (const k of topKeys) {
178
+ content += `
179
+ <section>
180
+ <h2>${escapeHtml(k)}</h2>
181
+ <div>${renderValue(obj[k])}</div>
182
+ </section>
183
+ `;
184
+ }
185
+ } else {
186
+ // si el input fue un array o primitivo
187
+ content = `<section><div>${renderValue(obj)}</div></section>`;
188
+ }
189
+
190
+ // template HTML + CSS
191
+ return `<h1>${escapeHtml(title)}</h1>${content}`;
192
+ }
193
+
194
+ async generarLastUser(Solicitud) {
195
+ let Resultado = undefined;
196
+ try {
197
+ Resultado = await this.obtenerDatosDelUsuario(Solicitud.headers.authorization);
198
+ if (!Resultado) {
199
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorVerificacionDeToken(), ManejadorDeErrores.obtenerNumeroDeLinea());
200
+ }
201
+ } catch (error) {
202
+ console.log(error);
203
+ }
204
+ let LastUser = '';
205
+ if (Resultado) {
206
+ LastUser = Resultado.uid;
207
+ }
208
+ LastUser = LastUser + '@' + Solicitud.headers.host.trim()
209
+ + '@' + Solicitud.headers["user-agent"].trim()
210
+ + '@' + (Solicitud.ip || Solicitud.headers['x-forwarded-for'] || Solicitud.socket.remoteAddress);
211
+ return LastUser;
212
+ }
213
+
214
+ async validarAccesoDelOrigen(Solicitud) {
215
+ if (this.NombresParalocalhost().includes(process.env.HOST) && (typeof process.env.DB_HOST_SIGU === "undefined")) {
216
+ return true;
217
+ }
218
+ const Resultado = await ejecutarConsultaSIGU("SELECT COUNT(*) AS `Total` FROM `SIGU`.`SIGU_RepositoriosAccesos`\
219
+ WHERE `RepositorioDestino` = ? AND `RepositorioOrigen` = ?"
220
+ , [this.NombreDelRepositorioDelBackend, this.NombreDelRepositorioDelFrontend]);
221
+ if (Resultado[0]['Total'] === 1) {
222
+ return true;
223
+ } else {
224
+ console.error('validarAccesoDelOrigen:', Solicitud.headers.origin, 'intentó consumir a:', this.NombreDelRepositorioDelBackend);
225
+ const Mensaje = "Error de validarAccesoDelOrigen por fallo de autorización.";
226
+ const solicitudCompleta = {
227
+ metodo: Solicitud.method,
228
+ url: Solicitud.originalUrl,
229
+ ip: Solicitud.ip,
230
+ headers: Solicitud.headers,
231
+ query: Solicitud.query,
232
+ params: Solicitud.params,
233
+ body: Solicitud.body,
234
+ };
235
+ const contenidoHTML = `
236
+ <h2>Solicitud HTTP completa</h2>
237
+ <p><strong>Método:</strong> ${solicitudCompleta.metodo}</p>
238
+ <p><strong>URL:</strong> ${solicitudCompleta.url}</p>
239
+ <p><strong>IP:</strong> ${solicitudCompleta.ip}</p>
240
+ <h3>Headers:</h3>
241
+ <pre>${JSON.stringify(solicitudCompleta.headers, null, 2)}</pre>
242
+ <h3>Query:</h3>
243
+ <pre>${JSON.stringify(solicitudCompleta.query, null, 2)}</pre>
244
+ <h3>Params:</h3>
245
+ <pre>${JSON.stringify(solicitudCompleta.params, null, 2)}</pre>
246
+ <h3>Body:</h3>
247
+ <pre>${JSON.stringify(solicitudCompleta.body, null, 2)}</pre>
248
+ `;
249
+ envioDeCorreo(process.env.DESTINATARIODEINFORMESDEERROR, Mensaje, contenidoHTML);
250
+ }
251
+ return false;
252
+ }
253
+
254
+ getNombreDelRepositorioDelBackend() {
255
+ return this.NombreDelRepositorioDelBackend;
256
+ }
257
+
258
+ async ejecucionCadaXMinutos(callback, intervaloMinutos) {
259
+ while (true) {
260
+ try {
261
+ await this.crearTareaProgramada(callback);
262
+ break;
263
+ } catch (error) {
264
+ console.error('Error al ejecutar crearTareaProgramada:', error);
265
+ console.log('Reintentando en 5 segundos...');
266
+ await new Promise(resolve => setTimeout(resolve, 5000));
267
+ }
268
+ }
269
+ const intervaloMilisegundos = intervaloMinutos * 60 * 1000;
270
+ while (true) {
271
+ const inicio = Date.now();
272
+ try {
273
+ await callback();
274
+ } catch (error) {
275
+ console.error(`Error en la función "${callback.name}":`, error?.message || error);
276
+ }
277
+ const duracion = Date.now() - inicio;
278
+ const tiempoRestante = intervaloMilisegundos - duracion;
279
+ if (tiempoRestante > 0) {
280
+ await new Promise(resolve => setTimeout(resolve, tiempoRestante));
281
+ }
282
+ }
283
+ }
284
+
285
+ async restablecimientoDeClave(Solicitud) {
286
+ let Clave = await ejecutarConsultaSIGU("SELECT MD5(NOW(4)) AS `Dato`");
287
+ Clave = Clave[0]['Dato'];
288
+ console.log("El usuario: " + Solicitud.body.Identificacion + " ha solicitado restablecer su clave de acceso.");
289
+ const CorreoElectronico = await ejecutarConsultaSIGU("SELECT `CorreoElectronico`, `Identificador` FROM `SIGU`.`SIGU_CorreosPersona` WHERE `Identificador` = (SELECT `Identificador` FROM `SIGU`.`SIGU_Personas` WHERE `Identificacion` = ?) AND `Principal` = TRUE LIMIT 1"
290
+ , [Solicitud.body.Identificacion]);
291
+ const LastUser = Solicitud.body.Identificacion
292
+ + '@' + Solicitud.headers.host.trim()
293
+ + '@' + Solicitud.headers["user-agent"].trim()
294
+ + '@' + (Solicitud.ip || Solicitud.headers['x-forwarded-for'] || Solicitud.socket.remoteAddress);
295
+ await ejecutarConsultaSIGU("REPLACE INTO `SIGU`.`SIGU_ClavesTemporalesDeLasPersonas` VALUES (?, ?, NOW(4), ?)"
296
+ , [CorreoElectronico[0]['Identificador'], Clave, LastUser]);
297
+ const SolicitudTextual = JSON.stringify({
298
+ timestamp: new Date().toISOString(),
299
+ httpVersion: Solicitud.httpVersion,
300
+ method: Solicitud.method,
301
+ protocol: Solicitud.protocol,
302
+ secure: Solicitud.secure,
303
+ ip: Solicitud.ip,
304
+ ips: Solicitud.ips,
305
+ hostname: Solicitud.hostname,
306
+ originalUrl: Solicitud.originalUrl,
307
+ baseUrl: Solicitud.baseUrl,
308
+ path: Solicitud.path,
309
+ url: Solicitud.url,
310
+ headers: Solicitud.headers,
311
+ query: Solicitud.query,
312
+ params: Solicitud.params,
313
+ body: Solicitud.body,
314
+ cookies: Solicitud.cookies,
315
+ signedCookies: Solicitud.signedCookies,
316
+ userAgent: Solicitud.get('User-Agent'),
317
+ authUser: Solicitud.user ?? null,
318
+ });
319
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_SolicitudesDeRestablecimientoDeClave` VALUES (?, ?, ?, NOW(4), ?)"
320
+ , [CorreoElectronico[0]['Identificador'], Solicitud.body.Identificacion
321
+ , SolicitudTextual, LastUser]);
322
+ await envioDeCorreo(CorreoElectronico[0]['CorreoElectronico'], "Solicitud de restablecimiento de clave",
323
+ "<p>Estimada persona usuaria,<br /><br />"
324
+ + "Se ha realizado una solicitud de cambio de clave para su cuenta de acceso a SIGU.</p>"
325
+ + "<p>Para continuar con el cambio por favor presione "
326
+ + "<a href='" + this.EnlaceDeAcceso + "/?Identificacion=" + Solicitud.body.Identificacion + "&Clave=" + Clave + "'>aquí</a>"
327
+ + " de lo contrario omita este mensaje.</p>"
328
+ + "<p>Su nueva clave es: " + Clave + " y se le invita a cambiarla lo antes posible haciendo uso del sistema.</p>"
329
+ + "<p>La vigencia de la clave generada es de 10 minutos, luego de eso se eliminará la solicitud.</p>"
330
+ + "<p>Si usted no solicitó el cambio de contraseña por favor omita este correo.</p>");
331
+ return;
332
+ }
333
+
334
+ async Autenticar(Solicitud) {
335
+ const crypto = require('crypto');
336
+ const bcrypt = require('bcryptjs');
337
+ const jwt = require('jsonwebtoken');
338
+ const LastUser = await this.generarLastUser(Solicitud);
339
+ const resultados = await ejecutarConsultaSIGU("SELECT `Identificador`, `Clave` FROM `SIGU`.`SIGU_Personas` WHERE `Activo` = TRUE AND `Identificacion` = ?"
340
+ , [Solicitud.body.Identificacion]);
341
+ const Resultado = await bcrypt.compare(crypto.createHash('md5').update(Solicitud.body.Clave).digest("hex"), resultados[0]['Clave']);
342
+ if (Resultado) {
343
+ console.log("La clave brindada para el usuario", Solicitud.body.Identificacion, "conincide");
344
+ const Token = await jwt.sign({ Identificador: resultados[0]['Identificador'], uid: resultados[0]['Identificador'] }, await this.palabraSecretaParaTokens(), { expiresIn: '2h' });
345
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_Sesiones` VALUES (?, ?, ?, NOW(4), ?) ON DUPLICATE KEY UPDATE `Token` = ?, `LastUser` = ?"
346
+ , [resultados[0]['Identificador'], Solicitud.headers.host.trim(), Token, LastUser, Token, LastUser]
347
+ );
348
+ await ejecutarConsultaSIGU("DELETE FROM `SIGU`.`SIGU_SesionesFallidas` WHERE `Identificador` = ?"
349
+ , [resultados[0]['Identificador']]);
350
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_PermisosPersonasV2`\
351
+ SELECT `PermisoId`, ?, NOW(4), USER() FROM `SIGU`.`SIGU_PermisosV2` WHERE `Nombre` LIKE '%Público%'\
352
+ ON DUPLICATE KEY UPDATE `LastUser` = USER()", [resultados[0]['Identificador']]);
353
+ return { Token, Dominio: ((process.env.ENV || 'local') === 'production' ? '.sigu.utn.ac.cr' : '.181.193.85.44.nip.io') };
354
+ } else {
355
+ console.log("La clave brindada para el usuario", Solicitud.body.Identificacion, "no conincide");
356
+ const Resultados2 = await ejecutarConsultaSIGU("SELECT COUNT(*) AS `Total` FROM `SIGU`.`SIGU_ClavesTemporalesDeLasPersonas`\
357
+ WHERE `Identificador` = ? AND `Clave` = ?"
358
+ , [resultados[0]['Identificador'], Solicitud.body.Clave]);
359
+ if (Resultados2[0]['Total'] > 0) {
360
+ console.log("La clave brindada para el usuario", Solicitud.body.Identificacion, "no conincide, pero coincide la clave temporal");
361
+ const bcrypt = require('bcryptjs');
362
+ await ejecutarConsultaSIGU("UPDATE `SIGU`.`SIGU_Personas` SET\
363
+ `Clave` = ?, `LastUpdate` = NOW(4), `LastUser` = ? WHERE `Identificacion` = ?"
364
+ , [await bcrypt.hash(require('crypto').createHash('md5').update(Solicitud.body.Clave).digest("hex"), 10)
365
+ , LastUser, Solicitud.body.Identificacion]);
366
+ await ejecutarConsultaSIGU("DELETE FROM `SIGU`.`SIGU_ClavesTemporalesDeLasPersonas`\
367
+ WHERE `Identificador` = ?", [resultados[0]['Identificador']]);
368
+ await this.Autenticar(Solicitud);
369
+ } else {
370
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_SesionesFallidas` VALUES (?, ?, NOW(4))"
371
+ , [resultados[0]['Identificador'], Solicitud.headers.host.trim()]);
372
+ }
373
+ }
374
+ return;
375
+ }
376
+
377
+ async ListadoDePaisesParaCrearCuenta() {
378
+ const Resultado = await ejecutarConsultaSIGU("SELECT REPLACE(MID(`COLUMN_TYPE`, 6, CHAR_LENGTH(`COLUMN_TYPE`) - 6), \"'\", '') AS `Datos` FROM `information_schema`.`COLUMNS`\
379
+ WHERE `TABLE_SCHEMA` = 'SIGU' AND `TABLE_NAME` = 'SIGU_Personas' AND\
380
+ `COLUMN_NAME` = 'Pais'");
381
+ return Resultado[0]['Datos'].split(',').sort();
382
+ }
383
+
384
+ async obtenerDetalleDelModulo() {
385
+ const Modulos = await ejecutarConsultaSIGU("SELECT `a`.`Nombre`, `a`.`Padre`, `a`.`Descripcion`, `a`.`Detalle`,\
386
+ `a`.`Tipo`, CONCAT('https://storage.sigu.utn.ac.cr/images/cards/', `a`.`Icono`) AS `Icono`, `a`.`Color`, `a`.`Correo`,\
387
+ `a`.`Version`, `a`.`FechaDePublicacion`, `a`.`AcuerdoDeNivelDeServicio`, `a`.`DiccionarioDeDatos`, `a`.`Repositorios`,\
388
+ `a`.`EnlaceDelVideo`,`a`.`EnlaceDelManual`\
389
+ , `a`.`Estado`, REGEXP_SUBSTR(`a`.`Repositorios`, '[^,]*front[^,]*') AS `Frontend`\
390
+ FROM `SIGU`.`SIGU_ModulosV2` `a`\
391
+ WHERE `a`.`Nombre` = ?", [this.NombreCanonicoDelModulo]);
392
+ return Modulos.map((linea) => {
393
+ linea.Enlace = this.generarEnlace(linea.Frontend);
394
+ return linea;
395
+ });
396
+ }
397
+
398
+ async obtenerMensajesInstitucionales() {
399
+ return await ejecutarConsultaSIGU("SELECT `MensajeInstitucionalId`, `Titulo`, `Texto`, `FechaYHoraDeInicio`, `FechaYHoraDeFinalizacion` FROM `SIGU`.`SIGU_MensajesInstitucionales` WHERE NOW(4) BETWEEN `FechaYHoraDeInicio` AND `FechaYHoraDeFinalizacion`");
400
+ }
401
+
402
+ async obtenerConsentimientoInformado(Modulo = undefined) {
403
+ if (Modulo === undefined) {
404
+ Modulo = this.NombreCanonicoDelModulo;
405
+ }
406
+ let Datos = await ejecutarConsultaSIGU("SELECT `ConsentimientoInformadoId`, `Titulo`, `Texto`, `TextoDeAceptacion` FROM `SIGU`.`SIGU_ConsentimientosInformadosV2`\
407
+ WHERE `Estado` = 'Activo' AND `Modulo` = ?", [Modulo]);
408
+ if (Datos.length === 0) {
409
+ Datos = await ejecutarConsultaSIGU("SELECT `ConsentimientoInformadoId`, `Titulo`, `Texto`, `TextoDeAceptacion` FROM `SIGU`.`SIGU_ConsentimientosInformadosV2`\
410
+ WHERE `Estado` = 'Activo' AND `Modulo` = ?", [this.NombreCanonicoDelModulo]);
411
+ }
412
+ return Datos[0];
413
+ }
414
+
415
+ async creacionDeConsetimientoInformado(Titulo, Texto, TextoDeAceptacion) {
416
+ return await ejecutarConsultaSIGU("UPDATE `SIGU`.`SIGU_ConsentimientosInformadosV2` SET `Estado` = 'Inactivo' WHERE\
417
+ `Modulo` = ?; INSERT INTO `SIGU`.`SIGU_ConsentimientosInformadosV2` VALUES\
418
+ (NULL, ?, ?, ?, 'Activo', ?, NOW(), USER())\
419
+ ON DUPLICATE KEY UPDATE `Estado` = 'Activo';"
420
+ , [this.NombreCanonicoDelModulo, Titulo, Texto, TextoDeAceptacion, this.NombreCanonicoDelModulo]);
421
+ }
422
+
423
+ obtenerCorreoParaReportes() {
424
+ return this.CorreoParaReportes;
425
+ }
426
+
427
+ async iniciarSesion() {
428
+ return this.EnlaceDeAcceso;
429
+ }
430
+
431
+ async obtenerModulos(Token, Padre, ModulosFavoritos) {
432
+ let Resultado = undefined;
433
+ try {
434
+ Resultado = await this.obtenerDatosDelUsuario(Token);
435
+ if (!Resultado) {
436
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorVerificacionDeToken(), ManejadorDeErrores.obtenerNumeroDeLinea());
437
+ }
438
+ } catch (error) {
439
+ console.log(error);
440
+ return;
441
+ }
442
+ const Permisos = await ejecutarConsultaSIGU("SELECT `PermisoId` FROM `SIGU`.`SIGU_PermisosPersonasV2` WHERE `Identificador` = ?"
443
+ , [Resultado.uid]);
444
+ const Modulos = await ejecutarConsultaSIGU("SELECT `a`.`Nombre`, `a`.`Padre`, `a`.`Descripcion`, `a`.`Detalle`,\
445
+ `a`.`Tipo`, CONCAT('https://storage.sigu.utn.ac.cr/images/cards/', `a`.`Icono`) AS `Icono`, `a`.`Color`, `a`.`Correo`,\
446
+ `a`.`Version`, `a`.`FechaDePublicacion`, `a`.`AcuerdoDeNivelDeServicio`, `a`.`DiccionarioDeDatos`, `a`.`Repositorios`,\
447
+ `a`.`EnlaceDelVideo`,`a`.`EnlaceDelManual`\
448
+ , `a`.`Estado`, REGEXP_SUBSTR(`a`.`Repositorios`, '[^,]*front[^,]*') AS `Frontend`\
449
+ FROM `SIGU`.`SIGU_ModulosV2` `a`\
450
+ JOIN `SIGU`.`SIGU_PermisosV2` `b` ON (`a`.`Nombre` = `b`.`Modulo`)\
451
+ WHERE `a`.`Estado` = 'Activo' AND `a`.`Padre` = ? AND `b`.`PermisoId` IN (?)\
452
+ ORDER BY FIELD(a.Nombre, " + ModulosFavoritos + ") DESC, a.Nombre", [Padre, Permisos.map(p => p.PermisoId)]);
453
+ return Modulos.map((linea) => {
454
+ linea.Enlace = this.generarEnlace(linea.Frontend);
455
+ return linea;
456
+ });
457
+ }
458
+
459
+ async crearNotificacion(IdentificadorDelUsuario, IdentificadorDelDestinatario, Mensaje) {
460
+ return await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_NotificacionesV2` VALUES (?, ?, 'Sin leer', NOW(4), NOW(4), ?)"
461
+ , [IdentificadorDelDestinatario, Mensaje, IdentificadorDelUsuario]);
462
+ }
463
+
464
+ async actualizarNotificacion(Token, FechaYHoraDeCreacion) {
465
+ let Resultado = undefined;
466
+ try {
467
+ Resultado = await this.obtenerDatosDelUsuario(Token);
468
+ if (!Resultado) {
469
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorVerificacionDeToken(), ManejadorDeErrores.obtenerNumeroDeLinea());
470
+ }
471
+ } catch (error) {
472
+ console.log(error);
473
+ return;
474
+ }
475
+ return await ejecutarConsultaSIGU("UPDATE `SIGU`.`SIGU_NotificacionesV2` SET `Estado` = 'Leída' WHERE `Identificador` = ? AND `FechaYHoraDeCreacion` = ?"
476
+ , [Resultado.uid, FechaYHoraDeCreacion]);
477
+ }
478
+
479
+ async obtenerNotificaciones(Token) {
480
+ let Resultado = undefined;
481
+ try {
482
+ Resultado = await this.obtenerDatosDelUsuario(Token);
483
+ if (!Resultado) {
484
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorVerificacionDeToken(), ManejadorDeErrores.obtenerNumeroDeLinea());
485
+ }
486
+ } catch (error) {
487
+ console.log(error);
488
+ return;
489
+ }
490
+ return await ejecutarConsultaSIGU("SELECT `Notificacion` AS `valor`, CONCAT(`FechaYHoraDeCreacion`) AS `llave`, false AS `tachado` FROM `SIGU`.`SIGU_NotificacionesV2` WHERE `Identificador` = ? AND `Estado` = 'Sin leer' ORDER BY `FechaYHoraDeCreacion` DESC LIMIT 10", [Resultado.uid]);
491
+ }
492
+
493
+ async reporteDeIncidencia(Solicitud, Datos) {
494
+ const DatosDelArchivo = await this.cargarArchivo(Solicitud, Datos);
495
+ await envioDeCorreo('msavatar@utn.ac.cr', "Reporte de incidencia",
496
+ "<p><b>Sistema: </b>" + this.NombreCanonicoDelModulo + "</p><br />"
497
+ + "<p><b>Asunto: </b>Reporte de incidencia</p><br />"
498
+ + "<p><b>Detalle de la incidencia: </b>" + Datos.detalle + "</p><br />"
499
+ + "<p><b>Resultado esperado: </b>" + Datos.resultado + "</p><br />"
500
+ + "<p><b>Información de contacto: </b>" + Datos.concato + "</p><br />"
501
+ + "<p><b>Información del usuario: </b>" + await this.obtenerDatosDeLaPersona(Solicitud.headers.authorization) + "</p><br />"
502
+ , [DatosDelArchivo.rutaDeArchivo]);
503
+ return;
504
+ }
505
+
506
+ async cerrarSesion(Token) {
507
+ let Resultado = undefined;
508
+ try {
509
+ Resultado = await this.obtenerDatosDelUsuario(Token);
510
+ if (!Resultado) {
511
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorVerificacionDeToken(), ManejadorDeErrores.obtenerNumeroDeLinea());
512
+ }
513
+ } catch (error) {
514
+ console.log(error);
515
+ return;
516
+ }
517
+ await ejecutarConsultaSIGU("DELETE FROM `SIGU`.`SIGU_Sesiones` WHERE `Token` = ?", [Token.split(" ")[1]]);
518
+ return this.EnlaceDeAcceso;
519
+ }
520
+
521
+ async permisosDelModuloV2(NombreCanonicoDelModulo) {
522
+ return await ejecutarConsultaSIGU("\
523
+ WITH RECURSIVE `Jerarquia` AS (\
524
+ SELECT\
525
+ `m`.`Padre`,\
526
+ `m`.`Nombre` AS `Modulo`,\
527
+ `p`.`PermisoId`,\
528
+ `p`.`Nombre` AS `Permiso`\
529
+ FROM `SIGU`.`SIGU_ModulosV2` `m`\
530
+ JOIN `SIGU`.`SIGU_PermisosV2` `p` ON `p`.`Modulo` = `m`.`Nombre`\
531
+ WHERE `m`.`Nombre` = ?\
532
+ UNION ALL\
533
+ SELECT \
534
+ `m`.`Padre`,\
535
+ `m`.`Nombre` AS `Modulo`,\
536
+ `p`.`PermisoId`,\
537
+ `p`.`Nombre` AS `Permiso`\
538
+ FROM `SIGU`.`SIGU_ModulosV2` `m`\
539
+ JOIN `SIGU`.`SIGU_PermisosV2` `p` ON `p`.`Modulo` = `m`.`Nombre`\
540
+ JOIN `Jerarquia` `j` ON `j`.`Padre` = `m`.`Nombre`\
541
+ )\
542
+ SELECT DISTINCT * FROM `Jerarquia`"
543
+ , [NombreCanonicoDelModulo]
544
+ );
545
+ }
546
+
547
+ async modulosV2() {
548
+ return await ejecutarConsultaSIGU("SELECT `Nombre`, `Padre`, `Descripcion`, `Detalle`, `Tipo`, `Icono`, `Color`, `Correo`, `Version`, `FechaDePublicacion`, `AcuerdoDeNivelDeServicio`, `DiccionarioDeDatos`, `Repositorios`, `EnlaceDelVideo`, `EnlaceDelManual`, `Estado` FROM `SIGU`.`SIGU_ModulosV2`");
549
+ }
550
+
551
+ async permisoIdV2() {
552
+ const Datos = await ejecutarConsultaSIGU("SELECT `PermisoId` FROM `SIGU`.`SIGU_PermisosV2` WHERE `Nombre` = ? AND `Modulo` = ?", [this.NombreDelPermisoV2, this.NombreCanonicoDelModulo]);
553
+ return Datos[0]['PermisoId'];
554
+ }
555
+
556
+ async permisoIdDelPadreV2() {
557
+ const Datos = await ejecutarConsultaSIGU("SELECT `PermisoId` FROM `SIGU`.`SIGU_PermisosV2` WHERE `Modulo` = ?"
558
+ , [this.MenuPadre]);
559
+ return Datos[0]['PermisoId'];
560
+ }
561
+
562
+ async registroDelModuloEnSIGUV2() {
563
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_ModulosV2` VALUES\
564
+ (?, ?, ?, ?, ?, ?, ?, ?, ?, NOW(4), ?, 'DiccionarioDeDatos'\
565
+ , ?, '-', '-', 'Activo', NOW(4), USER()) ON DUPLICATE KEY UPDATE `Padre` = ?, `Descripcion` = ?, `Detalle` = ?\
566
+ , `Color` = ?, `Correo` = ?, `Version` = ?, `Repositorios` = ?, `AcuerdoDeNivelDeServicio` = ?"
567
+ , [this.NombreCanonicoDelModulo, this.MenuPadre, this.DescripcionDelModulo, this.DetalleDelModulo
568
+ , this.TipoDeCard, this.IconoDelModulo, this.ColorDelModulo, this.CorreoParaReportes, this.Version, this.versionDelNucleo().split(' ')[0], this.Repositorios
569
+ , this.MenuPadre, this.DescripcionDelModulo, this.DetalleDelModulo, this.ColorDelModulo, this.CorreoParaReportes
570
+ , this.Version, this.Repositorios, this.versionDelNucleo().split(' ')[0]]);
571
+ await ejecutarConsultaSIGU("SELECT IFNULL(MAX(`PermisoId`), 0) + 1 INTO @`SiguientePermisoId` FROM `SIGU`.`SIGU_PermisosV2`;\
572
+ INSERT INTO `SIGU`.`SIGU_PermisosV2` VALUES\
573
+ (@`SiguientePermisoId`, ?, ?, ?, NOW(4), USER()) ON DUPLICATE KEY UPDATE `LastUser` = USER(), `Nombre` = ?, `Descripcion` = ?;"
574
+ , [this.NombreDelPermisoV2, this.NombreCanonicoDelModulo, this.DescripcionDelPermiso, this.NombreDelPermisoV2, this.DescripcionDelPermiso]);
575
+
576
+ // Creación de Flujo de aprobaciones predeterminado del módulo
577
+ await ejecutarConsultaSIGU("SELECT COALESCE(MAX(`FlujoDeAprobacionId`), 0) + 1 INTO @`Consecutivo` FROM `SIGU`.`SIGU_FlujosDeAprobacion`;\
578
+ INSERT INTO `SIGU`.`SIGU_FlujosDeAprobacion` VALUES (@`Consecutivo`, ?, CONCAT('Flujo de aprobación predeterminado para:', ' ', ?), TRUE, NOW(4), USER()) ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4);"
579
+ , [this.NombreCanonicoDelModulo, this.NombreCanonicoDelModulo]);
580
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_FlujosDeAprobacionPasos` VALUES (\
581
+ (SELECT `FlujoDeAprobacionId` FROM `SIGU`.`SIGU_FlujosDeAprobacion` WHERE `NombreCanonico` = ?)\
582
+ , 0, 'Sin aprobaciones realizadas', (SELECT `Identificador` FROM `SIGU`.`SIGU_Personas` WHERE `Identificacion` = '111050570'), 0, NOW(4), USER()) ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4)"
583
+ , [this.NombreCanonicoDelModulo]);
584
+
585
+ // Asignación del permiso a dvillalobos
586
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_PermisosPersonasV2` VALUES (?,\
587
+ (SELECT `Identificador` FROM `SIGU`.`SIGU_Personas` WHERE `Identificacion` = '111050570'), NOW(4), USER()) ON DUPLICATE KEY UPDATE `LastUser` = USER()"
588
+ , [await this.permisoIdV2()]);
589
+
590
+ // Asginación inicial de permisos
591
+ if (this.UsuariosConAccesoInicial.length > 0) {
592
+ const permisoId = await this.permisoIdV2();
593
+ const permisoIdDelPadre = await this.permisoIdDelPadreV2();
594
+ this.UsuariosConAccesoInicial.forEach(async (dato) => {
595
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_PermisosPersonasV2` VALUES (?,\
596
+ (SELECT `Identificador` FROM `SIGU`.`SIGU_Personas` WHERE `Identificacion` = ?), NOW(4), USER())\
597
+ ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4)"
598
+ , [permisoIdDelPadre, dato]);
599
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_PermisosPersonasV2` VALUES (?,\
600
+ (SELECT `Identificador` FROM `SIGU`.`SIGU_Personas` WHERE `Identificacion` = ?), NOW(4), USER())\
601
+ ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4)"
602
+ , [permisoId, dato]);
603
+ });
604
+ }
605
+
606
+ // Validación de que sólo el front especificado pueda consumir este backend
607
+ const uuidTemporal = await ejecutarConsultaSIGU("SELECT UUID() AS `UUID`");
608
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_Repositorios` VALUES (?, ?) ON DUPLICATE KEY UPDATE `Identificador` = ?"
609
+ , [this.NombreDelRepositorioDelFrontend, uuidTemporal[0]['UUID'], uuidTemporal[0]['UUID']]);
610
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_RepositoriosAccesos` VALUES (?, ?)\
611
+ ON DUPLICATE KEY UPDATE `RepositorioDestino` = ?,`RepositorioOrigen` = ?"
612
+ , [this.NombreDelRepositorioDelBackend, this.NombreDelRepositorioDelFrontend, this.NombreDelRepositorioDelBackend, this.NombreDelRepositorioDelFrontend]);
613
+
614
+ // Impresión de la información de registro
615
+ console.log(new Date());
616
+ console.log(`Módulo registrado correctamente en SIGU. Módulo: ${this.NombreCanonicoDelModulo}`);
617
+ console.log(`Identificador del flujo de aprobación: ${await this.idDelFlujoDeAprobacion()}`);
618
+ console.log(`Enlace del módulo: ${this.Enlace}`);
619
+ console.log(`Permisos: ${JSON.stringify(await this.permisosDelModuloV2(this.NombreCanonicoDelModulo))}`);
620
+ this.creacionDeldirectorioParaElAlmacenamientoDeArchivos();
621
+ console.log(`Versión del núcleo: ${this.versionDelNucleo()}`);
622
+
623
+ // // Creación de variables de entorno
624
+ // process.env.SERVIDORSMTP = await this.servidorSMTP();
625
+ // process.env.USUARIOSMTP = await this.usuarioSMTP();
626
+ // process.env.PUERTOSMTP = await this.puertoSMTP();
627
+ // process.env.CLAVESMTP = await this.claveSMTP();
628
+ // process.env.DESTINATARIODEINFORMESDEERROR = await this.destinatarioDeInformesDeError();
629
+ // process.env.NOMBRECANONICODELMODULO = this.NombreCanonicoDelModulo;
630
+ }
631
+
632
+ generarUUID() {
633
+ return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11)
634
+ .replace(/[018]/g, c =>
635
+ (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
636
+ );
637
+ }
638
+
639
+ async obtenerPersonasFuncionarias() {
640
+ return await ejecutarConsultaSIGU("SELECT `Identificador`, `Identificacion`, `Nombre`, `PrimerApellido`,\
641
+ `SegundoApellido` FROM `SIGU`.`SIGU_Personas` WHERE `Identificador` IN\
642
+ (SELECT `Identificador` FROM `SIGU`.`SIGU_RolesPersonas` WHERE `PerfilGeneralId` = ?) ORDER BY `Nombre`, `PrimerApellido`,\
643
+ `SegundoApellido`", [await this.perfilGeneralId()]);
644
+ }
645
+
646
+ async rolPermisoIdDelMenuPadre() {
647
+ const rolPermisoIdDelMenuPadre = await ejecutarConsultaSIGU("SELECT `RolPermisoId` FROM `SIGU`.`SIGU_RolesPermisos` WHERE\
648
+ `PermisoId` = (SELECT `PermisoId` FROM `SIGU`.`SIGU_Menu` WHERE `Nombre` = ?)", [this.MenuPadre]);
649
+ return rolPermisoIdDelMenuPadre[0]['RolPermisoId'];
650
+ }
651
+
652
+ async getUUID() {
653
+ const Identificador = await ejecutarConsultaSIGU("SELECT `Identificador` FROM `SIGU`.`SIGU_Repositorios` WHERE `Repositorio` = ?", [this.NombreDelRepositorioDelBackend]);
654
+ return Identificador[0]['Identificador'];
655
+ }
656
+
657
+ async perfilGeneralId() {
658
+ const PerfilGeneralId = await ejecutarConsultaSIGU("SELECT `PerfilGeneralId` FROM `SIGU`.`SIGU_PerfilesGenerales` WHERE `Perfil` = ?", [this.PerfilGeneral]);
659
+ return PerfilGeneralId[0]['PerfilGeneralId'];
660
+ }
661
+
662
+ async rolIdDelModulo() {
663
+ const RolId = await ejecutarConsultaSIGU("SELECT `RolId` FROM `SIGU`.`SIGU_Roles` WHERE `Descripcion` = ?", [this.NombreDelRol]);
664
+ return RolId[0]['RolId'];
665
+ }
666
+
667
+ async permisoIdDelModulo() {
668
+ const PermisoId = await ejecutarConsultaSIGU("SELECT `PermisoId` FROM `SIGU`.`SIGU_Permisos` WHERE `Nombre` = ?", [this.NombreDelPermiso]);
669
+ return PermisoId[0]['PermisoId'];
670
+ }
671
+
672
+ async rolPermisoIdDelModulo() {
673
+ this.RolId = await this.rolIdDelModulo();
674
+ this.PermisoId = await this.permisoIdDelModulo();
675
+ const RolPermisoId = await ejecutarConsultaSIGU("SELECT `RolPermisoId` FROM `SIGU`.`SIGU_RolesPermisos` WHERE `RolId` = ? AND `PermisoId` = ?"
676
+ , [this.RolId, this.PermisoId]);
677
+ return RolPermisoId[0]['RolPermisoId'];
678
+ }
679
+
680
+ async idDelMenuPadre() {
681
+ const IdDelMenuPadre = await ejecutarConsultaSIGU("SELECT `MenuId` FROM `SIGU`.`SIGU_Menu` WHERE `Nombre` = ?", [this.MenuPadre]);
682
+ return IdDelMenuPadre[0]['MenuId'];
683
+ }
684
+
685
+ async idDelMenuDelModulo() {
686
+ const IdDelMenuDelModulo = await ejecutarConsultaSIGU("SELECT `MenuId` FROM `SIGU`.`SIGU_Menu` WHERE `Nombre` = ?", [this.NombreCanonicoDelModulo]);
687
+ return IdDelMenuDelModulo[0]['MenuId'];
688
+ }
689
+
690
+ generarEnlace(Modulo) {
691
+ return ((process.env.ENV || 'local') === 'production' ? 'https' : 'http')
692
+ + '://' + Modulo
693
+ + ((process.env.ENV || 'local') === 'production' ? '' : '-' + (process.env.ENV || 'local'))
694
+ + ((process.env.ENV || 'local') === 'production' ? '.sigu.utn.ac.cr' : '.181.193.85.44.nip.io');
695
+ }
696
+
697
+ async registroDelModuloEnSIGU() {
698
+
699
+ // Creación del enlace
700
+ this.Enlace = this.generarEnlace(this.NombreDelRepositorioDelFrontend);
701
+
702
+ // Creación del enlace a portal
703
+ this.EnlaceDePortal = this.generarEnlace('portalv2-frontend');
704
+
705
+ // Creación del enlace a perfil
706
+ this.EnlaceDePerfil = this.generarEnlace('perfilv2-frontend');
707
+
708
+ // Creación del enlace a acceso
709
+ this.EnlaceDeAcceso = this.generarEnlace('accesov2-frontend');
710
+
711
+ // Creación del Rol
712
+ const RolId = await ejecutarConsultaSIGU("SELECT (MAX(`RolId`) + 1) AS `RolId` FROM `SIGU`.`SIGU_Roles` WHERE `RolId` < 1000");
713
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_Roles` VALUES (?, ?, NOW(4), USER()) ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4)", [RolId[0]['RolId'], this.NombreDelRol]);
714
+ this.RolId = await this.rolIdDelModulo();
715
+
716
+ // Creación del Módulo
717
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_Modulos` VALUES (?, ?, ?, ?, ?, 1, ?, ?\
718
+ , (SELECT `Identificador` FROM `SIGU`.`SIGU_Personas` WHERE `Identificacion` = '111050570')\
719
+ , (SELECT `Identificador` FROM `SIGU`.`SIGU_Personas` WHERE `Identificacion` = '111050570')\
720
+ , (SELECT `Identificador` FROM `SIGU`.`SIGU_Personas` WHERE `Identificacion` = '111050570')\
721
+ , ?, '1.0.0', NOW(4), 'ANS', '/', ?, '1', NOW(4), USER()) ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4)"
722
+ , [this.NombreDelModulo, this.DescripcionDelModulo, this.NombreCanonicoDelModulo, this.TipoDeCard, this.IconoDelModulo
723
+ , this.ColorDelModulo, this.RolId, this.CorreoParaReportes, this.Repositorios]);
724
+
725
+ // Creación del Permiso
726
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_Permisos` VALUES (NULL, ?, ?, NOW(4), USER()) ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4)"
727
+ , [this.NombreDelPermiso, this.DescripcionDelPermiso]);
728
+ this.PermisoId = await this.permisoIdDelModulo();
729
+
730
+ // Creación del Rol-Permiso
731
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_RolesPermisos` VALUES (NULL, ?, ?, NOW(4), USER()) ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4)"
732
+ , [this.RolId, this.PermisoId]);
733
+ this.RolPermisoId = await this.rolPermisoIdDelModulo();
734
+
735
+ // Asignación del permiso a dvillalobos
736
+ const perfilGeneralId = await this.perfilGeneralId();
737
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_RolesPersonas` VALUES (?, ?,\
738
+ (SELECT `Identificador` FROM `SIGU`.`SIGU_Personas` WHERE `Identificacion` = '111050570'), NOW(4), USER())\
739
+ ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4)"
740
+ , [this.RolPermisoId, perfilGeneralId]);
741
+
742
+ // Creación de los menús
743
+ this.IdDelMenuPadre = await this.idDelMenuPadre();
744
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_Menu` VALUES (NULL, ?, ?, ?, 'Módulo', 'opciones', ?\
745
+ , ?, ?, 0, 1, NOW(4), USER()) ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4)"
746
+ , [this.PermisoId, this.NombreCanonicoDelModulo, this.DescripcionDelModulo, this.NombreCanonicoDelModulo, this.Enlace, this.IdDelMenuPadre]);
747
+ this.IdDelMenuDelModulo = await this.idDelMenuDelModulo();
748
+
749
+ let IdDelMenuAreas = await ejecutarConsultaSIGU("SELECT `MenuId` FROM `SIGU`.`SIGU_Menu` WHERE `Nombre` = 'Menú principal de áreas'\
750
+ AND `Padre` = ?", [this.IdDelMenuDelModulo]);
751
+ if (IdDelMenuAreas.length === 0) {
752
+ IdDelMenuAreas = await ejecutarConsultaSIGU("SELECT MAX(`MenuId`) + 1 AS `MenuId` FROM `SIGU`.`SIGU_Menu`");
753
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_Menu` VALUES (?, ?, 'Menú principal de áreas', 'Regreso al menú principal de áreas', 'Opción Menú', 'inicio'\
754
+ , NULL, '/modulos', ?, 0, 1, NOW(4), USER())"
755
+ , [IdDelMenuAreas[0]['MenuId'], this.PermisoId, this.IdDelMenuDelModulo]);
756
+ }
757
+
758
+ let IdDelMenuRegreso1 = await ejecutarConsultaSIGU("SELECT `MenuId` FROM `SIGU`.`SIGU_Menu` WHERE `Nombre` = CONCAT('Regreso a ', ?)\
759
+ AND `Padre` = ?", [this.MenuPadre, this.IdDelMenuDelModulo]);
760
+ if (IdDelMenuRegreso1.length === 0) {
761
+ IdDelMenuRegreso1 = await ejecutarConsultaSIGU("SELECT MAX(`MenuId`) + 1 AS `MenuId` FROM `SIGU`.`SIGU_Menu`");
762
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_Menu` VALUES (?, ?, CONCAT('Regreso a ', ?), CONCAT('Regreso a ', ?), 'Opción Menú', 'opciones'\
763
+ , NULL, CONCAT('/modulos/', ?), ?, 0, 1, NOW(4), USER())"
764
+ , [IdDelMenuRegreso1[0]['MenuId'], this.PermisoId, this.MenuPadre, this.MenuPadre, this.IdDelMenuPadre, this.IdDelMenuDelModulo]);
765
+ }
766
+
767
+ let IdDelMenuRegreso2 = await ejecutarConsultaSIGU("SELECT `MenuId` FROM `SIGU`.`SIGU_Menu` WHERE `Nombre` = CONCAT('Regreso a ', ?)\
768
+ AND `Padre` = ?", [this.NombreCanonicoDelModulo, this.IdDelMenuDelModulo]);
769
+ if (IdDelMenuRegreso2.length === 0) {
770
+ IdDelMenuRegreso2 = await ejecutarConsultaSIGU("SELECT MAX(`MenuId`) + 1 AS `MenuId` FROM `SIGU`.`SIGU_Menu`");
771
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_Menu` VALUES (?, ?, CONCAT('Regreso a ', ?), CONCAT('Regreso a ', ?), 'Opción Menú', 'menus'\
772
+ , NULL, CONCAT('/enlace/', ?, '/', ?), ?, 0, 1, NOW(4), USER())"
773
+ , [IdDelMenuRegreso2[0]['MenuId'], this.PermisoId, this.NombreCanonicoDelModulo, this.NombreCanonicoDelModulo
774
+ , this.IdDelMenuDelModulo, Buffer.from(this.Enlace.split('//')[1]).toString('base64'), this.IdDelMenuDelModulo]);
775
+ }
776
+
777
+ // Creación del UUID del módulo
778
+ const uuidTemporal = await ejecutarConsultaSIGU("SELECT UUID() AS `UUID`");
779
+ this.UUID = uuidTemporal[0]['UUID'];
780
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_Repositorios` VALUES (?, ?) ON DUPLICATE KEY UPDATE `Identificador` = ?"
781
+ , [this.NombreDelRepositorioDelBackend, this.UUID, this.UUID]);
782
+ process.env.UUID = this.UUID;
783
+ if (this.BackEndsQueConsumeEsteModulo.length > 0) {
784
+ this.BackEndsQueConsumeEsteModulo.forEach(async (dato) => {
785
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_RepositoriosAccesos` VALUES (?, ?)\
786
+ ON DUPLICATE KEY UPDATE `RepositorioDestino` = ?,`RepositorioOrigen` = ?"
787
+ , [dato, this.NombreDelRepositorioDelBackend, dato, this.NombreDelRepositorioDelBackend]);
788
+ });
789
+ }
790
+
791
+ // Asginación inicial de permisos
792
+ if (this.UsuariosConAccesoInicial.length > 0) {
793
+ const rolPermisoIdDelPadre = await this.rolPermisoIdDelMenuPadre();
794
+ this.UsuariosConAccesoInicial.forEach(async (dato) => {
795
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_RolesPersonas` VALUES (?, ?,\
796
+ (SELECT `Identificador` FROM `SIGU`.`SIGU_Personas` WHERE `Identificacion` = ?), NOW(4), USER())\
797
+ ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4)"
798
+ , [this.RolPermisoId, perfilGeneralId, dato]);
799
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_RolesPersonas` VALUES (?, ?,\
800
+ (SELECT `Identificador` FROM `SIGU`.`SIGU_Personas` WHERE `Identificacion` = ?), NOW(4), USER())\
801
+ ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4)"
802
+ , [rolPermisoIdDelPadre, perfilGeneralId, dato]);
803
+ });
804
+ }
805
+
806
+ // Impresión de la información de registro
807
+ console.log(new Date());
808
+ console.log(`Módulo registrado correctamente en SIGU. Módulo: ${this.NombreCanonicoDelModulo}`);
809
+ console.log(`Identificador de rol a utilizar (RolId): ${this.RolId}`);
810
+ console.log(`Identificador de permiso a utilizar (PermisoId): ${this.PermisoId}`);
811
+ console.log(`Identificador de Rol-Permiso a utilizar (RolPermisoId): ${this.RolPermisoId}`);
812
+ console.log(`Identificador del menú padre (MenuId del padre): ${this.IdDelMenuPadre}`);
813
+ console.log(`Identificador del menú (MenuId del módulo): ${this.IdDelMenuDelModulo}`);
814
+ // console.log(`Identificador del flujo de aprobación: ${await this.idDelFlujoDeAprobacion()}`);
815
+ console.log(`Enlace del módulo: ${this.Enlace}`);
816
+ this.creacionDeldirectorioParaElAlmacenamientoDeArchivos();
817
+ console.log(`Versión del núcleo: ${this.versionDelNucleo()}`);
818
+
819
+ // Creación de variables de entorno
820
+ process.env.SERVIDORSMTP = await this.servidorSMTP();
821
+ process.env.USUARIOSMTP = await this.usuarioSMTP();
822
+ process.env.PUERTOSMTP = await this.puertoSMTP();
823
+ process.env.CLAVESMTP = await this.claveSMTP();
824
+ process.env.DESTINATARIODEINFORMESDEERROR = await this.destinatarioDeInformesDeError();
825
+ process.env.NOMBRECANONICODELMODULO = this.NombreCanonicoDelModulo;
826
+
827
+ await this.registroDelModuloEnSIGUV2();
828
+ }
829
+
830
+ enlaceDelFrontend() {
831
+ return this.Enlace;
832
+ }
833
+
834
+ async idDelFlujoDeAprobacion() {
835
+ const Resultado = await ejecutarConsultaSIGU("SELECT `FlujoDeAprobacionId` FROM `SIGU`.`SIGU_FlujosDeAprobacion` WHERE `NombreCanonico` = ?"
836
+ , [this.NombreCanonicoDelModulo]);
837
+ return Resultado[0]['FlujoDeAprobacionId'];
838
+ }
839
+
840
+ fechaConFormato() {
841
+ const ahora = new Date(Date.now());
842
+ const anio = ahora.getFullYear();
843
+ const mes = String(ahora.getMonth() + 1).padStart(2, '0');
844
+ const dia = String(ahora.getDate()).padStart(2, '0');
845
+ const hora = String(ahora.getHours()).padStart(2, '0');
846
+ const minutos = String(ahora.getMinutes()).padStart(2, '0');
847
+ const segundos = String(ahora.getSeconds()).padStart(2, '0');
848
+ return `${anio}${mes}${dia}${hora}${minutos}${segundos}`;
849
+ }
850
+ creacionDeldirectorioParaElAlmacenamientoDeArchivos() {
851
+ const fs = require('fs');
852
+ try {
853
+ if (!fs.existsSync(this.directorioParaElAlmacenamientoDeArchivos())) {
854
+ fs.mkdirSync(this.directorioParaElAlmacenamientoDeArchivos(), { recursive: true });
855
+ console.log(`El directorio '${this.directorioParaElAlmacenamientoDeArchivos()}' ha sido creado.`);
856
+ } else {
857
+ console.log(`El directorio '${this.directorioParaElAlmacenamientoDeArchivos()}' ya existe.`);
858
+ }
859
+ } catch (error) {
860
+ console.error(`Se presentó el siguiente problema al interactuar con el sistema de archivos: ${error}`);
861
+ }
862
+ }
863
+
864
+ directorioParaElAlmacenamientoDeArchivos() {
865
+ return '/var/storage/public/' + this.NombreCanonicoDelModulo;
866
+ }
867
+
868
+ versionDelNucleo() {
869
+ return "VERSION_DEL_NUCLEO" + " " + this.NombreCanonicoDelModulo;
870
+ }
871
+
872
+ async destinatarioDeInformesDeError() {
873
+ const destinatarioDeInformesDeError = await ejecutarConsultaSIGU("SELECT `Valor` FROM `SIGU`.`SIGU_VariablesDeSistema` WHERE `Nombre` = 'DestinatarioDeInformesDeError'");
874
+ if (destinatarioDeInformesDeError.length > 0) {
875
+ return destinatarioDeInformesDeError[0]['Valor'];
876
+ } else {
877
+ return '';
878
+ }
879
+ }
880
+
881
+ async claveSMTP() {
882
+ const claveSMTP = await ejecutarConsultaSIGU("SELECT `Valor` FROM `SIGU`.`SIGU_VariablesDeSistema` WHERE `Nombre` = 'ClaveSMTP'");
883
+ if (claveSMTP.length > 0) {
884
+ return claveSMTP[0]['Valor'];
885
+ } else {
886
+ return '';
887
+ }
888
+ }
889
+
890
+ async puertoSMTP() {
891
+ const puertoSMTP = await ejecutarConsultaSIGU("SELECT `Valor` FROM `SIGU`.`SIGU_VariablesDeSistema` WHERE `Nombre` = 'PuertoSMTP'");
892
+ if (puertoSMTP.length > 0) {
893
+ return puertoSMTP[0]['Valor'];
894
+ } else {
895
+ return '';
896
+ }
897
+ }
898
+
899
+ async usuarioSMTP() {
900
+ const usuarioSMTP = await ejecutarConsultaSIGU("SELECT `Valor` FROM `SIGU`.`SIGU_VariablesDeSistema` WHERE `Nombre` = 'UsuarioSMTP'");
901
+ if (usuarioSMTP.length > 0) {
902
+ return usuarioSMTP[0]['Valor'];
903
+ } else {
904
+ return '';
905
+ }
906
+ }
907
+
908
+ async servidorSMTP() {
909
+ const servidorSMTP = await ejecutarConsultaSIGU("SELECT `Valor` FROM `SIGU`.`SIGU_VariablesDeSistema` WHERE `Nombre` = 'ServidorSMTP'");
910
+ if (servidorSMTP.length > 0) {
911
+ return servidorSMTP[0]['Valor'];
912
+ } else {
913
+ return '';
914
+ }
915
+ }
916
+
917
+ almacenarCuentaIBAN(Cuerpo) {
918
+ return ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_CuentasBancariasPersonas` VALUES (NULL, ?, ?, TRUE, NOW(4), ?)\
919
+ ON DUPLICATE KEY UPDATE `LastUpdate` = NOW(4), `LastUser` = ?"
920
+ , [Cuerpo.Identificador, Cuerpo.IBAN, Cuerpo.LastUser, Cuerpo.LastUser]);
921
+ }
922
+
923
+ async obtenerDatosDeLaPersona(Token) {
924
+ let Resultado = undefined;
925
+ try {
926
+ Resultado = await this.obtenerDatosDelUsuario(Token);
927
+ if (!Resultado) {
928
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorVerificacionDeToken(), ManejadorDeErrores.obtenerNumeroDeLinea());
929
+ }
930
+ } catch (error) {
931
+ console.log(error);
932
+ return;
933
+ }
934
+ return ejecutarConsultaSIGU("SELECT `a`.`Identificador`, `a`.`Identificacion`\
935
+ , `a`.`Nombre`, `a`.`PrimerApellido`, `a`.`SegundoApellido`\
936
+ , (SELECT GROUP_CONCAT(`b`.`CuentaIBAN`) FROM `SIGU`.`SIGU_CuentasBancariasPersonas` `b` WHERE `b`.`Estado` = TRUE AND `a`.`Identificador` = `b`.`Identificador`) AS `CuentasIBAN`\
937
+ FROM `SIGU`.`SIGU_Personas` `a` WHERE `a`.`Identificador` = ?"
938
+ , [Resultado.uid]);
939
+ }
940
+
941
+ obtenerDatosDeLaPersonaPorIdentificacion(Identificacion) {
942
+ return ejecutarConsultaSIGU("SELECT `a`.`Identificador`, `a`.`Identificacion`\
943
+ , `a`.`Nombre`, `a`.`PrimerApellido`, `a`.`SegundoApellido`\
944
+ , (SELECT GROUP_CONCAT(`b`.`CuentaIBAN`) FROM `SIGU`.`SIGU_CuentasBancariasPersonas` `b` WHERE `b`.`Estado` = TRUE AND `a`.`Identificador` = `b`.`Identificador`) AS `CuentasIBAN`\
945
+ FROM `SIGU`.`SIGU_Personas` `a` WHERE `a`.`Identificacion` = ?"
946
+ , [Identificacion]);
947
+ }
948
+
949
+ obtenerEstudiantes() {
950
+ return ejecutarConsultaSIGU("SELECT `Identificador`, `Identificacion`, `Nombre`, `PrimerApellido`,\
951
+ `SegundoApellido` FROM `SIGU`.`SIGU_Personas` WHERE `Identificador` IN\
952
+ (SELECT `Identificador` FROM `SIGU`.`SIGU_RolesPersonas` WHERE `PerfilGeneralId` = 1 /*El perfil 1 parece ser para Estudiantes*/)");
953
+ }
954
+
955
+ obtenerBeneficios() {
956
+ return ejecutarConsultaSIGU("SELECT `BeneficioId`, `Beneficio`, `Estado` FROM `SIGU`.`SIGU_Beneficios`");
957
+ }
958
+
959
+ obtenerIdentificacion(Identificador) {
960
+ return ejecutarConsultaSIGU("SELECT `Identificacion` FROM `SIGU`.`SIGU_Personas` WHERE `Identificador` = ?", [Identificador]);
961
+ }
962
+
963
+ obtenerPeriodos() {
964
+ return ejecutarConsultaSIGU("SELECT `PeriodoId`, `CodigoPeriodo`, `Anio`, `Periodo`, `FechaInicio`, `FechaFinal`, `Tipo`, `Estado` FROM `SIGU`.`SIGU_Periodos` ORDER BY `Anio` DESC, `CodigoPeriodo` DESC");
965
+ }
966
+
967
+ obtenerAnios() {
968
+ return ejecutarConsultaSIGU("SELECT DISTINCT `Anio` FROM `SIGU`.`SIGU_Periodos`");
969
+ }
970
+
971
+ obtenerSedes() {
972
+ return ejecutarConsultaSIGU("SELECT `SedesId`, `CodigoAvatar`, `Descripcion`, `Siglas` FROM `SIGU`.`SIGU_Sedes` ORDER BY `Descripcion`");
973
+ }
974
+
975
+ obtenerRecintos() {
976
+ 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`");
977
+ }
978
+
979
+ async palabraSecretaParaTokens() {
980
+ const palabraSecreta = await ejecutarConsultaSIGU("SELECT `Valor` FROM `SIGU`.`SIGU_VariablesDeSistema` WHERE `Nombre` = 'PalabraSecretaParaLaCreacionDeTokens'");
981
+ return palabraSecreta[0]['Valor'];
982
+ }
983
+
984
+ comparacionDeCadenas(cadena1, cadena2) {
985
+ const cadenaA = String(cadena1);
986
+ let cadenaB = String(cadena2);
987
+ const tamanioDeCadelaA = cadenaA.length;
988
+ let resultado = 0;
989
+
990
+ if (tamanioDeCadelaA !== cadenaB.length) {
991
+ cadenaB = cadenaA;
992
+ resultado = 1;
993
+ }
994
+
995
+ for (let contador = 0; contador < tamanioDeCadelaA; contador++) {
996
+ resultado |= (cadenaA.charCodeAt(contador) ^ cadenaB.charCodeAt(contador));
997
+ }
998
+ return resultado === 0;
999
+ };
1000
+
1001
+ async obtenerDatosDelUsuario(encabezadoDeAutorizacion) {
1002
+ const jwt = require('jsonwebtoken');
1003
+ // Obtención del token
1004
+ let token = undefined;
1005
+ try {
1006
+ token = encabezadoDeAutorizacion.split(" ")[1];
1007
+ if (!token) {
1008
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorEncabezadoDeAutorizacion(), ManejadorDeErrores.obtenerNumeroDeLinea(), encabezadoDeAutorizacion);
1009
+ }
1010
+ } catch (error) {
1011
+ console.error(error);
1012
+ return false;
1013
+ }
1014
+
1015
+ // Verificación del token
1016
+ let Resultado = undefined;
1017
+ try {
1018
+ Resultado = await jwt.verify(token, await this.palabraSecretaParaTokens());
1019
+ if (!Resultado) {
1020
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorVerificacionDeToken(), ManejadorDeErrores.obtenerNumeroDeLinea(), encabezadoDeAutorizacion);
1021
+ }
1022
+ Resultado.token = token;
1023
+ const DatosDeLaPersona = await ejecutarConsultaSIGU("SELECT `Identificacion`, `Nombre`, `PrimerApellido`,\
1024
+ `SegundoApellido`, CONCAT(`FechaNacimiento`) AS `FechaDeNacimiento`\
1025
+ FROM `SIGU`.`SIGU_Personas` WHERE `Identificador` = ?", [Resultado.uid]);
1026
+ Resultado.Identificacion = DatosDeLaPersona[0]['Identificacion'];
1027
+ Resultado.Nombre = DatosDeLaPersona[0]['Nombre'];
1028
+ Resultado.PrimerApellido = DatosDeLaPersona[0]['PrimerApellido'];
1029
+ Resultado.SegundoApellido = DatosDeLaPersona[0]['SegundoApellido'];
1030
+ Resultado.FechaDeNacimiento = DatosDeLaPersona[0]['FechaDeNacimiento'];
1031
+ return Resultado;
1032
+ } catch (error) {
1033
+ console.error(error);
1034
+ return false;
1035
+ }
1036
+ }
1037
+
1038
+ async validarTokenV2(encabezadoDeAutorizacion, permisoExtraId = undefined) {
1039
+ let Resultado = undefined;
1040
+ try {
1041
+ Resultado = await this.obtenerDatosDelUsuario(encabezadoDeAutorizacion);
1042
+ } catch (error) {
1043
+ console.error(error);
1044
+ }
1045
+ // Validación del token para el usuario y authorización
1046
+ if (Resultado) {
1047
+ try {
1048
+ // Validación del token en la sesión
1049
+ const tokenAlmacenado = await ejecutarConsultaSIGU("SELECT COUNT(*) AS `Total` FROM `SIGU`.`SIGU_Sesiones`\
1050
+ WHERE `Identificador` = ? AND `Token` = ?", [Resultado.uid, Resultado.token]);
1051
+ if (tokenAlmacenado[0]['Total'] >= 1) { // Se compara con >= para preveer multisesiones
1052
+ // Validación de permisos
1053
+ const rolPermisoId = await this.permisoIdV2();
1054
+ const permisos = await ejecutarConsultaSIGU("SELECT COUNT(*) AS `Total` FROM `SIGU`.`SIGU_PermisosPersonasV2`\
1055
+ WHERE `PermisoId` = ? AND `Identificador` = ?", [rolPermisoId, Resultado.uid]);
1056
+ if (permisos[0]['Total'] === 1) {
1057
+ if (permisoExtraId) {
1058
+ const ValidacionPermisoExtra = await ejecutarConsultaSIGU("SELECT COUNT(*) AS `Total` FROM `SIGU`.`SIGU_PermisosPersonasV2`\
1059
+ WHERE `PermisoId` = ? AND `Identificador` = ?", [permisoExtraId, Resultado.uid]);
1060
+ if (ValidacionPermisoExtra[0]['Total'] === 1) {
1061
+ return true;
1062
+ }
1063
+ } else {
1064
+ return true;
1065
+ }
1066
+ } else {
1067
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorPermisosInsuficientes(), ManejadorDeErrores.obtenerNumeroDeLinea());
1068
+ }
1069
+ } else {
1070
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorTokenInvalido(), ManejadorDeErrores.obtenerNumeroDeLinea());
1071
+ }
1072
+ } catch (error) {
1073
+ console.error(error);
1074
+ return false;
1075
+ }
1076
+ }
1077
+ return false;
1078
+ }
1079
+
1080
+ async validarToken(encabezadoDeAutorizacion) {
1081
+ return await this.validarTokenV2(encabezadoDeAutorizacion);
1082
+ // const Resultado = undefined;
1083
+ // try {
1084
+ // Resultado = await this.obtenerDatosDelUsuario(encabezadoDeAutorizacion);
1085
+ // } catch (error) {
1086
+ // console.error(error);
1087
+ // }
1088
+ // // Validación del token para el usuario y authorización
1089
+ // if (Resultado) {
1090
+ // try {
1091
+ // // Validación del token en la sesión
1092
+ // const tokenAlmacenado = await ejecutarConsultaSIGU("SELECT COUNT(*) AS `Total` FROM `SIGU`.`SIGU_Sesiones`\
1093
+ // WHERE `Identificador` = ? AND `Token` = ?", [Resultado.uid, Resultado.token]);
1094
+ // if (tokenAlmacenado[0]['Total'] >= 1) { // Se compara con >= para preveer multisesiones
1095
+ // // Validación de permisos
1096
+ // const perfilGeneralId = await this.perfilGeneralId();
1097
+ // const rolPermisoId = await this.rolPermisoIdDelModulo();
1098
+ // const permisos = await ejecutarConsultaSIGU("SELECT COUNT(*) AS `Total` FROM `SIGU`.`SIGU_RolesPersonas`\
1099
+ // WHERE `RolPermisoId` = ? AND `Identificador` = ? AND `PerfilGeneralId` = ?", [rolPermisoId, Resultado.uid, perfilGeneralId]);
1100
+ // if (permisos[0]['Total'] === 1) {
1101
+ // return true;
1102
+ // } else {
1103
+ // throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorPermisosInsuficientes(), ManejadorDeErrores.obtenerNumeroDeLinea());
1104
+ // }
1105
+ // } else {
1106
+ // throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorTokenInvalido(), ManejadorDeErrores.obtenerNumeroDeLinea());
1107
+ // }
1108
+ // } catch (error) {
1109
+ // console.error(error);
1110
+ // return false;
1111
+ // }
1112
+ // }
1113
+ // return false;
1114
+ }
1115
+
1116
+ convertirACSV(ArregloDeJSON) {
1117
+ const Encabezados = Object.keys(ArregloDeJSON[0]);
1118
+ const Filas = ArregloDeJSON.map(Fila => {
1119
+ return Encabezados.map(Encabezado => {
1120
+ let valor = Fila[Encabezado];
1121
+ if (valor === null || valor === 'null') {
1122
+ valor = '';
1123
+ }
1124
+ return JSON.stringify(String(valor)).replace(/,/g, ' ');
1125
+ }).join(',');
1126
+ });
1127
+ return [Encabezados.join(','), ...Filas].join('\n');
1128
+ };
1129
+
1130
+ convertirACSVConDetalle(ArregloDeJSON, ColumnaConDetalle) {
1131
+ if (!ArregloDeJSON || ArregloDeJSON.length === 0) return '';
1132
+ const ejemploConDetalle = ArregloDeJSON.find(e => Array.isArray(e[ColumnaConDetalle]) && e[ColumnaConDetalle].length > 0);
1133
+ const camposDetalle = ejemploConDetalle ? Object.keys(ejemploConDetalle[ColumnaConDetalle][0]) : [];
1134
+ const columnasBase = Object.keys(ArregloDeJSON[0]).filter(key => key !== ColumnaConDetalle);
1135
+ const encabezados = [...columnasBase, ...camposDetalle];
1136
+ const filas = ArregloDeJSON.flatMap(fila => {
1137
+ const detalles = Array.isArray(fila[ColumnaConDetalle]) ? fila[ColumnaConDetalle] : [];
1138
+ if (detalles.length === 0) {
1139
+ return [
1140
+ encabezados.map(col => {
1141
+ const valor = fila[col];
1142
+ return formatearValor(valor);
1143
+ }).join(',')
1144
+ ];
1145
+ }
1146
+ return detalles.map(detalle => {
1147
+ return encabezados.map(col => {
1148
+ if (camposDetalle.includes(col)) {
1149
+ return formatearValor(detalle[col]);
1150
+ } else {
1151
+ return formatearValor(fila[col]);
1152
+ }
1153
+ }).join(',');
1154
+ });
1155
+ });
1156
+ return [encabezados.join(','), ...filas].join('\n');
1157
+ function formatearValor(valor) {
1158
+ if (valor === null || valor === 'null' || typeof valor === 'undefined') {
1159
+ return '""';
1160
+ }
1161
+ return `"${String(valor).replace(/"/g, '""')}"`; // Escapa comillas
1162
+ }
1163
+ }
1164
+
1165
+ async validarIdentificadorAPI(Encabezados) {
1166
+ // Obtención del UUID del repositorio
1167
+ let Identificador = undefined;
1168
+ try {
1169
+ Identificador = Encabezados.authorization.split(" ")[1];
1170
+ if (!Identificador) {
1171
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorEncabezadoDeAutorizacion(), ManejadorDeErrores.obtenerNumeroDeLinea());
1172
+ }
1173
+ } catch (error) {
1174
+ console.error(error);
1175
+ return false;
1176
+ }
1177
+
1178
+ // Obtención del Repositorio
1179
+ let Repositorio = undefined;
1180
+ try {
1181
+ Repositorio = Encabezados.referrer;
1182
+ if (!Repositorio) {
1183
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorRepositorioOrigen(), ManejadorDeErrores.obtenerNumeroDeLinea());
1184
+ }
1185
+ } catch (error) {
1186
+ console.error(error);
1187
+ return false;
1188
+ }
1189
+
1190
+ // Comprobar el UUID y el repositorio
1191
+ let ComprobacionDeRepositorio = undefined;
1192
+ try {
1193
+ ComprobacionDeRepositorio = await ejecutarConsultaSIGU("SELECT COUNT(*) AS `Total` FROM `SIGU`.`SIGU_Repositorios`\
1194
+ WHERE `Repositorio` = ? AND `Identificador` = ?", [Repositorio, Identificador]);
1195
+ if (ComprobacionDeRepositorio[0]['Total'] === 0) {
1196
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorRepositorioOrigen(), ManejadorDeErrores.obtenerNumeroDeLinea());
1197
+ } else {
1198
+ // Comprobar si el repositorio origen tiene derecho a consumir el repositorio destino
1199
+ let ComprobacionDeAcceso = undefined;
1200
+ try {
1201
+ ComprobacionDeAcceso = await ejecutarConsultaSIGU("SELECT COUNT(*) AS `Total` FROM `SIGU`.`SIGU_RepositoriosAccesos`\
1202
+ WHERE `RepositorioDestino` = ? AND `RepositorioOrigen` = ?", [this.NombreDelRepositorioDelBackend, Repositorio]);
1203
+ if (ComprobacionDeAcceso[0]['Total'] === 1) {
1204
+ return true;
1205
+ } else {
1206
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorPermisosInsuficientes(), ManejadorDeErrores.obtenerNumeroDeLinea());
1207
+ }
1208
+ } catch (error) {
1209
+ console.error(error);
1210
+ return false;
1211
+ }
1212
+ }
1213
+ } catch (error) {
1214
+ console.error(error);
1215
+ return false;
1216
+ }
1217
+ }
1218
+
1219
+ async validarUsuarioYContrasenia(Cuerpo) {
1220
+ // Esta función no es para autenticación, se parte del hecho de que la clave y el usario dada son correctos.
1221
+ // Esta función se usa para que APIs de entidades externas debidamente documentadas consuman nuestros servicios.
1222
+ // Si la clave no coincide, el usuario se bloquea.
1223
+ const crypto = require('crypto');
1224
+ const bcrypt = require('bcryptjs');
1225
+ const resultados = await ejecutarConsultaSIGU("SELECT `Clave` FROM `SIGU`.`SIGU_Personas` WHERE `Activo` = TRUE AND `Identificacion` = ?"
1226
+ , [Cuerpo.body.Identificacion]);
1227
+ if (resultados.length != 1) {
1228
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorAccesoAAPI("El usuario " + Cuerpo.body.Identificacion + " no existe"), ManejadorDeErrores.obtenerNumeroDeLinea());
1229
+ }
1230
+ const Resultado = await bcrypt.compare(crypto.createHash('md5').update(Cuerpo.body.Clave).digest("hex"), resultados[0]['Clave']);
1231
+ if (!Resultado) {
1232
+ const Mensaje = "Desactivación del usario: " + Cuerpo.body.Identificacion + " por fallo de autenticación.";
1233
+ console.log(Mensaje);
1234
+ const solicitudCompleta = {
1235
+ metodo: Cuerpo.method,
1236
+ url: Cuerpo.originalUrl,
1237
+ ip: Cuerpo.ip,
1238
+ headers: Cuerpo.headers,
1239
+ query: Cuerpo.query,
1240
+ params: Cuerpo.params,
1241
+ body: Cuerpo.body,
1242
+ };
1243
+ const contenidoHTML = `
1244
+ <h2>Solicitud HTTP completa</h2>
1245
+ <p><strong>Método:</strong> ${solicitudCompleta.metodo}</p>
1246
+ <p><strong>URL:</strong> ${solicitudCompleta.url}</p>
1247
+ <p><strong>IP:</strong> ${solicitudCompleta.ip}</p>
1248
+ <h3>Headers:</h3>
1249
+ <pre>${JSON.stringify(solicitudCompleta.headers, null, 2)}</pre>
1250
+ <h3>Query:</h3>
1251
+ <pre>${JSON.stringify(solicitudCompleta.query, null, 2)}</pre>
1252
+ <h3>Params:</h3>
1253
+ <pre>${JSON.stringify(solicitudCompleta.params, null, 2)}</pre>
1254
+ <h3>Body:</h3>
1255
+ <pre>${JSON.stringify(solicitudCompleta.body, null, 2)}</pre>
1256
+ `;
1257
+ envioDeCorreo(process.env.DESTINATARIODEINFORMESDEERROR, Mensaje, contenidoHTML);
1258
+ await ejecutarConsultaSIGU("UPDATE `SIGU`.`SIGU_Personas` SET `Activo` = FALSE WHERE `Identificacion` = ?"
1259
+ , [Cuerpo.body.Identificacion]);
1260
+ }
1261
+ return Resultado;
1262
+ }
1263
+
1264
+ async consumirBackend(URL, Cuerpo = undefined, Tipo = undefined) {
1265
+ const Encabezados = {
1266
+ 'Content-Type': 'application/json',
1267
+ 'Authorization': 'Bearer ' + await this.getUUID(),
1268
+ 'Referrer': this.NombreDelRepositorioDelBackend,
1269
+ 'Origin': this.Enlace
1270
+ };
1271
+ let Respuesta = undefined;
1272
+ const Opciones = {
1273
+ method: Cuerpo ? "POST" : "GET",
1274
+ headers: Encabezados,
1275
+ redirect: 'error'
1276
+ };
1277
+ if (Tipo === 'stream') {
1278
+ Opciones.responseType = 'stream';
1279
+ }
1280
+ if (Cuerpo) {
1281
+ Opciones.body = JSON.stringify(Cuerpo);
1282
+ }
1283
+ const ListaDeDominiosPermitidos = [
1284
+ "181.193.85.44.nip.io",
1285
+ "sigu.utn.ac.cr",
1286
+ "localhost",
1287
+ "svc.cluster.local"
1288
+ ];
1289
+ try {
1290
+ if (ListaDeDominiosPermitidos.some(dominio => URL.includes(dominio))) {
1291
+ Respuesta = await fetch(URL, Opciones);
1292
+ }
1293
+ if (!Respuesta.ok) {
1294
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorAccesoAAPI(Respuesta.error), ManejadorDeErrores.obtenerNumeroDeLinea());
1295
+ }
1296
+ if (Tipo === 'stream') {
1297
+ return await Respuesta;
1298
+ }
1299
+ return await Respuesta.json();
1300
+ } catch (error) {
1301
+ console.error(error);
1302
+ console.error(Respuesta);
1303
+ throw new ManejadorDeErrores(error.message, ManejadorDeErrores.obtenerNumeroDeLinea());
1304
+ }
1305
+ };
1306
+
1307
+ async almacenarArchivoEnDisco(Solicitud, UId) {
1308
+ const fs = require('fs');
1309
+ const trozos = [];
1310
+ let tamanioTotal = 0;
1311
+ let informacionDelArchivo = {};
1312
+
1313
+ await new Promise((resolve, reject) => {
1314
+ Solicitud.on('data', (trozo) => {
1315
+ trozos.push(trozo);
1316
+ tamanioTotal += trozo.length;
1317
+ });
1318
+
1319
+ Solicitud.on('end', resolve);
1320
+ Solicitud.on('error', reject);
1321
+ });
1322
+
1323
+ try {
1324
+ const buffer = Buffer.concat(trozos);
1325
+ const limite = Solicitud.headers['content-type'].split('; ')[1].split('=')[1];
1326
+ const limiteDelimitador = `--${limite}`;
1327
+ const partes = buffer.toString('latin1').split(limiteDelimitador).filter(Boolean);
1328
+
1329
+ for (const parte of partes) {
1330
+ if (parte.includes('filename=')) {
1331
+ const [headers, ...contentParts] = parte.split('\r\n\r\n');
1332
+ const contenidoBinario = Buffer.from(contentParts.join('\r\n\r\n'), 'latin1');
1333
+ const nombreDeArchivoMatch = headers.match(/filename="([^"]+)"/);
1334
+ const tipoDeContenidoMatch = headers.match(/Content-Type: ([^\r\n]+)/);
1335
+
1336
+ if (nombreDeArchivoMatch) {
1337
+ const nombreDeArchivo = Buffer.from(nombreDeArchivoMatch[1], 'latin1').toString('utf8');
1338
+ const tipoDeContenido = tipoDeContenidoMatch ? tipoDeContenidoMatch[1] : 'application/octet-stream';
1339
+ const rutaDeArchivo = `${this.directorioParaElAlmacenamientoDeArchivos()}/${UId}-${this.fechaConFormato()}-${nombreDeArchivo}`;
1340
+
1341
+ fs.writeFileSync(rutaDeArchivo, contenidoBinario);
1342
+
1343
+ informacionDelArchivo = {
1344
+ nombreDeArchivo,
1345
+ tipoDeContenido,
1346
+ tamanioTotal,
1347
+ rutaDeArchivo,
1348
+ };
1349
+ }
1350
+ }
1351
+ }
1352
+ } catch (error) {
1353
+ console.error('Error al guardar el archivo:', error);
1354
+ throw new ManejadorDeErrores(error.message, ManejadorDeErrores.obtenerNumeroDeLinea());
1355
+ }
1356
+ return informacionDelArchivo;
1357
+ }
1358
+
1359
+ async cargarArchivo(Solicitud, Etiquetas) {
1360
+ const Partes = Etiquetas.split('--');
1361
+ Etiquetas = Partes.slice(0, -1).join("--");
1362
+ let Resultado = undefined;
1363
+ try {
1364
+ Resultado = await this.obtenerDatosDelUsuario(Solicitud.headers.authorization);
1365
+ } catch (error) {
1366
+ console.error(error);
1367
+ }
1368
+ // Validación del token para el usuario y authorización
1369
+ if (Resultado) {
1370
+ const informacionDelArchivo = await this.almacenarArchivoEnDisco(Solicitud, Resultado['uid']);
1371
+ const Respuesta = await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_Adjuntos` (`AdjuntosId`, `Identificador`, `Modulo`, `Seccion`, `Nombre`,\
1372
+ `NombreOriginal`, `Ruta`, `Tipo`, `Tamanio`, `Etiqueta`, `LastUpdate`, `LastUser`)\
1373
+ VALUES (NULL, ?, ?, 'No aplica', ?, ?, ?, ?, ?, 'No aplica', NOW(4), ?)"
1374
+ , [Resultado['uid'], this.NombreCanonicoDelModulo, informacionDelArchivo.nombreDeArchivo, informacionDelArchivo.nombreDeArchivo
1375
+ , informacionDelArchivo.rutaDeArchivo, informacionDelArchivo.tipoDeContenido, informacionDelArchivo.tamanioTotal
1376
+ , Resultado['uid']]);
1377
+ informacionDelArchivo.insertId = Respuesta.insertId;
1378
+ informacionDelArchivo.Etiquetas = Etiquetas;
1379
+ await ejecutarConsulta("INSERT INTO `" + this.NombreDelRepositorioDeLaBaseDeDatos.slice(0, -3) + "`.`Archivos`\
1380
+ VALUES (?, ?, ?, ?, ?, NOW(4), ?)"
1381
+ , [Respuesta.insertId, Resultado.uid, informacionDelArchivo.rutaDeArchivo, informacionDelArchivo.nombreDeArchivo
1382
+ , Etiquetas, Resultado.uid]);
1383
+ return informacionDelArchivo;
1384
+ }
1385
+ return;
1386
+ }
1387
+
1388
+ archivoCSVAJSON(rutaArchivo) {
1389
+ const fs = require('fs');
1390
+ const path = require('path');
1391
+ return new Promise((resolve, reject) => {
1392
+ fs.readFile(path.resolve(rutaArchivo), 'utf8', (err, data) => {
1393
+ if (err) {
1394
+ return reject(err);
1395
+ }
1396
+ try {
1397
+ const lineas = data.trim().split('\n'); // Dividir en líneas
1398
+ const encabezados = lineas[0].split(','); // Extraer encabezados de la primera línea
1399
+ const resultados = lineas.slice(1).map((linea) => {
1400
+ const valores = linea.split(','); // Dividir cada línea en valores
1401
+ const objeto = {};
1402
+ encabezados.forEach((encabezado, index) => {
1403
+ objeto[encabezado.trim()] = valores[index]?.trim(); // Crear clave-valor
1404
+ });
1405
+ return objeto;
1406
+ });
1407
+ resolve(resultados);
1408
+ } catch (error) {
1409
+ reject(error);
1410
+ }
1411
+ });
1412
+ });
1413
+ }
1414
+
1415
+ jsonATabla(Datos) {
1416
+ if (!Array.isArray(Datos) || Datos.length === 0) {
1417
+ return 'El arreglo está vacío o no es válido.';
1418
+ }
1419
+ const columnas = Object.keys(Datos[0]);
1420
+ const anchos = columnas.map(columna => {
1421
+ return Math.max(
1422
+ columna.length,
1423
+ ...Datos.map(row => (row[columna] ? row[columna].toString().length : 0))
1424
+ );
1425
+ });
1426
+ const formatearFila = (fila) => '| ' + fila.map((valor, index) => (valor || '').toString().padEnd(anchos[index])).join(' | ') + ' |';
1427
+ const separador = '+-' + anchos.map(ancho => '-'.repeat(ancho)).join('-+-') + '-+';
1428
+ const encabezado = formatearFila(columnas);
1429
+ const filas = Datos.map(row => formatearFila(columnas.map(col => row[col] || '')));
1430
+ return [separador, encabezado, separador, ...filas, separador].join('\n');
1431
+ }
1432
+
1433
+ // async agregarCodigoQR(doc, url, opciones = {}) {
1434
+ // const { x = 0, y = 0, size = 100 } = opciones;
1435
+
1436
+
1437
+
1438
+ // const urlQR = `https://qrcode.tec-it.com/API/QRCode?data=${encodeURIComponent(url)}&backcolor=%23ffffff&size=small&quietzone=1&errorcorrection=H`;
1439
+ // doc.image(urlQR, x, y, { width: size, height: size });
1440
+ // }
1441
+
1442
+ agregarMarcaDeAgua(doc, texto = 'Borrador', opciones = {}) {
1443
+ const {
1444
+ color = '#CCCCCC',
1445
+ opacity = 0.3,
1446
+ } = opciones;
1447
+
1448
+ const { width, height } = doc.page; // Tamaño de la página
1449
+
1450
+ doc.save(); // Guardar el estado original de la página
1451
+
1452
+ // Calcular la posición y el ángulo de la marca de agua
1453
+ doc
1454
+ .font('Times-Roman', 220)
1455
+ .fillColor(color)
1456
+ .opacity(opacity)
1457
+ .rotate(-55, { origin: [width / 2, height / 2] }) // Rotar el texto en diagonal
1458
+ .text(
1459
+ texto,
1460
+ -width * 0.2, // Ajustar el desplazamiento horizontal
1461
+ height * 0.4, // Ajustar el desplazamiento vertical
1462
+ {
1463
+ align: 'center',
1464
+ valign: 'center',
1465
+ width: width * 1.5, // Asegurar que el texto abarca toda la diagonal
1466
+ }
1467
+ );
1468
+
1469
+ doc.restore(); // Restaurar el estado original de la página
1470
+ }
1471
+
1472
+ async generarObjetoInfoDeUnReportePDF() {
1473
+
1474
+ // Título: UTN-1-1-2024
1475
+ // Autor: Apellido Apellido Nombre + cédula del funcionario
1476
+ // Asunto: Boleta de Vacaciones
1477
+ // Palabras Clave: Hash documento: asfsadffsdafsdfafggef4455
1478
+
1479
+ // Agregarle al doc un QR con el enlace a SIGU y códiigo de verificación
1480
+
1481
+ const UUID = await ejecutarConsulta("SELECT UUID() AS `Dato`");
1482
+ const PalabrasClave = {
1483
+ "Módulo": this.NombreCanonicoDelModulo,
1484
+ "UUID": UUID[0]['Dato']
1485
+ };
1486
+ return {
1487
+ Title: 'Nombre del reporte, como por ejemplo: Boleta de Vacaciones',
1488
+ Author: 'Universidad Técnica Nacional',
1489
+ Subject: 'Reporte PDF',
1490
+ Keywords: JSON.stringify(PalabrasClave),
1491
+ Creator: 'SIGU',
1492
+ Producer: 'SIGU'
1493
+ };
1494
+ }
1495
+
1496
+ agregarTablaElegante(doc, datos, opciones = {}) {
1497
+ const { x = 50, y = 50, columnWidth = 100, rowHeight = 20, headerHeight = 25, fontSize = 10 } = opciones;
1498
+
1499
+ // Configuración de fuentes
1500
+ doc.fontSize(fontSize);
1501
+
1502
+ // Obtener las claves del primer objeto como encabezados
1503
+ const encabezados = Object.keys(datos[0]);
1504
+
1505
+ // Dibujar los encabezados
1506
+ encabezados.forEach((encabezado, i) => {
1507
+ const posX = x + i * columnWidth;
1508
+ doc
1509
+ .rect(posX, y, columnWidth, headerHeight)
1510
+ .fillAndStroke('#d3d3d3', '#000')
1511
+ .fillColor('#000')
1512
+ .text(encabezado, posX + 5, y + 5, { width: columnWidth - 10, align: 'left' });
1513
+ });
1514
+
1515
+ // Dibujar las filas
1516
+ datos.forEach((fila, filaIndex) => {
1517
+ const filaY = y + headerHeight + filaIndex * rowHeight;
1518
+ encabezados.forEach((columna, colIndex) => {
1519
+ const posX = x + colIndex * columnWidth;
1520
+ const texto = fila[columna] !== undefined ? fila[columna].toString() : '';
1521
+ doc
1522
+ .rect(posX, filaY, columnWidth, rowHeight)
1523
+ .stroke()
1524
+ .fillColor('#000')
1525
+ .text(texto, posX + 5, filaY + 5, { width: columnWidth - 10, align: 'left' });
1526
+ });
1527
+ });
1528
+
1529
+ return doc;
1530
+ }
1531
+
1532
+ async reportePDFDeEjemplo(Respuesta) {
1533
+
1534
+ Respuesta.setHeader('Content-Type', 'application/pdf');
1535
+ Respuesta.setHeader('Content-Disposition', 'inline; filename="reporte.pdf"');
1536
+ const PDFDocument = require('pdfkit');
1537
+
1538
+ const opciones = {
1539
+ font: 'Courier',
1540
+ size: 'LETTER',
1541
+ info: await this.generarObjetoInfoDeUnReportePDF()
1542
+ };
1543
+ var doc = new PDFDocument(opciones);
1544
+ doc.pipe(Respuesta);
1545
+
1546
+ this.agregarMarcaDeAgua(doc, 'Borrador', {
1547
+ fontSize: 80,
1548
+ opacity: 0.2,
1549
+ color: '#FF0000',
1550
+ });
1551
+
1552
+ doc.fontSize(25).text('Here is some vector graphics...', 100, 80);
1553
+
1554
+ doc.save()
1555
+ .moveTo(100, 150)
1556
+ .lineTo(100, 250)
1557
+ .lineTo(200, 250)
1558
+ .fill('#FF3300');
1559
+
1560
+ doc.circle(280, 200, 50).fill('#6600FF');
1561
+
1562
+ doc.scale(0.6)
1563
+ .translate(470, 130)
1564
+ .path('M 250,75 L 323,301 131,161 369,161 177,301 z')
1565
+ .fill('red', 'even-odd')
1566
+ .restore();
1567
+
1568
+ doc.text('And here is some wrapped text...', 100, 300)
1569
+ .font('Times-Roman', 13)
1570
+ .moveDown()
1571
+ .text("lorem", {
1572
+ width: 412,
1573
+ align: 'justify',
1574
+ indent: 30,
1575
+ columns: 2,
1576
+ height: 300,
1577
+ ellipsis: true
1578
+ });
1579
+
1580
+ // Datos de ejemplo
1581
+ const datos = [
1582
+ { Nombre: 'Juan', Edad: 28, Ciudad: 'San José', LugarDeTrabajo: 'UTN' },
1583
+ { Nombre: 'Ana', Edad: 34 },
1584
+ { Nombre: 'Luis', Edad: 25, Ciudad: 'Alajuela' },
1585
+ ];
1586
+ this.agregarTablaElegante(doc, datos, { x: 0, y: 400, columnWidth: 150, fontSize: 12 });
1587
+ // await this.agregarCodigoQR(doc, 'https://www.utn.ac.cr', { x: doc.page.width - 150, y: doc.page.height - 150, size: 100 });
1588
+ doc.end();
1589
+ }
1590
+
1591
+ async verificarToken(Token) {
1592
+ let Resultado = undefined;
1593
+ try {
1594
+ Resultado = await this.obtenerDatosDelUsuario(`Bearer ${Token}`);
1595
+ } catch (error) {
1596
+ console.error(error);
1597
+ }
1598
+ return Resultado;
1599
+ }
1600
+
1601
+ async crearTareaProgramada(Tarea) {
1602
+ const os = require('node:os');
1603
+ return await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_ModulosTareasProgramadas` VALUES\
1604
+ (?, ?, 'Ejecutada', NOW(4), ?) ON DUPLICATE KEY UPDATE `NombreDelEquipo` = ?"
1605
+ , [this.NombreDelRepositorioDelBackend, Tarea.name, os.hostname(), os.hostname()]);
1606
+ }
1607
+
1608
+ async pseudoEjecutarTareaProgramada(Tarea) {
1609
+ const os = require('node:os');
1610
+ const Resultado = await ejecutarConsultaSIGU("UPDATE `SIGU`.`SIGU_ModulosTareasProgramadas` SET `Estado` = 'Procesando'\
1611
+ , `NombreDelEquipo` = ?, `FechaYHoraDeLaUltimaEjecucion` = NOW(4)\
1612
+ WHERE `Repositorio` = ? AND `TareaProgramada` = ? AND `Estado` IN ('Ejecutada', 'Cancelada', 'Fallida')"
1613
+ , [os.hostname(), this.NombreDelRepositorioDelBackend, Tarea]);
1614
+ return Resultado['affectedRows'];
1615
+ }
1616
+
1617
+ async finalizarTareaProgramada(Tarea) {
1618
+ const os = require('node:os');
1619
+ const Resultado = await ejecutarConsultaSIGU("UPDATE `SIGU`.`SIGU_ModulosTareasProgramadas` SET `Estado` = 'Ejecutada'\
1620
+ , `NombreDelEquipo` = ?, `FechaYHoraDeLaUltimaEjecucion` = NOW(4)\
1621
+ WHERE `Repositorio` = ? AND `TareaProgramada` = ? AND `Estado` IN ('Procesando')"
1622
+ , [os.hostname(), this.NombreDelRepositorioDelBackend, Tarea]);
1623
+ return Resultado['affectedRows'];
1624
+ }
1625
+
1626
+ async ejecutarEnHoraEspecifica(hora, minuto, segundo, callback) {
1627
+ while (true) {
1628
+ try {
1629
+ await this.crearTareaProgramada(callback);
1630
+ break;
1631
+ } catch (error) {
1632
+ console.error('Error al ejecutar crearTareaProgramada:', error);
1633
+ console.log('Reintentando en 5 segundos...');
1634
+ await new Promise(resolve => setTimeout(resolve, 5000));
1635
+ }
1636
+ }
1637
+
1638
+ function programarEjecucion() {
1639
+ const ahora = new Date();
1640
+ const proximaEjecucion = new Date(ahora);
1641
+ proximaEjecucion.setHours(hora, minuto, segundo, 0);
1642
+ let tiempoEspera = proximaEjecucion - ahora;
1643
+ if (tiempoEspera < 0) {
1644
+ proximaEjecucion.setDate(proximaEjecucion.getDate() + 1);
1645
+ tiempoEspera = proximaEjecucion - ahora;
1646
+ }
1647
+ console.log(`Se ha programado a '${callback.name}' para ejecución a las ${proximaEjecucion.toLocaleTimeString()}`);
1648
+
1649
+ setTimeout(() => {
1650
+ callback();
1651
+ programarEjecucion();
1652
+ }, tiempoEspera);
1653
+ }
1654
+
1655
+ programarEjecucion();
1656
+ }
1657
+
1658
+ NombresParalocalhost() {
1659
+ return ["localhost", "::", "127.0.0.1", "::1"];
1660
+ }
1661
+
1662
+ async crearToken(Identificador) {
1663
+ let Token = undefined;
1664
+ if (this.NombresParalocalhost().includes(process.env.HOST) && (typeof process.env.DB_HOST_SIGU === "undefined")) {
1665
+ const jwt = require('jsonwebtoken');
1666
+ Token = await jwt.sign({ uid: Identificador }, await this.palabraSecretaParaTokens(), { expiresIn: '10h' });
1667
+ await ejecutarConsultaSIGU("DELETE FROM `SIGU`.`SIGU_Sesiones` WHERE `Identificador` = ?", [Identificador]);
1668
+ await ejecutarConsultaSIGU("INSERT INTO `SIGU`.`SIGU_Sesiones` VALUES (?, 'Backend', ?, NOW(4), USER())", [Identificador, Token]);
1669
+ }
1670
+ const fs = require('fs');
1671
+ const ExpresionRegular = new RegExp(/[A-Za-z0-9_-]{30,}\.[A-Za-z0-9_-]{30,}\.[A-Za-z0-9_-]{30,}/, 'g');
1672
+ // index.rest
1673
+ let ArchivoREST = process.cwd() + '/index.rest';
1674
+ let contenido = fs.readFileSync(ArchivoREST, 'utf-8');
1675
+ let contenidoActualizado = contenido.replace(ExpresionRegular, Token);
1676
+ fs.writeFileSync(ArchivoREST, contenidoActualizado);
1677
+ // Módulo.rest
1678
+ ArchivoREST = process.cwd() + '/' + this.NombreCanonicoDelModulo + '.rest';
1679
+ contenido = fs.readFileSync(ArchivoREST, 'utf-8');
1680
+ contenidoActualizado = contenido.replace(ExpresionRegular, Token);
1681
+ fs.writeFileSync(ArchivoREST, contenidoActualizado);
1682
+ // datos-globales.service.ts
1683
+ try {
1684
+ const CWD = process.cwd();
1685
+ process.chdir('..');
1686
+ ArchivoREST = process.cwd() + '/' + this.NombreDelRepositorioDelFrontend + '/src/app/datos-globales.service.ts';
1687
+ process.chdir(CWD);
1688
+ contenido = fs.readFileSync(ArchivoREST, 'utf-8');
1689
+ contenidoActualizado = contenido.replace(ExpresionRegular, Token);
1690
+ fs.writeFileSync(ArchivoREST, contenidoActualizado);
1691
+ } catch (error) {
1692
+ console.warn("No fue posible actualizar el archivo datos-globales.service.ts del front: ", error);
1693
+ }
1694
+ return Token;
1695
+ }
1696
+
1697
+ async listarArchivos(Datos) {
1698
+ const Partes = Datos.Etiquetas.split('--');
1699
+ const Etiquetas = Partes.slice(0, -1).join("--");
1700
+ const partes = Datos.Etiquetas.split('--');
1701
+ const ultimaParte = partes[partes.length - 1].split('=')[1];
1702
+ if (ultimaParte === 'Usuario') {
1703
+ let Resultado = undefined;
1704
+ try {
1705
+ Resultado = await this.obtenerDatosDelUsuario(Datos.Token);
1706
+ if (!Resultado) {
1707
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorVerificacionDeToken(), ManejadorDeErrores.obtenerNumeroDeLinea());
1708
+ }
1709
+ } catch (error) {
1710
+ console.log(error);
1711
+ return;
1712
+ }
1713
+ return await ejecutarConsulta("SELECT `ArchivoId`, `Identificador`, `Ruta`, CONCAT(`Nombre`, ' (', DATE_FORMAT(`LastUpdate`, '%Y-%M-%d %H:%i'), ')') AS `Nombre`, `Etiquetas`\
1714
+ FROM `" + this.NombreDelRepositorioDeLaBaseDeDatos.slice(0, -3) + "`.`Archivos`\
1715
+ WHERE `Identificador` = ? AND `Etiquetas` = ?"
1716
+ , [Resultado.uid, Etiquetas]);
1717
+ }
1718
+ if (ultimaParte === 'Servicio') {
1719
+ return await ejecutarConsulta("SELECT `ArchivoId`, `Identificador`, `Ruta`, CONCAT(`Nombre`, ' (', DATE_FORMAT(`LastUpdate`, '%Y-%M-%d %H:%i'), ')') AS `Nombre`, `Etiquetas`\
1720
+ FROM `" + this.NombreDelRepositorioDeLaBaseDeDatos.slice(0, -3) + "`.`Archivos`\
1721
+ WHERE `Etiquetas` = ?"
1722
+ , [Etiquetas]);
1723
+ }
1724
+ if (ultimaParte === 'Proceso') {
1725
+ return await ejecutarConsulta("SELECT `ArchivoId`, `Identificador`, `Ruta`, CONCAT(`Nombre`, ' (', DATE_FORMAT(`LastUpdate`, '%Y-%M-%d %H:%i'), ')') AS `Nombre`, `Etiquetas`\
1726
+ FROM `" + this.NombreDelRepositorioDeLaBaseDeDatos.slice(0, -3) + "`.`Archivos`\
1727
+ WHERE `Etiquetas` = ?"
1728
+ , [Etiquetas]);
1729
+ }
1730
+ if (typeof ultimaParte === "number") {
1731
+ if (this.validarTokenV2(Datos.Token, ultimaParte)) {
1732
+ return await ejecutarConsulta("SELECT `ArchivoId`, `Identificador`, `Ruta`, CONCAT(`Nombre`, ' (', DATE_FORMAT(`LastUpdate`, '%Y-%M-%d %H:%i'), ')') AS `Nombre`, `Etiquetas`\
1733
+ FROM `" + this.NombreDelRepositorioDeLaBaseDeDatos.slice(0, -3) + "`.`Archivos`\
1734
+ WHERE `Etiquetas` = ?"
1735
+ , [Etiquetas]);
1736
+ }
1737
+ }
1738
+ }
1739
+
1740
+ async borrarArchivo(Datos) {
1741
+ let Resultado = undefined;
1742
+ try {
1743
+ Resultado = await this.obtenerDatosDelUsuario(Datos.Token);
1744
+ if (!Resultado) {
1745
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorVerificacionDeToken(), ManejadorDeErrores.obtenerNumeroDeLinea());
1746
+ }
1747
+ } catch (error) {
1748
+ console.log(error);
1749
+ return;
1750
+ }
1751
+ const fs = require('fs');
1752
+ const Archivo = await ejecutarConsulta("SELECT `Ruta`\
1753
+ FROM `" + this.NombreDelRepositorioDeLaBaseDeDatos.slice(0, -3) + "`.`Archivos`\
1754
+ WHERE `Identificador` = ? AND `ArchivoId` = ?"
1755
+ , [Resultado.uid, Datos.ArchivoId]);
1756
+ fs.unlinkSync(Archivo[0]['Ruta']);
1757
+ await ejecutarConsulta("DELETE FROM `" + this.NombreDelRepositorioDeLaBaseDeDatos.slice(0, -3) + "`.`Archivos`\
1758
+ WHERE `Identificador` = ? AND `ArchivoId` = ?"
1759
+ , [Resultado.uid, Datos.ArchivoId]);
1760
+ await ejecutarConsultaSIGU("DELETE FROM `SIGU`.`SIGU_Adjuntos`\
1761
+ WHERE `Identificador` = ? AND `AdjuntosId` = ?"
1762
+ , [Resultado.uid, Datos.ArchivoId]);
1763
+ return;
1764
+ }
1765
+
1766
+ async descargarArchivo(Respuesta, Datos) {
1767
+ let RutaDelArchivo = undefined;
1768
+ const ArchivoId = Datos.ArchivoId.split('--')[0];
1769
+ const partes = Datos.ArchivoId.split('--');
1770
+ const ultimaParte = partes[partes.length - 1].split('=')[1];
1771
+ if (ultimaParte === 'Usuario') {
1772
+ let Resultado = undefined;
1773
+ try {
1774
+ Resultado = await this.obtenerDatosDelUsuario(Datos.Token);
1775
+ if (!Resultado) {
1776
+ throw new ManejadorDeErrores(ManejadorDeErrores.mensajeDeErrorVerificacionDeToken(), ManejadorDeErrores.obtenerNumeroDeLinea());
1777
+ }
1778
+ } catch (error) {
1779
+ console.log(error);
1780
+ return;
1781
+ }
1782
+ RutaDelArchivo = await ejecutarConsulta("SELECT `Ruta`\
1783
+ FROM `" + this.NombreDelRepositorioDeLaBaseDeDatos.slice(0, -3) + "`.`Archivos`\
1784
+ WHERE `Identificador` = ? AND `ArchivoId` = ?"
1785
+ , [Resultado.uid, ArchivoId]);
1786
+ }
1787
+ if (ultimaParte === 'Servicio') {
1788
+ RutaDelArchivo = await ejecutarConsulta("SELECT `Ruta`\
1789
+ FROM `" + this.NombreDelRepositorioDeLaBaseDeDatos.slice(0, -3) + "`.`Archivos`\
1790
+ WHERE `ArchivoId` = ?"
1791
+ , [ArchivoId]);
1792
+ }
1793
+ if (ultimaParte === 'Proceso') {
1794
+ RutaDelArchivo = await ejecutarConsulta("SELECT `Ruta`\
1795
+ FROM `" + this.NombreDelRepositorioDeLaBaseDeDatos.slice(0, -3) + "`.`Archivos`\
1796
+ WHERE `ArchivoId` = ?"
1797
+ , [ArchivoId]);
1798
+ }
1799
+ if (typeof ultimaParte === "number") {
1800
+ if (this.validarTokenV2(Datos.Token, ultimaParte)) {
1801
+ RutaDelArchivo = await ejecutarConsulta("SELECT `Ruta`\
1802
+ FROM `" + this.NombreDelRepositorioDeLaBaseDeDatos.slice(0, -3) + "`.`Archivos`\
1803
+ WHERE `ArchivoId` = ?"
1804
+ , [ArchivoId]);
1805
+ }
1806
+ }
1807
+ Respuesta.download(RutaDelArchivo[0]['Ruta']);
1808
+ return;
1809
+ }
1810
+
1811
+ async configurarFrontend() {
1812
+ return {
1813
+ "Modulo": this.NombreCanonicoDelModulo,
1814
+ "Titulo": this.NombreDelModulo,
1815
+ "Version": this.Version,
1816
+ "Descripcion": this.DescripcionDelModulo,
1817
+ "Detalle": this.DetalleDelModulo
1818
+ };
1819
+ // if (this.NombresParalocalhost().includes(process.env.HOST) && (typeof process.env.DB_HOST_SIGU === "undefined")) {
1820
+ // try {
1821
+ // const fs = require('fs');
1822
+ // const Archivo;
1823
+ // const CWD = process.cwd();
1824
+ // let contenido;
1825
+ // let contenidoActualizado;
1826
+ // // contenedor-principal.component.html
1827
+ // process.chdir('..');
1828
+ // Archivo = process.cwd() + '/' + this.NombreDelRepositorioDelFrontend + '/src/app/Paginas/contenedor-principal/contenedor-principal.component.html';
1829
+ // contenido = fs.readFileSync(Archivo, 'utf-8');
1830
+ // contenidoActualizado = contenido.replace('DESCRIPCION_DEL_PROYECTO', this.DescripcionDelModulo);
1831
+ // fs.writeFileSync(Archivo, contenidoActualizado);
1832
+ // contenido = fs.readFileSync(Archivo, 'utf-8');
1833
+ // contenidoActualizado = contenido.replace('DETALLE_DEL_PROYECTO', this.DetalleDelModulo);
1834
+ // fs.writeFileSync(Archivo, contenidoActualizado);
1835
+ // process.chdir(CWD);
1836
+
1837
+ // // contenedor-componentes.component.html
1838
+ // process.chdir('..');
1839
+ // Archivo = process.cwd() + '/' + this.NombreDelRepositorioDelFrontend + '/src/app/Paginas/Nucleo/contenedor-componentes/contenedor-componentes.component.html';
1840
+ // contenido = fs.readFileSync(Archivo, 'utf-8');
1841
+ // contenidoActualizado = contenido.replace('NOMBRE_DEL_PROYECTO', this.NombreDelModulo);
1842
+ // fs.writeFileSync(Archivo, contenidoActualizado);
1843
+ // contenido = fs.readFileSync(Archivo, 'utf-8');
1844
+ // contenidoActualizado = contenido.replace('MODULO', this.NombreCanonicoDelModulo);
1845
+ // fs.writeFileSync(Archivo, contenidoActualizado);
1846
+ // contenido = fs.readFileSync(Archivo, 'utf-8');
1847
+ // contenidoActualizado = contenido.replace('VERSION', '1.0.0');
1848
+ // fs.writeFileSync(Archivo, contenidoActualizado);
1849
+ // process.chdir(CWD);
1850
+
1851
+ // } catch (error) {
1852
+ // console.warn("No fue posible actualizar el archivo contenedor-principal.component.html del front: ", error);
1853
+ // }
1854
+ // }
1855
+ // return;
1856
+ }
1857
+
1858
+ async DatosPersonalesDeUnaPersona(Identificador) {
1859
+ const Resultado = {};
1860
+ const DatosDeLaPersona = await ejecutarConsultaSIGU("SELECT `Identificacion`, `Nombre`, `PrimerApellido`,\
1861
+ `SegundoApellido`, (SELECT `CorreoElectronico` FROM `SIGU`.`SIGU_CorreosPersona` WHERE `Identificador` = ? AND `Principal` = TRUE) AS `CorreoElectronicoPrincipal`\
1862
+ FROM `SIGU`.`SIGU_Personas` WHERE `Identificador` = ?", [Identificador, Identificador]);
1863
+ Resultado.Identificador = Identificador;
1864
+ Resultado.Identificacion = DatosDeLaPersona[0]['Identificacion'];
1865
+ Resultado.Nombre = DatosDeLaPersona[0]['Nombre'];
1866
+ Resultado.PrimerApellido = DatosDeLaPersona[0]['PrimerApellido'];
1867
+ Resultado.SegundoApellido = DatosDeLaPersona[0]['SegundoApellido'];
1868
+ Resultado.CorreoElectronicoPrincipal = DatosDeLaPersona[0]['CorreoElectronicoPrincipal'];
1869
+ return Resultado;
1870
+ }
1871
+
1872
+ async ejecucionDiferida(callback) {
1873
+ while (true) {
1874
+ try {
1875
+ await callback();
1876
+ break;
1877
+ } catch (error) {
1878
+ console.error(`Error en la función "${callback.name}": `, error.message);
1879
+ console.log('Reintentando en 5 segundos...');
1880
+ await new Promise(resolve => setTimeout(resolve, 5000));
1881
+ }
1882
+ }
1883
+ }
1884
+
1885
+ async obtenerEnlaceDelModuloPadre() {
1886
+ const Ruta = await ejecutarConsultaSIGU("SELECT CONCAT('modulos/', `MenuId`) AS `Ruta` FROM `SIGU`.`SIGU_Menu`\
1887
+ WHERE `MenuId` = (SELECT `Padre` FROM `SIGU`.`SIGU_Menu` WHERE `Nombre` = ?)"
1888
+ , [this.NombreCanonicoDelModulo]);
1889
+ return await this.obtenerEnlaceDePortal() + "/" + Ruta[0]['Ruta'];
1890
+ }
1891
+
1892
+ async obtenerEnlaceDePortal() {
1893
+ return this.EnlaceDePortal;
1894
+ }
1895
+
1896
+ async obtenerEnlaceDePerfil() {
1897
+ return this.EnlaceDePerfil;
1898
+ }
1899
+ }
1900
+
1901
+ module.exports = new Miscelaneo();