summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/app.rs10
-rw-r--r--src/login/handlers/logout/mod.rs9
-rw-r--r--src/login/handlers/logout/test.rs25
-rw-r--r--src/test/verify/identity.rs26
-rw-r--r--src/test/verify/token.rs29
-rw-r--r--src/token/app.rs10
-rw-r--r--src/token/extract/identity.rs24
7 files changed, 88 insertions, 45 deletions
diff --git a/src/app.rs b/src/app.rs
index 202d542..6f6e8ba 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -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(