feat: optional auth + backup/restore reliability fixes
Some checks failed
Lint & Test / test (push) Failing after 29s
Some checks failed
Lint & Test / test (push) Failing after 29s
Auth is now optional: when `auth.api_keys` is empty, all endpoints are open (no login screen, no Bearer tokens). Health endpoint reports `auth_required` so the frontend knows which mode to use. Backup/restore fixes: - Auto-backup uses atomic writes (was `write_text`, risked corruption) - Startup backup skipped if recent backup exists (<5 min cooldown), preventing rapid restarts from rotating out good backups - Restore rejects all-empty backups to prevent accidental data wipes - Store saves frozen after restore to prevent stale in-memory data from overwriting freshly-restored files before restart completes - Missing stores during restore logged as warnings - STORE_MAP completeness verified at startup against StorageConfig
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
*/
|
||||
|
||||
// Layer 0: state
|
||||
import { apiKey, setApiKey, refreshInterval } from './core/state.ts';
|
||||
import { apiKey, setApiKey, authRequired, refreshInterval } from './core/state.ts';
|
||||
import { Modal } from './core/modal.ts';
|
||||
import { queryEl } from './core/dom-utils.ts';
|
||||
|
||||
@@ -180,6 +180,9 @@ import {
|
||||
import { switchTab, initTabs, startAutoRefresh, handlePopState } from './features/tabs.ts';
|
||||
import { navigateToCard } from './core/navigation.ts';
|
||||
import { openCommandPalette, closeCommandPalette, initCommandPalette } from './core/command-palette.ts';
|
||||
import {
|
||||
applyStylePreset, applyBgEffect, renderAppearanceTab, initAppearance,
|
||||
} from './features/appearance.ts';
|
||||
import {
|
||||
openSettingsModal, closeSettingsModal, switchSettingsTab,
|
||||
downloadBackup, handleRestoreFileSelected,
|
||||
@@ -548,6 +551,11 @@ Object.assign(window, {
|
||||
setLogLevel,
|
||||
saveExternalUrl,
|
||||
getBaseOrigin,
|
||||
|
||||
// appearance
|
||||
applyStylePreset,
|
||||
applyBgEffect,
|
||||
renderAppearanceTab,
|
||||
});
|
||||
|
||||
// ─── Global keyboard shortcuts ───
|
||||
@@ -626,6 +634,7 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
// Initialize visual effects
|
||||
initCardGlare();
|
||||
initBgAnim();
|
||||
initAppearance();
|
||||
initTabIndicator();
|
||||
updateBgAnimTheme(document.documentElement.getAttribute('data-theme') !== 'light');
|
||||
const accent = localStorage.getItem('accentColor') || '#4CAF50';
|
||||
@@ -659,11 +668,15 @@ document.addEventListener('DOMContentLoaded', async () => {
|
||||
if (addDeviceForm) addDeviceForm.addEventListener('submit', handleAddDevice);
|
||||
|
||||
// Always monitor server connection (even before login)
|
||||
loadServerInfo();
|
||||
await loadServerInfo();
|
||||
startConnectionMonitor();
|
||||
|
||||
// Show modal if no API key is stored
|
||||
if (!apiKey) {
|
||||
// Expose auth state for inline scripts (after loadServerInfo sets it)
|
||||
(window as any)._authRequired = authRequired;
|
||||
if (typeof window.updateAuthUI === 'function') window.updateAuthUI();
|
||||
|
||||
// Show login modal only when auth is enabled and no API key is stored
|
||||
if (authRequired && !apiKey) {
|
||||
setTimeout(() => {
|
||||
if (typeof window.showApiKeyModal === 'function') {
|
||||
window.showApiKeyModal(null, true);
|
||||
|
||||
Reference in New Issue
Block a user