feat: add password reset, SMTP settings, and Add Account button

Password reset: users with a registered email can request a reset link
from the login screen. A one-hour signed token is emailed via SMTP;
clicking the link opens a set-new-password form. Tokens are hashed
(SHA-256) before storage and invalidated after use.

SMTP settings: admin-only panel in the Users modal lets admins
configure host, port, encryption, credentials, and from address.
Settings persisted in a new key-value settings table. The SMTP
password is never returned to the client.

Users: email field added to the create/edit form and stored in a new
users.email column. Email is used for password reset lookup.

Add Account: admins now have a + button in the header that opens the
existing setup wizard to add additional checking accounts.

Schema: adds password_reset_tokens and settings tables with automatic
runtime migrations for existing databases.
This commit is contained in:
2026-03-31 10:21:49 -06:00
parent 444e24a191
commit fc114d0ec6
10 changed files with 378 additions and 12 deletions
+25
View File
@@ -122,4 +122,29 @@ db.exec(`
CREATE INDEX IF NOT EXISTS idx_layout_account ON layout_fields(account_id);
`);
// Migration: add email column to users
const usersInfo = db.prepare('PRAGMA table_info(users)').all();
if (!usersInfo.some(c => c.name === 'email')) {
db.exec('ALTER TABLE users ADD COLUMN email TEXT');
}
// Migration: create password_reset_tokens table
db.exec(`
CREATE TABLE IF NOT EXISTS password_reset_tokens (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
token_hash TEXT NOT NULL,
expires_at TEXT NOT NULL,
used_at TEXT
)
`);
// Migration: create settings table
db.exec(`
CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY,
value TEXT
)
`);
module.exports = db;