From 846d3a5a25f93eb10e462853f5d81fa629f8c876 Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Sun, 10 Dec 2023 11:01:30 +0200 Subject: [PATCH 1/2] Add CLI command to expire all sessions. --- backend/rvoc-backend/src/cli/mod.rs | 33 +++++++++++++++++++++++++++ backend/rvoc-backend/src/error/mod.rs | 3 +++ 2 files changed, 36 insertions(+) diff --git a/backend/rvoc-backend/src/cli/mod.rs b/backend/rvoc-backend/src/cli/mod.rs index 895a7a3..7244723 100644 --- a/backend/rvoc-backend/src/cli/mod.rs +++ b/backend/rvoc-backend/src/cli/mod.rs @@ -42,6 +42,10 @@ enum Cli { /// Note that this does not expire all sessions. ExpireAllPasswords, + /// Expire all sessions of all users. + /// This should always succeed, and sessions that are updated simultaneously should be be logged out anyways. + ExpireAllSessions, + /// Set the password of a user. /// If no password is given, then it is read from stdin. SetPassword { @@ -74,6 +78,7 @@ pub async fn run_cli_command(configuration: &Configuration) -> RVocResult<()> { } Cli::ApplyMigrations => apply_pending_database_migrations(configuration).await?, Cli::ExpireAllPasswords => expire_all_passwords(configuration).await?, + Cli::ExpireAllSessions => expire_all_sessions(configuration).await?, Cli::SetPassword { username, password } => { set_password(username, password, configuration).await? } @@ -161,6 +166,34 @@ async fn expire_all_passwords(configuration: &Configuration) -> RVocResult<()> { Ok(()) } +#[instrument(err, skip(configuration))] +async fn expire_all_sessions(configuration: &Configuration) -> RVocResult<()> { + let database_connection_pool = create_async_database_connection_pool(configuration).await?; + + database_connection_pool + .execute_read_committed_transaction( + |database_connection| { + Box::pin(async { + use crate::database::schema::sessions::dsl::*; + + diesel::delete(sessions) + .execute(database_connection) + .await + .map_err(|error| { + RVocError::ExpireAllSessions { + source: Box::new(error), + } + .into() + }) + }) + }, + configuration.maximum_transaction_retry_count, + ) + .await?; + + Ok(()) +} + #[instrument(err, skip(configuration))] async fn set_password( username: String, diff --git a/backend/rvoc-backend/src/error/mod.rs b/backend/rvoc-backend/src/error/mod.rs index 10de632..47b5d27 100644 --- a/backend/rvoc-backend/src/error/mod.rs +++ b/backend/rvoc-backend/src/error/mod.rs @@ -90,6 +90,9 @@ pub enum RVocError { #[error("error expiring all passwords: {source}")] ExpireAllPasswords { source: BoxDynError }, + #[error("error expiring all sessions: {source}")] + ExpireAllSessions { source: BoxDynError }, + #[error("error reading password from stdin: {source}")] ReadPasswordFromStdin { source: BoxDynError }, From c4ad61cf8a240590d963655c28cff7f6974e21ef Mon Sep 17 00:00:00 2001 From: Sebastian Schmidt Date: Sun, 10 Dec 2023 11:02:24 +0200 Subject: [PATCH 2/2] Have `expire-all-passwords` also expire all sessions. Closes #95 --- backend/rvoc-backend/src/cli/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/backend/rvoc-backend/src/cli/mod.rs b/backend/rvoc-backend/src/cli/mod.rs index 7244723..d43bbe1 100644 --- a/backend/rvoc-backend/src/cli/mod.rs +++ b/backend/rvoc-backend/src/cli/mod.rs @@ -37,9 +37,8 @@ enum Cli { /// Apply pending database migrations. ApplyMigrations, - /// Expire the passwords of all users. + /// Expire the passwords and sessions of all users. /// This should always succeed, and users who update their passwords simultaneously should receive an error. - /// Note that this does not expire all sessions. ExpireAllPasswords, /// Expire all sessions of all users. @@ -163,6 +162,8 @@ async fn expire_all_passwords(configuration: &Configuration) -> RVocResult<()> { ) .await?; + expire_all_sessions(configuration).await?; + Ok(()) }