feat: optional auth + backup/restore reliability fixes
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:
2026-03-23 14:50:25 +03:00
parent cd3137b0ec
commit 4975a74ff3
18 changed files with 189 additions and 67 deletions

View File

@@ -341,14 +341,27 @@
const savedAccent = localStorage.getItem('accentColor');
if (savedAccent) applyAccentColor(savedAccent, true);
// Early-apply saved background effect class (before bundle loads)
const savedBgEffect = localStorage.getItem('bgEffect');
if (savedBgEffect && savedBgEffect !== 'none') {
const effectClasses = { grid: 'bg-effect-grid', mesh: 'bg-effect-mesh', scanlines: 'bg-effect-scanlines', particles: 'bg-effect-particles' };
if (effectClasses[savedBgEffect]) document.documentElement.classList.add(effectClasses[savedBgEffect]);
}
// Initialize auth state
function updateAuthUI() {
const apiKey = localStorage.getItem('wled_api_key');
const loginBtn = document.getElementById('login-btn');
const logoutBtn = document.getElementById('logout-btn');
const tabBar = document.querySelector('.tab-bar');
const authDisabled = window._authRequired === false;
if (apiKey) {
if (authDisabled) {
// Auth disabled — hide login/logout, always show tabs
loginBtn.style.display = 'none';
logoutBtn.style.display = 'none';
if (tabBar) tabBar.style.display = '';
} else if (apiKey) {
loginBtn.style.display = 'none';
logoutBtn.style.display = 'inline-block';
if (tabBar) tabBar.style.display = '';