From 7a06bd89638ee87044d4d69d82e614acdc1cda75 Mon Sep 17 00:00:00 2001 From: admin Date: Thu, 28 May 2026 15:58:03 +0200 Subject: [PATCH] feat(verifactu): persist certificate token in localStorage - Add saveVeriFactuToken / getVeriFactuToken / clearVeriFactuToken helpers in verifactu.js - Save token to localStorage (key: verifactu_cert_token) after successful registration - Show active token status on SettingsPage load (first 8 chars + ellipsis) - Add "Borrar token" button that appears only when a token is stored Co-Authored-By: Claude Sonnet 4.6 --- src/pages/SettingsPage.js | 31 ++++++++++++++++++++++++++++--- src/services/verifactu.js | 16 ++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) diff --git a/src/pages/SettingsPage.js b/src/pages/SettingsPage.js index 8f656e7..be1bb8b 100644 --- a/src/pages/SettingsPage.js +++ b/src/pages/SettingsPage.js @@ -2,7 +2,7 @@ import { isDarkTheme, toggleTheme } from '../services/theme.js'; import { icons } from '../services/icons.js'; import { apiGet, apiPut } from '../services/apiClient.js'; import { showToast } from '../services/toast.js'; -import { encryptVeriFactuPassword, formatVeriFactuError, getVeriFactuFormats, getVeriFactuHealth, registerVeriFactuCertificate } from '../services/verifactu.js'; +import { encryptVeriFactuPassword, formatVeriFactuError, getVeriFactuFormats, getVeriFactuHealth, registerVeriFactuCertificate, saveVeriFactuToken, getVeriFactuToken, clearVeriFactuToken } from '../services/verifactu.js'; function decodeTokenPayload(token) { try { @@ -155,6 +155,7 @@ export function renderSettingsPage() {
+

@@ -202,6 +203,26 @@ export function renderSettingsPage() { const verifactuCertName = container.querySelector('#verifactu-cert-name'); const verifactuCertFile = container.querySelector('#verifactu-cert-file'); const verifactuCertPassword = container.querySelector('#verifactu-cert-password'); + const clearTokenBtn = container.querySelector('#verifactu-clear-token-btn'); + + const renderVeriFactuTokenStatus = () => { + const token = getVeriFactuToken(); + if (token) { + verifactuStatus.textContent = `Token activo: ${token.slice(0, 8)}...`; + clearTokenBtn.style.display = ''; + } else { + clearTokenBtn.style.display = 'none'; + } + }; + + renderVeriFactuTokenStatus(); + + clearTokenBtn.addEventListener('click', () => { + clearVeriFactuToken(); + verifactuStatus.textContent = 'Token eliminado.'; + clearTokenBtn.style.display = 'none'; + showToast('Token de VeriFactu eliminado', 'success'); + }); verifactuCertFile.addEventListener('change', () => { const file = verifactuCertFile.files?.[0]; @@ -333,8 +354,12 @@ export function renderSettingsPage() { return; } - const token = result.token ? ` Token: ${result.token}` : ''; - verifactuStatus.textContent = `Certificado registrado.${token}`; + if (result.token) { + saveVeriFactuToken(result.token); + renderVeriFactuTokenStatus(); + } + const tokenHint = result.token ? ` Token: ${result.token.slice(0, 8)}...` : ''; + verifactuStatus.textContent = `Certificado registrado.${tokenHint}`; showToast('Certificado registrado en VeriFactu', 'success'); } catch (error) { const errorMessage = formatVeriFactuError(error); diff --git a/src/services/verifactu.js b/src/services/verifactu.js index f96c5c1..80b510a 100644 --- a/src/services/verifactu.js +++ b/src/services/verifactu.js @@ -3,6 +3,22 @@ import { apiGet, apiPost } from './apiClient.js'; let cachedPublicKeyPem = null; +const VERIFACTU_TOKEN_KEY = 'verifactu_cert_token'; + +export function saveVeriFactuToken(token) { + if (token) { + localStorage.setItem(VERIFACTU_TOKEN_KEY, token); + } +} + +export function getVeriFactuToken() { + return localStorage.getItem(VERIFACTU_TOKEN_KEY) || null; +} + +export function clearVeriFactuToken() { + localStorage.removeItem(VERIFACTU_TOKEN_KEY); +} + const VERIFACTU_ERROR_MESSAGES = { missing_fields: 'Faltan campos obligatorios para registrar el certificado.', invalid_json: 'La peticion enviada a VeriFactu no tiene un JSON valido.',