From 6c65e97e49d1d56380aa7d71abb0394b08ff60ca Mon Sep 17 00:00:00 2001 From: Owen Jacobson Date: Sun, 24 Aug 2025 16:00:45 -0400 Subject: Return an identity, rather than the parts of an identity, when validating an identity token. This is a small refactoring that's been possible for a while, and we only just noticed. --- src/event/handlers/stream/test/invite.rs | 8 ++++---- src/event/handlers/stream/test/setup.rs | 4 ++-- src/invite/handlers/accept/test.rs | 8 ++++---- src/setup/handlers/setup/test.rs | 8 ++++---- src/test/fixtures/identity.rs | 7 ++----- src/token/app.rs | 5 +++-- src/token/extract/identity.rs | 12 +++++++----- src/user/handlers/login/test.rs | 7 +++---- src/user/handlers/logout/mod.rs | 4 ++-- src/user/handlers/password/test.rs | 8 ++++---- 10 files changed, 35 insertions(+), 36 deletions(-) diff --git a/src/event/handlers/stream/test/invite.rs b/src/event/handlers/stream/test/invite.rs index f2d6950..ce22384 100644 --- a/src/event/handlers/stream/test/invite.rs +++ b/src/event/handlers/stream/test/invite.rs @@ -33,7 +33,7 @@ async fn accepting_invite() { .accept(&invite.id, &name, &password, &fixtures::now()) .await .expect("accepting an invite succeeds"); - let (_, joiner) = app + let joiner = app .tokens() .validate(&joiner, &fixtures::now()) .await @@ -44,7 +44,7 @@ async fn accepting_invite() { let _ = events .filter_map(fixtures::event::stream::user) .filter_map(fixtures::event::stream::user::created) - .filter(|event| future::ready(event.user == joiner)) + .filter(|event| future::ready(event.user == joiner.user)) .next() .expect_some("a login created event is sent") .await; @@ -67,7 +67,7 @@ async fn previously_accepted_invite() { .accept(&invite.id, &name, &password, &fixtures::now()) .await .expect("accepting an invite succeeds"); - let (_, joiner) = app + let joiner = app .tokens() .validate(&joiner, &fixtures::now()) .await @@ -90,7 +90,7 @@ async fn previously_accepted_invite() { let _ = events .filter_map(fixtures::event::stream::user) .filter_map(fixtures::event::stream::user::created) - .filter(|event| future::ready(event.user == joiner)) + .filter(|event| future::ready(event.user == joiner.user)) .next() .expect_some("a login created event is sent") .await; diff --git a/src/event/handlers/stream/test/setup.rs b/src/event/handlers/stream/test/setup.rs index 297162e..1fd2b7c 100644 --- a/src/event/handlers/stream/test/setup.rs +++ b/src/event/handlers/stream/test/setup.rs @@ -22,7 +22,7 @@ async fn previously_completed() { .initial(&name, &password, &fixtures::now()) .await .expect("initial setup in an empty app succeeds"); - let (_, owner) = app + let owner = app .tokens() .validate(&secret, &fixtures::now()) .await @@ -45,7 +45,7 @@ async fn previously_completed() { let _ = events .filter_map(fixtures::event::stream::user) .filter_map(fixtures::event::stream::user::created) - .filter(|event| future::ready(event.user == owner)) + .filter(|event| future::ready(event.user == owner.user)) .next() .expect_some("a login created event is sent") .await; diff --git a/src/invite/handlers/accept/test.rs b/src/invite/handlers/accept/test.rs index adc7aa4..5140e3f 100644 --- a/src/invite/handlers/accept/test.rs +++ b/src/invite/handlers/accept/test.rs @@ -37,12 +37,12 @@ async fn valid_invite() { let secret = identity .secret() .expect("newly-issued identity has a token secret"); - let (_, login) = app + let identity = app .tokens() .validate(&secret, &fixtures::now()) .await .expect("newly-issued identity cookie is valid"); - assert_eq!(name, login.name); + assert_eq!(name, identity.user.name); // Verify that the given credentials can log in @@ -51,12 +51,12 @@ async fn valid_invite() { .login(&name, &password, &fixtures::now()) .await .expect("credentials given on signup are valid"); - let (_, login) = app + let identity = app .tokens() .validate(&secret, &fixtures::now()) .await .expect("validating a newly-issued token secret succeeds"); - assert_eq!(name, login.name); + assert_eq!(name, identity.user.name); } #[tokio::test] diff --git a/src/setup/handlers/setup/test.rs b/src/setup/handlers/setup/test.rs index 4a37690..133a162 100644 --- a/src/setup/handlers/setup/test.rs +++ b/src/setup/handlers/setup/test.rs @@ -25,12 +25,12 @@ async fn fresh_instance() { let secret = identity .secret() .expect("newly-issued identity has a token secret"); - let (_, login) = app + let identity = app .tokens() .validate(&secret, &fixtures::now()) .await .expect("newly-issued identity cookie is valid"); - assert_eq!(name, login.name); + assert_eq!(name, identity.user.name); // Verify that the given credentials can log in @@ -39,12 +39,12 @@ async fn fresh_instance() { .login(&name, &password, &fixtures::now()) .await .expect("credentials given on signup are valid"); - let (_, login) = app + let identity = app .tokens() .validate(&secret, &fixtures::now()) .await .expect("validating a newly-issued token secret succeeds"); - assert_eq!(name, login.name); + assert_eq!(name, identity.user.name); } #[tokio::test] diff --git a/src/test/fixtures/identity.rs b/src/test/fixtures/identity.rs index 84e1cf6..29ff5ae 100644 --- a/src/test/fixtures/identity.rs +++ b/src/test/fixtures/identity.rs @@ -21,13 +21,10 @@ pub async fn from_cookie( validated_at: &RequestedAt, ) -> Identity { let secret = cookie.secret().expect("identity token has a secret"); - let (token, user) = app - .tokens() + app.tokens() .validate(&secret, validated_at) .await - .expect("always validates newly-issued secret"); - - Identity { token, user } + .expect("always validates newly-issued secret") } pub async fn logged_in( diff --git a/src/token/app.rs b/src/token/app.rs index 56c0e21..8ec61c5 100644 --- a/src/token/app.rs +++ b/src/token/app.rs @@ -7,6 +7,7 @@ use sqlx::sqlite::SqlitePool; use super::{ Broadcaster, Event as TokenEvent, Id, Secret, + extract::Identity, repo::{self, Provider as _, auth::Provider as _}, }; use crate::{ @@ -104,7 +105,7 @@ impl<'a> Tokens<'a> { &self, secret: &Secret, used_at: &DateTime, - ) -> Result<(Id, User), ValidateError> { + ) -> Result { let mut tx = self.db.begin().await?; let (token, user) = tx .tokens() @@ -115,7 +116,7 @@ impl<'a> Tokens<'a> { let user = user.as_snapshot().ok_or(ValidateError::LoginDeleted)?; - Ok((token, user)) + Ok(Identity { token, user }) } pub async fn limit_stream( diff --git a/src/token/extract/identity.rs b/src/token/extract/identity.rs index d1c0334..4d076d7 100644 --- a/src/token/extract/identity.rs +++ b/src/token/extract/identity.rs @@ -30,11 +30,13 @@ impl FromRequestParts for Identity { let secret = cookie.secret().ok_or(LoginError::Unauthorized)?; let app = State::::from_request_parts(parts, state).await?; - match app.tokens().validate(&secret, &used_at).await { - Ok((token, user)) => Ok(Identity { token, user }), - Err(ValidateError::InvalidToken) => Err(LoginError::Unauthorized), - Err(other) => Err(other.into()), - } + app.tokens() + .validate(&secret, &used_at) + .await + .map_err(|err| match err { + ValidateError::InvalidToken => LoginError::Unauthorized, + other => other.into(), + }) } } diff --git a/src/user/handlers/login/test.rs b/src/user/handlers/login/test.rs index bdd1957..cb387ad 100644 --- a/src/user/handlers/login/test.rs +++ b/src/user/handlers/login/test.rs @@ -30,14 +30,13 @@ async fn correct_credentials() { // Verify the semantics - let validated_at = fixtures::now(); - let (_, validated_login) = app + let validated = app .tokens() - .validate(&secret, &validated_at) + .validate(&secret, &fixtures::now()) .await .expect("identity secret is valid"); - assert_eq!(name, validated_login.name); + assert_eq!(name, validated.user.name); } #[tokio::test] diff --git a/src/user/handlers/logout/mod.rs b/src/user/handlers/logout/mod.rs index 4450e4c..f759451 100644 --- a/src/user/handlers/logout/mod.rs +++ b/src/user/handlers/logout/mod.rs @@ -21,8 +21,8 @@ pub async fn handler( Json(_): Json, ) -> Result<(IdentityCookie, Empty), Error> { if let Some(secret) = identity.secret() { - let (token, _) = app.tokens().validate(&secret, &now).await?; - app.tokens().logout(&token).await?; + let validated_ident = app.tokens().validate(&secret, &now).await?; + app.tokens().logout(&validated_ident.token).await?; } let identity = identity.clear(); diff --git a/src/user/handlers/password/test.rs b/src/user/handlers/password/test.rs index ffa12f3..c0f789b 100644 --- a/src/user/handlers/password/test.rs +++ b/src/user/handlers/password/test.rs @@ -38,12 +38,12 @@ async fn password_change() { let new_secret = new_cookie .secret() .expect("we should have a secret after changing our password"); - let (_, login) = app + let new_identity = app .tokens() .validate(&new_secret, &fixtures::now()) .await .expect("the newly-issued secret should be valid"); - assert_eq!(identity.user, login); + assert_eq!(identity.user, new_identity.user); // Verify that our original token is no longer valid let validate_err = app @@ -72,10 +72,10 @@ async fn password_change() { .login(&name, &to, &fixtures::now()) .await .expect("logging in with the new password should succeed"); - let (_, login) = app + let identity = app .tokens() .validate(&secret, &fixtures::now()) .await .expect("validating a newly-issued token secret succeeds"); - assert_eq!(identity.user, login); + assert_eq!(name, identity.user.name); } -- cgit v1.2.3