diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/app.rs | 10 | ||||
| -rw-r--r-- | src/login/handlers/logout/mod.rs | 9 | ||||
| -rw-r--r-- | src/login/handlers/logout/test.rs | 25 | ||||
| -rw-r--r-- | src/test/verify/identity.rs | 26 | ||||
| -rw-r--r-- | src/test/verify/token.rs | 29 | ||||
| -rw-r--r-- | src/token/app.rs | 10 | ||||
| -rw-r--r-- | src/token/extract/identity.rs | 24 |
7 files changed, 88 insertions, 45 deletions
@@ -62,8 +62,8 @@ impl App { Setup::new(self.db.clone(), self.events.clone()) } - pub const fn tokens(&self) -> Tokens<'_> { - Tokens::new(&self.db, &self.token_events) + pub fn tokens(&self) -> Tokens { + Tokens::new(self.db.clone(), self.token_events.clone()) } #[cfg(test)] @@ -107,3 +107,9 @@ impl FromRef<App> for Setup { app.setup() } } + +impl FromRef<App> for Tokens { + fn from_ref(app: &App) -> Self { + app.tokens() + } +} diff --git a/src/login/handlers/logout/mod.rs b/src/login/handlers/logout/mod.rs index 73efe73..ce4cb1a 100644 --- a/src/login/handlers/logout/mod.rs +++ b/src/login/handlers/logout/mod.rs @@ -4,25 +4,24 @@ use axum::{ }; use crate::{ - app::App, clock::RequestedAt, empty::Empty, error::{Internal, Unauthorized}, - token::{app, extract::IdentityCookie}, + token::{app, app::Tokens, extract::IdentityCookie}, }; #[cfg(test)] mod test; pub async fn handler( - State(app): State<App>, + State(tokens): State<Tokens>, RequestedAt(now): RequestedAt, identity: IdentityCookie, Json(_): Json<Request>, ) -> Result<(IdentityCookie, Empty), Error> { if let Some(secret) = identity.secret() { - let identity = app.tokens().validate(&secret, &now).await?; - app.tokens().logout(&identity.token).await?; + let identity = tokens.validate(&secret, &now).await?; + tokens.logout(&identity.token).await?; } let identity = identity.clear(); diff --git a/src/login/handlers/logout/test.rs b/src/login/handlers/logout/test.rs index e7b7dd4..18744ed 100644 --- a/src/login/handlers/logout/test.rs +++ b/src/login/handlers/logout/test.rs @@ -18,7 +18,7 @@ async fn successful() { // Call the endpoint let (response_identity, Empty) = super::handler( - State(app.clone()), + State(app.tokens()), fixtures::now(), identity.clone(), Json::default(), @@ -42,9 +42,14 @@ async fn no_identity() { // Call the endpoint let identity = fixtures::cookie::not_logged_in(); - let (identity, Empty) = super::handler(State(app), fixtures::now(), identity, Json::default()) - .await - .expect("logged out with no token succeeds"); + let (identity, Empty) = super::handler( + State(app.tokens()), + fixtures::now(), + identity, + Json::default(), + ) + .await + .expect("logged out with no token succeeds"); // Verify the return value's basic structure @@ -60,10 +65,14 @@ async fn invalid_token() { // Call the endpoint let identity = fixtures::cookie::fictitious(); - let super::Error(error) = - super::handler(State(app), fixtures::now(), identity, Json::default()) - .await - .expect_err("logged out with an invalid token fails"); + let super::Error(error) = super::handler( + State(app.tokens()), + fixtures::now(), + identity, + Json::default(), + ) + .await + .expect_err("logged out with an invalid token fails"); // Verify the return value's basic structure diff --git a/src/test/verify/identity.rs b/src/test/verify/identity.rs index 8e2d36e..fba2a4d 100644 --- a/src/test/verify/identity.rs +++ b/src/test/verify/identity.rs @@ -1,31 +1,43 @@ +use axum::extract::FromRef; + use crate::{ - app::App, login::Login, name::Name, test::{fixtures, verify}, - token::{app::ValidateError, extract::IdentityCookie}, + token::{ + app::{Tokens, ValidateError}, + extract::IdentityCookie, + }, }; -pub async fn valid_for_name(app: &App, identity: &IdentityCookie, name: &Name) { +pub async fn valid_for_name<App>(app: &App, identity: &IdentityCookie, name: &Name) +where + Tokens: FromRef<App>, +{ let secret = identity .secret() .expect("identity cookie must be set to be valid"); verify::token::valid_for_name(app, &secret, name).await; } -pub async fn valid_for_login(app: &App, identity: &IdentityCookie, login: &Login) { +pub async fn valid_for_login<App>(app: &App, identity: &IdentityCookie, login: &Login) +where + Tokens: FromRef<App>, +{ let secret = identity .secret() .expect("identity cookie must be set to be valid"); verify::token::valid_for_login(app, &secret, login).await; } -pub async fn invalid(app: &App, identity: &IdentityCookie) { +pub async fn invalid<App>(app: &App, identity: &IdentityCookie) +where + Tokens: FromRef<App>, +{ let secret = identity .secret() .expect("identity cookie must be set to be invalid"); - let validate_err = app - .tokens() + let validate_err = Tokens::from_ref(app) .validate(&secret, &fixtures::now()) .await .expect_err("identity cookie secret must be invalid"); diff --git a/src/test/verify/token.rs b/src/test/verify/token.rs index adc4397..1b61a19 100644 --- a/src/test/verify/token.rs +++ b/src/test/verify/token.rs @@ -1,32 +1,39 @@ +use axum::extract::FromRef; + use crate::{ - app::App, login::Login, name::Name, test::fixtures, - token::{Secret, app}, + token::{Secret, app, app::Tokens}, }; -pub async fn valid_for_name(app: &App, secret: &Secret, name: &Name) { - let identity = app - .tokens() +pub async fn valid_for_name<App>(app: &App, secret: &Secret, name: &Name) +where + Tokens: FromRef<App>, +{ + let identity = Tokens::from_ref(app) .validate(secret, &fixtures::now()) .await .expect("provided secret is valid"); assert_eq!(name, &identity.login.name); } -pub async fn valid_for_login(app: &App, secret: &Secret, login: &Login) { - let identity = app - .tokens() +pub async fn valid_for_login<App>(app: &App, secret: &Secret, login: &Login) +where + Tokens: FromRef<App>, +{ + let identity = Tokens::from_ref(app) .validate(secret, &fixtures::now()) .await .expect("provided secret is valid"); assert_eq!(login, &identity.login); } -pub async fn invalid(app: &App, secret: &Secret) { - let error = app - .tokens() +pub async fn invalid<App>(app: &App, secret: &Secret) +where + Tokens: FromRef<App>, +{ + let error = Tokens::from_ref(app) .validate(secret, &fixtures::now()) .await .expect_err("provided secret is invalid"); diff --git a/src/token/app.rs b/src/token/app.rs index 1d68f32..332473d 100644 --- a/src/token/app.rs +++ b/src/token/app.rs @@ -12,13 +12,13 @@ use super::{ }; use crate::{clock::DateTime, db::NotFound as _, name}; -pub struct Tokens<'a> { - db: &'a SqlitePool, - token_events: &'a Broadcaster, +pub struct Tokens { + db: SqlitePool, + token_events: Broadcaster, } -impl<'a> Tokens<'a> { - pub const fn new(db: &'a SqlitePool, token_events: &'a Broadcaster) -> Self { +impl Tokens { + pub const fn new(db: SqlitePool, token_events: Broadcaster) -> Self { Self { db, token_events } } diff --git a/src/token/extract/identity.rs b/src/token/extract/identity.rs index bee4e31..5c004ef 100644 --- a/src/token/extract/identity.rs +++ b/src/token/extract/identity.rs @@ -1,16 +1,18 @@ use axum::{ - extract::{FromRequestParts, OptionalFromRequestParts, State}, + extract::{FromRef, FromRequestParts, OptionalFromRequestParts, State}, http::request::Parts, response::{IntoResponse, Response}, }; use super::IdentityCookie; use crate::{ - app::App, clock::RequestedAt, error::{Internal, Unauthorized}, login::Login, - token::{Token, app::ValidateError}, + token::{ + Token, + app::{Tokens, ValidateError}, + }, }; #[derive(Clone, Debug)] @@ -19,7 +21,11 @@ pub struct Identity { pub login: Login, } -impl FromRequestParts<App> for Identity { +impl<App> FromRequestParts<App> for Identity +where + Tokens: FromRef<App>, + App: Send + Sync, +{ type Rejection = LoginError<Internal>; async fn from_request_parts(parts: &mut Parts, state: &App) -> Result<Self, Self::Rejection> { @@ -28,8 +34,8 @@ impl FromRequestParts<App> for Identity { let secret = cookie.secret().ok_or(LoginError::Unauthorized)?; - let app = State::<App>::from_request_parts(parts, state).await?; - app.tokens() + let tokens = State::<Tokens>::from_request_parts(parts, state).await?; + tokens .validate(&secret, &used_at) .await .map_err(|err| match err { @@ -39,7 +45,11 @@ impl FromRequestParts<App> for Identity { } } -impl OptionalFromRequestParts<App> for Identity { +impl<App> OptionalFromRequestParts<App> for Identity +where + Tokens: FromRef<App>, + App: Send + Sync, +{ type Rejection = LoginError<Internal>; async fn from_request_parts( |
