feat(auth): server-side sessions and current password for account changes (FLAW-30, FLAW-31)
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m52s
MindSift CI & Docker Release / Build, Test in Container & Push (push) Successful in 1m52s
- Every login is a session (device, IP, last use); the token's jti is its ID. Sessions end on logout, per device from the profile, or after 30 idle days. - Tokens older than a day are renewed via the X-Session-Token header. - Changing password or login e-mail needs the current password; a new password logs out all other devices and mails the old address. - Demo reset keeps the demo visitors' sessions. - revoked_tokens is replaced by sessions (migration 4); everyone is logged out once after the upgrade. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
b2ecda9896
commit
1af3a6e90a
25 files changed
+705
-75
No files matched your search
@@ -7,6 +7,8 @@ import (
|
||||
|
||||
// ResetAndSeedDemo drops all tables, recreates the schema, and seeds demo accounts and demo data.
|
||||
func (s *Store) ResetAndSeedDemo() error {
|
||||
// Logged-in demo visitors stay logged in: their sessions survive the reset (fixed account IDs)
|
||||
kept := s.demoSessions()
|
||||
if err := s.dropAllTables(); err != nil {
|
||||
return fmt.Errorf("reset demo: drop all tables: %w", err)
|
||||
}
|
||||
@@ -16,6 +18,29 @@ func (s *Store) ResetAndSeedDemo() error {
|
||||
if err := s.EnsureDemoAccounts(); err != nil {
|
||||
return fmt.Errorf("reset demo: ensure demo accounts: %w", err)
|
||||
}
|
||||
for _, k := range kept {
|
||||
_, _ = s.db.Exec(`INSERT OR IGNORE INTO sessions (id, user_id, created_at, last_used_at, user_agent, ip) VALUES (?, ?, ?, ?, ?, ?)`,
|
||||
k.id, k.userID, k.created, k.lastUsed, k.agent, k.ip)
|
||||
}
|
||||
slog.Info("🧹 Demo-Modus: Datenbank für Testumgebung zurückgesetzt und neu befüllt")
|
||||
return nil
|
||||
}
|
||||
|
||||
type keptSession struct{ id, userID, created, lastUsed, agent, ip string }
|
||||
|
||||
func (s *Store) demoSessions() []keptSession {
|
||||
rows, err := s.db.Query(`SELECT id, user_id, created_at, last_used_at, user_agent, ip FROM sessions
|
||||
WHERE revoked_at = '' AND user_id IN (?, ?)`, DemoAdminID, DemoUserID)
|
||||
if err != nil {
|
||||
return nil // first start: no sessions table yet
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []keptSession
|
||||
for rows.Next() {
|
||||
var k keptSession
|
||||
if rows.Scan(&k.id, &k.userID, &k.created, &k.lastUsed, &k.agent, &k.ip) == nil {
|
||||
out = append(out, k)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in new issue
Block a user