From 90b82233850cb6b59795bb291acb3d8583beae4f Mon Sep 17 00:00:00 2001 From: naielv <109038805+naielv@users.noreply.github.com> Date: Thu, 25 Dec 2025 19:15:28 +0100 Subject: [PATCH] updated --- src/app_modules.js | 57 +++++++++++++++++++++++++++++++----------- src/db.js | 32 +++++++++++++++++++----- src/page/aulas.js | 2 ++ src/page/avisos.js | 1 + src/page/comedor.js | 1 + src/page/login.js | 7 ++++++ src/page/materiales.js | 1 + src/page/notas.js | 1 + src/page/pagos.js | 1 + src/page/personas.js | 1 + 10 files changed, 84 insertions(+), 20 deletions(-) diff --git a/src/app_modules.js b/src/app_modules.js index 7bcaae9..d465a34 100644 --- a/src/app_modules.js +++ b/src/app_modules.js @@ -554,15 +554,14 @@ const SC_actions = { }, ], }; -// Listado precargado de personas: function TS_decrypt(input, secret, callback, table, id) { - // Accept objects or plaintext strings. Also support legacy RSA{...} AES-encrypted entries. + // Accept objects or plaintext strings. Support AES-encrypted entries wrapped as RSA{...}. if (typeof input !== "string") { try { callback(input, false); } catch (e) { console.error(e); } return; } - // Legacy encrypted format: RSA{...} + // Encrypted format marker: RSA{} where is CryptoJS AES output if (input.startsWith("RSA{") && input.endsWith("}") && typeof CryptoJS !== 'undefined') { try { var data = input.slice(4, -1); @@ -571,7 +570,6 @@ function TS_decrypt(input, secret, callback, table, id) { try { decryptedUtf8 = words.toString(CryptoJS.enc.Utf8); } catch (utfErr) { - // Malformed UTF-8 — try Latin1 fallback try { decryptedUtf8 = words.toString(CryptoJS.enc.Latin1); } catch (latinErr) { @@ -583,9 +581,9 @@ function TS_decrypt(input, secret, callback, table, id) { var parsed = null; try { parsed = JSON.parse(decryptedUtf8); } catch (pe) { parsed = decryptedUtf8; } try { callback(parsed, true); } catch (e) { console.error(e); } - // Migrate to plaintext in DB if table/id provided - if (table && id && window.DB && DB.put && typeof parsed !== 'string') { - DB.put(table, id, parsed).catch(() => {}); + // Keep encrypted at-rest: if table/id provided, ensure DB stores encrypted payload (input) + if (table && id && window.DB && DB.put) { + DB.put(table, id, input).catch(() => {}); } return; } catch (e) { @@ -595,12 +593,14 @@ function TS_decrypt(input, secret, callback, table, id) { } } - // Try to parse JSON strings and migrate to object + // Plain JSON stored as text -> parse and return, then re-encrypt in DB for at-rest protection try { var parsed = JSON.parse(input); try { callback(parsed, false); } catch (e) { console.error(e); } - if (table && id && window.DB && DB.put) { - DB.put(table, id, parsed).catch(() => {}); + if (table && id && window.DB && DB.put && typeof SECRET !== 'undefined') { + TS_encrypt(parsed, SECRET, function (enc) { + DB.put(table, id, enc).catch(() => {}); + }); } } catch (e) { // Not JSON, return raw string @@ -608,10 +608,27 @@ function TS_decrypt(input, secret, callback, table, id) { } } function TS_encrypt(input, secret, callback, mode = "RSA") { - // Encryption removed: store plaintext objects directly - try { callback(input); } catch (e) { console.error(e); } + // Encrypt given value for at-rest storage using CryptoJS AES. + // Always return string of form RSA{} via callback. + try { + if (typeof CryptoJS === 'undefined') { + // CryptoJS not available — return plaintext + try { callback(input); } catch (e) { console.error(e); } + return; + } + var payload = input; + if (typeof input !== 'string') { + try { payload = JSON.stringify(input); } catch (e) { payload = String(input); } + } + var encrypted = CryptoJS.AES.encrypt(payload, secret).toString(); + var out = 'RSA{' + encrypted + '}'; + try { callback(out); } catch (e) { console.error(e); } + } catch (e) { + console.error('TS_encrypt: encryption failed', e); + try { callback(input); } catch (err) { console.error(err); } + } } -// Populate SC_Personas from DB (PouchDB) +// Listado precargado de personas: DB.map('personas', (data, key) => { function add_row(data, key) { if (data != null) { @@ -771,7 +788,7 @@ function TS_IndexElement( var tablebody_EL = document.getElementById(tablebody); var rows = {}; config.forEach((key) => { - tablehead_EL.innerHTML += `${key.label}`; + tablehead_EL.innerHTML += `${key.label || ""}`; }); // Add search functionality const searchKeyEl = document.getElementById(searchKeyInput); @@ -874,6 +891,14 @@ function TS_IndexElement( } config.forEach((key) => { switch (key.type) { + case "_encrypted": { + const tdEncrypted = document.createElement("td"); + tdEncrypted.innerText = data["_encrypted__"] + ? "🔒" + : ""; + new_tr.appendChild(tdEncrypted); + break; + } case "raw": case "text": { const tdRaw = document.createElement("td"); @@ -1170,9 +1195,11 @@ function TS_IndexElement( } if (typeof data == "string") { TS_decrypt(data, SECRET, (data, wasEncrypted) => { + data["_encrypted__"] = wasEncrypted; add_row(data, key); }, ref, key); } else { + data["_encrypted__"] = false; add_row(data, key); } }); @@ -1191,9 +1218,11 @@ function TS_IndexElement( } if (typeof data == "string") { TS_decrypt(data, SECRET, (data, wasEncrypted) => { + data["_encrypted__"] = wasEncrypted; add_row(data, key); }, undefined, undefined); } else { + data["_encrypted__"] = false; add_row(data, key); } }); diff --git a/src/db.js b/src/db.js index 0041b37..36c5605 100644 --- a/src/db.js +++ b/src/db.js @@ -5,7 +5,6 @@ var DB = (function () { let local = null; - let secret = null; let remote = null; let changes = null; let repPush = null; @@ -31,9 +30,15 @@ var DB = (function () { } function init(opts) { - // opts: { secret, remoteServer, username, password, dbname } - secret = opts.secret || ''; + // opts: { remoteServer, username, password, dbname } const localName = 'telesec'; + // Allow passing encryption secret via opts + try { + if (opts && opts.secret) { + SECRET = opts.secret; + try { localStorage.setItem('TELESEC_SECRET', SECRET); } catch (e) {} + } + } catch (e) {} local = new PouchDB(localName); if (opts.remoteServer) { @@ -109,7 +114,21 @@ var DB = (function () { return; } const doc = existing || { _id: _id }; - doc.data = data; + // If TS_encrypt is available and a SECRET is configured, encrypt non-encrypted payloads + var toStore = data; + try { + var isEncryptedString = (typeof data === 'string' && data.startsWith('RSA{') && data.endsWith('}')); + if (!isEncryptedString && typeof TS_encrypt === 'function' && typeof SECRET !== 'undefined' && SECRET) { + toStore = await new Promise((resolve) => { + try { + TS_encrypt(data, SECRET, function (enc) { + resolve(enc); + }); + } catch (e) { resolve(data); } + }); + } + } catch (e) { toStore = data; } + doc.data = toStore; doc.table = table; doc.ts = new Date().toISOString(); if (existing) doc._rev = existing._rev; @@ -234,9 +253,10 @@ window.DB = DB; const username = localStorage.getItem('TELESEC_COUCH_USER') || ''; const password = localStorage.getItem('TELESEC_COUCH_PASS') || ''; const dbname = localStorage.getItem('TELESEC_COUCH_DBNAME') || undefined; - const secret = localStorage.getItem('TELESEC_secret') || ''; + // Load saved secret into global SECRET for encryption/decryption + try { SECRET = localStorage.getItem('TELESEC_SECRET') || ''; } catch (e) { SECRET = ''; } // Call init but don't await; DB functions are safe-guarded with ensureLocal() - DB.init({ secret, remoteServer, username, password, dbname }).catch((e) => { + DB.init({ remoteServer, username, password, dbname }).catch((e) => { console.warn('DB.autoInit error', e); }); } catch (e) { diff --git a/src/page/aulas.js b/src/page/aulas.js index 2f050ec..e71dffb 100644 --- a/src/page/aulas.js +++ b/src/page/aulas.js @@ -134,6 +134,7 @@ PAGES.aulas = { TS_IndexElement( "aulas,solicitudes", [ + {"type": "_encrypted"}, { key: "Solicitante", type: "persona", @@ -243,6 +244,7 @@ PAGES.aulas = { TS_IndexElement( "aulas,informes", [ + {"type": "_encrypted"}, { key: "Autor", type: "persona", diff --git a/src/page/avisos.js b/src/page/avisos.js index 1e76163..69dd705 100644 --- a/src/page/avisos.js +++ b/src/page/avisos.js @@ -173,6 +173,7 @@ PAGES.avisos = { TS_IndexElement( "avisos", [ + {"type": "_encrypted"}, { key: "Origen", type: "persona", diff --git a/src/page/comedor.js b/src/page/comedor.js index ec62209..2738681 100644 --- a/src/page/comedor.js +++ b/src/page/comedor.js @@ -87,6 +87,7 @@ PAGES.comedor = { TS_IndexElement( "comedor", [ + {"type": "_encrypted"}, { key: "Fecha", type: "raw", diff --git a/src/page/login.js b/src/page/login.js index 8637438..732cec0 100644 --- a/src/page/login.js +++ b/src/page/login.js @@ -7,6 +7,7 @@ PAGES.login = { var field_couch_dbname = safeuuid(); var field_couch_user = safeuuid(); var field_couch_pass = safeuuid(); + var field_secret = safeuuid(); var btn_save = safeuuid(); container.innerHTML = `

