Fix Books tab: auto-generate encryption key, remove password prompt
- getOrCreateEncKey() now generates a random AES-GCM-256 key if none found in localStorage, instead of throwing an error - Removed enc-key-prompt div from player.html entirely - Simplified initBookDropZone() — removed prompt show/hide logic - book-upload-area always visible, no longer hidden behind prompt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
500b3fa780
commit
2fad4a726c
2 changed files with 9 additions and 21 deletions
|
|
@ -1813,16 +1813,20 @@ function hexToBytes(hex) {
|
|||
|
||||
async function getOrCreateEncKey() {
|
||||
if (_encKey) return _encKey;
|
||||
const storageKey = `diora_enc_key_${window.USER_ID || 'anon'}`;
|
||||
const storageKey = `diora_enc_key_${window.USER_ID || 0}`;
|
||||
const stored = localStorage.getItem(storageKey);
|
||||
if (stored) {
|
||||
try {
|
||||
const raw = base64ToBytes(stored);
|
||||
_encKey = await crypto.subtle.importKey('raw', raw, {name: 'AES-GCM'}, false, ['encrypt', 'decrypt']);
|
||||
return _encKey;
|
||||
} catch (e) { /* fall through */ }
|
||||
} catch (e) { /* fall through, generate new */ }
|
||||
}
|
||||
throw new Error('Encryption key not found — please log out and log in again.');
|
||||
// No key found — generate one and store it
|
||||
_encKey = await crypto.subtle.generateKey({name: 'AES-GCM', length: 256}, true, ['encrypt', 'decrypt']);
|
||||
const raw = await crypto.subtle.exportKey('raw', _encKey);
|
||||
localStorage.setItem(storageKey, bytesToBase64(new Uint8Array(raw)));
|
||||
return _encKey;
|
||||
}
|
||||
|
||||
async function encryptBytes(key, plainBytes) {
|
||||
|
|
@ -2205,14 +2209,6 @@ function initBookDropZone() {
|
|||
if (!zone || !zone.contains(e.target)) e.preventDefault();
|
||||
});
|
||||
|
||||
const storageKey = `diora_enc_key_${window.USER_ID || 'anon'}`;
|
||||
const hasKey = !!localStorage.getItem(storageKey);
|
||||
const prompt = $('enc-key-prompt');
|
||||
const uploadArea = $('book-upload-area');
|
||||
|
||||
if (prompt) prompt.style.display = hasKey ? 'none' : '';
|
||||
if (uploadArea) uploadArea.style.display = hasKey ? '' : 'none';
|
||||
|
||||
const zone = $('book-drop-zone');
|
||||
if (!zone) return;
|
||||
|
||||
|
|
@ -2245,7 +2241,7 @@ async function deriveAndStoreKey() {
|
|||
mat, {name: 'AES-GCM', length: 256}, true, ['encrypt', 'decrypt']
|
||||
);
|
||||
const raw = await crypto.subtle.exportKey('raw', key);
|
||||
const storageKey = `diora_enc_key_${window.USER_ID || 'anon'}`;
|
||||
const storageKey = `diora_enc_key_${window.USER_ID || 0}`;
|
||||
localStorage.setItem(storageKey, bytesToBase64(new Uint8Array(raw)));
|
||||
_encKey = null; // reset cached key
|
||||
if (statusEl) statusEl.textContent = '✓ Unlocked';
|
||||
|
|
|
|||
|
|
@ -278,15 +278,7 @@
|
|||
<!-- ===== BOOKS TAB ===== -->
|
||||
<section class="tab-panel" id="tab-books" style="display:none;">
|
||||
{% if user.is_authenticated %}
|
||||
<div id="enc-key-prompt" class="enc-key-prompt">
|
||||
<p class="muted">Enter your password to unlock encrypted storage on this device.</p>
|
||||
<div class="search-bar">
|
||||
<input type="password" id="enc-key-password" class="search-input" placeholder="Your password…">
|
||||
<button class="btn" onclick="deriveAndStoreKey()">Unlock</button>
|
||||
</div>
|
||||
<span id="enc-key-status" class="muted"></span>
|
||||
</div>
|
||||
<div id="book-upload-area" style="display:none;">
|
||||
<div id="book-upload-area">
|
||||
<div class="book-drop-zone" id="book-drop-zone">
|
||||
<span>Drop .epub or .pdf here or <label for="book-file-input" style="cursor:pointer;text-decoration:underline;">browse</label></span>
|
||||
<input type="file" id="book-file-input" accept=".epub,.pdf" style="display:none;" onchange="bookFileSelected(this)">
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue