feat: v0.36.0 patch set — 404 page, OIDC encryption, session rotate, user validation, calendar fixes

This commit is contained in:
null 2026-06-03 20:31:27 -05:00
parent 36a65156e3
commit 2550034996
2 changed files with 7 additions and 10 deletions

View File

@ -6,6 +6,8 @@
- **Bump**`0.35.1``0.36.0`
- **`rotateSessionId` uses `db.transaction()` instead of raw SQL** — `rotateSessionId()` in `authService.js` managed its DELETE + INSERT pair with explicit `db.prepare('BEGIN').run()` / `COMMIT` / `ROLLBACK` calls. This is fragile: if the rollback itself throws (e.g. connection in a bad state), the transaction is left open. Replaced with better-sqlite3's `db.transaction()` wrapper, which commits automatically on success and rolls back automatically on any thrown error with no manual try/catch required.
### 🔒 Security
- **OIDC client secret encrypted at rest** — The OIDC client secret was stored as plaintext in the `settings` table alongside all other application settings. It is now encrypted using the same AES-256-GCM + HKDF pipeline already in use for SMTP passwords and SimpleFIN tokens. A new `getOidcClientSecret()` helper in `oidcService.js` decrypts on read (with a plaintext fallback for legacy values), and the write path calls `encryptSecret()` before `setSetting`. DB migration `v0.79` encrypts any existing plaintext value on first startup — no manual action required. Env-var-sourced secrets (`OIDC_CLIENT_SECRET`) are unaffected and bypass the DB path entirely.

View File

@ -127,19 +127,14 @@ function rotateSessionId(oldSessionId, userId) {
const expiresAt = new Date(Date.now() + SESSION_DAYS * 86400000)
.toISOString().slice(0, 19).replace('T', ' ');
// Delete old session and create new one in a transaction
db.prepare('BEGIN').run();
try {
// Delete old session and create new one atomically
db.transaction(() => {
db.prepare('DELETE FROM sessions WHERE id = ?').run(oldSessionId);
db.prepare('INSERT INTO sessions (id, user_id, expires_at) VALUES (?, ?, ?)')
.run(newSessionId, userId, expiresAt);
db.prepare('COMMIT').run();
return newSessionId;
} catch (err) {
db.prepare('ROLLBACK').run();
throw err;
}
})();
return newSessionId;
}
function getSessionUser(sessionId) {