Configuración del servidor CouchDB

@@ -23,6 +24,9 @@ PAGES.login = { +

Después de guardar, el navegador intentará sincronizar en segundo plano con el servidor.

@@ -32,10 +36,13 @@ PAGES.login = { var dbname = document.getElementById(field_couch_dbname).value.trim(); var user = document.getElementById(field_couch_user).value.trim(); var pass = document.getElementById(field_couch_pass).value; + var secret = document.getElementById(field_secret).value || ''; localStorage.setItem('TELESEC_COUCH_URL', "https://" + url); localStorage.setItem('TELESEC_COUCH_DBNAME', dbname); localStorage.setItem('TELESEC_COUCH_USER', user); localStorage.setItem('TELESEC_COUCH_PASS', pass); + localStorage.setItem('TELESEC_SECRET', secret); + SECRET = secret; try { DB.init({ secret: SECRET, remoteServer: "https://" + url, username: user, password: pass, dbname: dbname || undefined }); toastr.success('Iniciando sincronización con CouchDB'); diff --git a/src/page/materiales.js b/src/page/materiales.js index f5e4bec..f79450d 100644 --- a/src/page/materiales.js +++ b/src/page/materiales.js @@ -136,6 +136,7 @@ PAGES.materiales = { `; const config = [ + {"type": "_encrypted"}, { key: "Revision", label: "Ult. Revisión", type: "fecha-diff", default: "" }, { key: "Nombre", label: "Nombre", type: "text", default: "" }, { key: "Ubicacion", label: "Ubicación", type: "text", default: "--" }, diff --git a/src/page/notas.js b/src/page/notas.js index b2f9513..bf85243 100644 --- a/src/page/notas.js +++ b/src/page/notas.js @@ -111,6 +111,7 @@ PAGES.notas = { TS_IndexElement( "notas", [ + {"type": "_encrypted"}, { key: "Autor", type: "persona-nombre", diff --git a/src/page/pagos.js b/src/page/pagos.js index f8296d6..47eeffc 100644 --- a/src/page/pagos.js +++ b/src/page/pagos.js @@ -900,6 +900,7 @@ PAGES.pagos = { var totals = { ingresos: 0, gastos: 0 }; const config = [ + {"type": "_encrypted"}, { key: "Fecha", label: "Fecha/Hora", diff --git a/src/page/personas.js b/src/page/personas.js index ba863b4..986a913 100644 --- a/src/page/personas.js +++ b/src/page/personas.js @@ -203,6 +203,7 @@ PAGES.personas = { `; const config = [ + {"type": "_encrypted"}, // { // label: "Persona", // type: "persona",