Skip to content

Commit e0d7ee4

Browse files
committed
Delete a user's other sessions on password change
1 parent dd246f7 commit e0d7ee4

3 files changed

Lines changed: 41 additions & 3 deletions

File tree

.sqlx/query-5e4f8a9f90fd5177a3f0883fb3026a2bf2216efb5588c8011de57054076ff355.json

Lines changed: 14 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/api/db_helpers.rs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Helper functions that perform common database operations.
22
3-
use sqlx::PgTransaction;
3+
use sqlx::{postgres::PgQueryResult, PgTransaction};
44

55
use crate::{
66
crypto::hash_without_salt,
@@ -12,7 +12,7 @@ use crate::{
1212
///
1313
/// # Errors
1414
///
15-
/// Returns a transaction error if the database query fails.
15+
/// Returns a transaction error if any database query fails.
1616
pub(crate) async fn create_session<UserId, E>(
1717
tx: &mut PgTransaction<'static>,
1818
user_id: &UserId,
@@ -41,3 +41,25 @@ where
4141

4242
Ok(token)
4343
}
44+
45+
/// Deletes all of a user's sessions. This is a conventionally expected security feature whenever a
46+
/// user's password is changed.
47+
///
48+
/// # Errors
49+
///
50+
/// Returns a transaction error if any database query fails.
51+
pub(crate) async fn delete_all_sessions_for_user<UserId>(
52+
tx: &mut PgTransaction<'static>,
53+
user_id: &UserId,
54+
) -> sqlx::Result<PgQueryResult>
55+
where
56+
UserId: AsRef<[u8]>,
57+
{
58+
sqlx::query!(
59+
"DELETE FROM sessions
60+
WHERE user_id = $1",
61+
user_id.as_ref(),
62+
)
63+
.execute(tx.as_mut())
64+
.await
65+
}

backend/api/routes/v0/password_reset/password.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use crate::{
88
api::{
99
self,
1010
cookie::{CookieWrapper, SessionCookie},
11-
db_helpers::create_session,
11+
db_helpers::{create_session, delete_all_sessions_for_user},
1212
extract::Query,
1313
response::{body::User, Response},
1414
validation::NewUserPassword,
@@ -74,6 +74,8 @@ pub(crate) async fn post(
7474
.fetch_one(tx.as_mut())
7575
.await?;
7676

77+
delete_all_sessions_for_user(tx, &password_reset.user_id).await?;
78+
7779
let session_token = create_session(tx, &password_reset.user_id).await?;
7880

7981
Ok((password_reset.user_id, user.name, session_token))

0 commit comments

Comments
 (0)