sessions: every signed-in browser is a row, and one can be signed out

A session cookie now carries the id of a row in the new sessions table,
and is refused once that row is gone. :sessions lists the browsers
signed in, newest first, and :sessions rm <n> signs one out without
touching the rest; it locks the vault too, since the vault is open for
the whole workspace. Logging out deletes the row, :logout! and a login
password change delete them all, and the sweep drops expired rows.
last_seen is kept in memory and written at most every five minutes.

Cookies issued before this carry no id and are refused: every browser
logs in once more after the upgrade.
This commit is contained in:
nvrl committed 2026-10-20 12:19:26 +02:00
1 parent 6c82264f57
commit 165561f6a2
10 files changed
+540 -56

No files matched your search

+4 -1
View File
@@ -3,7 +3,8 @@ use std::sync::{atomic::AtomicI64, Arc};
use sqlx::SqlitePool;
use crate::{
backup::Backup, config::Config, notify::Notifier, throttle::LoginThrottle, vault::Vault,
auth::Sessions, backup::Backup, config::Config, notify::Notifier, throttle::LoginThrottle,
vault::Vault,
};
#[derive(Clone)]
@@ -23,4 +24,6 @@ pub struct AppState {
/// Signed into every session cookie, which must carry the current value
/// to be accepted; see [`crate::auth::Epoch`].
pub epoch: Arc<AtomicI64>,
/// Every signed-in browser; a cookie is good only while its row is here.
pub sessions: Arc<Sessions>,
}