import { renderHeader } from '../components/header.js'; import { state } from '../state.js'; import { bytesToBase58 } from '../services/crypto-utils.js'; import { extractSeed32FromPkcs8B64 } from '../services/client-key-utils.js'; import { loadEncryptedUserSecrets } from '../services/key-vault.js'; export const pageMeta = { id: 'show-keys-view', title: 'Показать ключи' }; export function render({ navigate }) { const screen = document.createElement('section'); screen.className = 'stack'; const visible = { root: false, blockchain: false, device: false, }; const keys = { root: '', blockchain: '', device: '', }; screen.append( renderHeader({ title: 'Показать ключи', leftAction: { label: '←', onClick: () => navigate('device-view') }, }), ); const card = document.createElement('div'); card.className = 'card stack'; const status = document.createElement('p'); status.className = 'meta-muted'; status.textContent = 'Загружаем сохранённые ключи...'; card.append(status); const renderField = (id, label) => { const row = document.createElement('div'); row.className = 'key-card stack'; const eyeIcon = ` `; const eyeOffIcon = ` `; row.innerHTML = `
${label}
*****
`; row._eyeIcon = eyeIcon; row._eyeOffIcon = eyeOffIcon; return row; }; card.append( renderField('root', 'root key (base58)'), renderField('blockchain', 'blockchain.key (base58)'), renderField('device', 'client key (base58)'), ); const setMissingState = (id) => { const valueEl = card.querySelector(`[data-value="${id}"]`); const btnEl = card.querySelector(`[data-toggle="${id}"]`); const field = btnEl?.closest('.key-card'); valueEl.textContent = 'нет данных'; btnEl.disabled = true; btnEl.innerHTML = field?._eyeOffIcon || ''; btnEl.setAttribute('aria-label', 'Нет данных'); btnEl.title = 'Нет данных'; }; const updateField = (id) => { const valueEl = card.querySelector(`[data-value="${id}"]`); const btnEl = card.querySelector(`[data-toggle="${id}"]`); const field = btnEl?.closest('.key-card'); if (!keys[id]) { setMissingState(id); return; } valueEl.textContent = visible[id] ? keys[id] : '*****'; btnEl.disabled = false; btnEl.innerHTML = visible[id] ? field?._eyeIcon || '' : field?._eyeOffIcon || ''; btnEl.setAttribute('aria-label', visible[id] ? 'Скрыть ключ' : 'Показать ключ'); btnEl.title = visible[id] ? 'Скрыть ключ' : 'Показать ключ'; }; card.querySelectorAll('[data-toggle]').forEach((button) => { button.addEventListener('click', () => { const { toggle } = button.dataset; if (!keys[toggle]) return; visible[toggle] = !visible[toggle]; updateField(toggle); }); }); ['root', 'blockchain', 'device'].forEach((id) => updateField(id)); const actions = document.createElement('div'); actions.className = 'auth-footer-actions'; const closeButton = document.createElement('button'); closeButton.className = 'ghost-btn'; closeButton.type = 'button'; closeButton.textContent = 'Назад'; closeButton.addEventListener('click', () => navigate('device-view')); actions.append(closeButton); (async () => { try { if (!state.session.login || !state.session.storagePwdInMemory) { throw new Error('Нет активной сессии для чтения ключей'); } const savedKeys = await loadEncryptedUserSecrets( state.session.login, state.session.storagePwdInMemory, ); const rootSeed32 = savedKeys.rootKey ? extractSeed32FromPkcs8B64(savedKeys.rootKey) : null; const blockchainSeed32 = savedKeys.blockchainKey ? extractSeed32FromPkcs8B64(savedKeys.blockchainKey) : null; const clientSeed32 = savedKeys.clientKey ? extractSeed32FromPkcs8B64(savedKeys.clientKey) : null; keys.root = rootSeed32 ? bytesToBase58(rootSeed32) : ''; keys.blockchain = blockchainSeed32 ? bytesToBase58(blockchainSeed32) : ''; keys.device = clientSeed32 ? bytesToBase58(clientSeed32) : ''; if (keys.root || keys.blockchain || keys.device) { status.textContent = 'Показаны только ключи, сохранённые на этом устройстве.'; } else { status.textContent = 'На этом устройстве нет сохранённых ключей.'; } } catch (error) { status.textContent = 'На этом устройстве нет сохранённых ключей.'; } ['root', 'blockchain', 'device'].forEach((id) => updateField(id)); })(); screen.append(card, actions); return screen; }