summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Jacobson <owen@grimoire.ca>2025-10-27 17:41:22 -0400
committerOwen Jacobson <owen@grimoire.ca>2025-10-28 01:42:29 -0400
commitf305e487d619f1d993d11d728c8cf7261bf3b371 (patch)
tree46ab6203babd5b93dcce00a0b7af7ae86dc0945e
parent6de7402a002791c6216b12a40e74af9c8ab82c02 (diff)
Convert `Invites` into a freestanding component.
-rw-r--r--src/app.rs10
-rw-r--r--src/invite/app.rs12
-rw-r--r--src/invite/handlers/accept/mod.rs8
-rw-r--r--src/invite/handlers/accept/test.rs12
-rw-r--r--src/invite/handlers/get/mod.rs7
-rw-r--r--src/invite/handlers/get/test.rs6
-rw-r--r--src/invite/handlers/issue/mod.rs9
-rw-r--r--src/invite/handlers/issue/test.rs2
-rw-r--r--src/test/fixtures/invite.rs12
-rw-r--r--src/ui/handlers/invite.rs6
10 files changed, 47 insertions, 37 deletions
diff --git a/src/app.rs b/src/app.rs
index 0b560dd..2d6d62b 100644
--- a/src/app.rs
+++ b/src/app.rs
@@ -46,8 +46,8 @@ impl App {
Events::new(self.db.clone(), self.events.clone())
}
- pub const fn invites(&self) -> Invites<'_> {
- Invites::new(&self.db, &self.events)
+ pub fn invites(&self) -> Invites {
+ Invites::new(self.db.clone(), self.events.clone())
}
pub const fn logins(&self) -> Logins<'_> {
@@ -83,3 +83,9 @@ impl FromRef<App> for Conversations {
app.conversations()
}
}
+
+impl FromRef<App> for Invites {
+ fn from_ref(app: &App) -> Self {
+ app.invites()
+ }
+}
diff --git a/src/invite/app.rs b/src/invite/app.rs
index 6684d03..6f58d0a 100644
--- a/src/invite/app.rs
+++ b/src/invite/app.rs
@@ -17,13 +17,13 @@ use crate::{
},
};
-pub struct Invites<'a> {
- db: &'a SqlitePool,
- events: &'a Broadcaster,
+pub struct Invites {
+ db: SqlitePool,
+ events: Broadcaster,
}
-impl<'a> Invites<'a> {
- pub const fn new(db: &'a SqlitePool, events: &'a Broadcaster) -> Self {
+impl Invites {
+ pub const fn new(db: SqlitePool, events: Broadcaster) -> Self {
Self { db, events }
}
@@ -88,7 +88,7 @@ impl<'a> Invites<'a> {
tx.tokens().create(&token, &secret).await?;
tx.commit().await?;
- stored.publish(self.events);
+ stored.publish(&self.events);
Ok(secret)
}
diff --git a/src/invite/handlers/accept/mod.rs b/src/invite/handlers/accept/mod.rs
index cdf385f..8bdaa51 100644
--- a/src/invite/handlers/accept/mod.rs
+++ b/src/invite/handlers/accept/mod.rs
@@ -5,11 +5,10 @@ use axum::{
};
use crate::{
- app::App,
clock::RequestedAt,
empty::Empty,
error::{Internal, NotFound},
- invite::{app, handlers::PathInfo},
+ invite::{app, app::Invites, handlers::PathInfo},
name::Name,
password::Password,
token::extract::IdentityCookie,
@@ -19,14 +18,13 @@ use crate::{
mod test;
pub async fn handler(
- State(app): State<App>,
+ State(invites): State<Invites>,
RequestedAt(accepted_at): RequestedAt,
identity: IdentityCookie,
Path(invite): Path<PathInfo>,
Json(request): Json<Request>,
) -> Result<(IdentityCookie, Empty), Error> {
- let secret = app
- .invites()
+ let secret = invites
.accept(&invite, &request.name, &request.password, &accepted_at)
.await
.map_err(Error)?;
diff --git a/src/invite/handlers/accept/test.rs b/src/invite/handlers/accept/test.rs
index 283ec76..446dbf9 100644
--- a/src/invite/handlers/accept/test.rs
+++ b/src/invite/handlers/accept/test.rs
@@ -24,7 +24,7 @@ async fn valid_invite() {
password: password.clone(),
};
let (identity, Empty) = super::handler(
- State(app.clone()),
+ State(app.invites()),
fixtures::now(),
identity,
Path(invite.id),
@@ -67,7 +67,7 @@ async fn nonexistent_invite() {
password: password.clone(),
};
let super::Error(error) = super::handler(
- State(app.clone()),
+ State(app.invites()),
fixtures::now(),
identity,
Path(invite.clone()),
@@ -103,7 +103,7 @@ async fn expired_invite() {
password: password.clone(),
};
let super::Error(error) = super::handler(
- State(app.clone()),
+ State(app.invites()),
fixtures::now(),
identity,
Path(invite.id.clone()),
@@ -140,7 +140,7 @@ async fn accepted_invite() {
password: password.clone(),
};
let super::Error(error) = super::handler(
- State(app.clone()),
+ State(app.invites()),
fixtures::now(),
identity,
Path(invite.id.clone()),
@@ -183,7 +183,7 @@ async fn conflicting_name() {
password: password.clone(),
};
let super::Error(error) = super::handler(
- State(app.clone()),
+ State(app.invites()),
fixtures::now(),
identity,
Path(invite.id.clone()),
@@ -217,7 +217,7 @@ async fn invalid_name() {
password: password.clone(),
};
let super::Error(error) = super::handler(
- State(app.clone()),
+ State(app.invites()),
fixtures::now(),
identity,
Path(invite.id),
diff --git a/src/invite/handlers/get/mod.rs b/src/invite/handlers/get/mod.rs
index bb72586..d5fd9c2 100644
--- a/src/invite/handlers/get/mod.rs
+++ b/src/invite/handlers/get/mod.rs
@@ -4,19 +4,18 @@ use axum::{
};
use crate::{
- app::App,
error::{Internal, NotFound},
- invite::{Id, Summary, handlers::PathInfo},
+ invite::{Id, Summary, app::Invites, handlers::PathInfo},
};
#[cfg(test)]
mod test;
pub async fn handler(
- State(app): State<App>,
+ State(invites): State<Invites>,
Path(invite): Path<PathInfo>,
) -> Result<Json<Summary>, Error> {
- app.invites()
+ invites
.get(&invite)
.await?
.map(Json)
diff --git a/src/invite/handlers/get/test.rs b/src/invite/handlers/get/test.rs
index 0f2f725..a08c510 100644
--- a/src/invite/handlers/get/test.rs
+++ b/src/invite/handlers/get/test.rs
@@ -12,7 +12,7 @@ async fn valid_invite() {
// Call endpoint
- let Json(response) = super::handler(State(app), Path(invite.id))
+ let Json(response) = super::handler(State(app.invites()), Path(invite.id))
.await
.expect("get for an existing invite succeeds");
@@ -31,7 +31,7 @@ async fn nonexistent_invite() {
// Call endpoint
let invite = fixtures::invite::fictitious();
- let error = super::handler(State(app), Path(invite.clone()))
+ let error = super::handler(State(app.invites()), Path(invite.clone()))
.await
.expect_err("get for a nonexistent invite fails");
@@ -55,7 +55,7 @@ async fn expired_invite() {
// Call endpoint
- let error = super::handler(State(app), Path(invite.id.clone()))
+ let error = super::handler(State(app.invites()), Path(invite.id.clone()))
.await
.expect_err("get for an expired invite fails");
diff --git a/src/invite/handlers/issue/mod.rs b/src/invite/handlers/issue/mod.rs
index 4ac74cc..0549c78 100644
--- a/src/invite/handlers/issue/mod.rs
+++ b/src/invite/handlers/issue/mod.rs
@@ -1,19 +1,22 @@
use axum::extract::{Json, State};
use crate::{
- app::App, clock::RequestedAt, error::Internal, invite::Invite, token::extract::Identity,
+ clock::RequestedAt,
+ error::Internal,
+ invite::{Invite, app::Invites},
+ token::extract::Identity,
};
#[cfg(test)]
mod test;
pub async fn handler(
- State(app): State<App>,
+ State(invites): State<Invites>,
RequestedAt(issued_at): RequestedAt,
identity: Identity,
_: Json<Request>,
) -> Result<Json<Invite>, Internal> {
- let invite = app.invites().issue(&identity.login, &issued_at).await?;
+ let invite = invites.issue(&identity.login, &issued_at).await?;
Ok(Json(invite))
}
diff --git a/src/invite/handlers/issue/test.rs b/src/invite/handlers/issue/test.rs
index 4421705..dc89243 100644
--- a/src/invite/handlers/issue/test.rs
+++ b/src/invite/handlers/issue/test.rs
@@ -13,7 +13,7 @@ async fn create_invite() {
// Call the endpoint
let Json(invite) = super::handler(
- State(app),
+ State(app.invites()),
issued_at.clone(),
issuer.clone(),
Json(super::Request {}),
diff --git a/src/test/fixtures/invite.rs b/src/test/fixtures/invite.rs
index 654d1b4..5a5d4d0 100644
--- a/src/test/fixtures/invite.rs
+++ b/src/test/fixtures/invite.rs
@@ -1,12 +1,16 @@
+use axum::extract::FromRef;
+
use crate::{
- app::App,
clock::DateTime,
- invite::{self, Invite},
+ invite::{self, Invite, app::Invites},
login::Login,
};
-pub async fn issue(app: &App, issuer: &Login, issued_at: &DateTime) -> Invite {
- app.invites()
+pub async fn issue<App>(app: &App, issuer: &Login, issued_at: &DateTime) -> Invite
+where
+ Invites: FromRef<App>,
+{
+ Invites::from_ref(app)
.issue(issuer, issued_at)
.await
.expect("issuing invites never fails")
diff --git a/src/ui/handlers/invite.rs b/src/ui/handlers/invite.rs
index 0f9580a..edd6dc1 100644
--- a/src/ui/handlers/invite.rs
+++ b/src/ui/handlers/invite.rs
@@ -4,9 +4,9 @@ use axum::{
};
use crate::{
- app::App,
error::Internal,
invite,
+ invite::app::Invites,
ui::{
assets::{Asset, Assets},
error::NotFound,
@@ -14,10 +14,10 @@ use crate::{
};
pub async fn handler(
- State(app): State<App>,
+ State(invites): State<Invites>,
Path(invite): Path<invite::Id>,
) -> Result<Asset, Error> {
- app.invites()
+ invites
.get(&invite)
.await
.map_err(Error::internal)?