diff options
| author | Owen Jacobson <owen@grimoire.ca> | 2024-09-11 22:43:14 -0400 |
|---|---|---|
| committer | Owen Jacobson <owen@grimoire.ca> | 2024-09-12 00:26:04 -0400 |
| commit | f2f820370efbd5c6d0f304f781284a9f68990e21 (patch) | |
| tree | 7fb25e676dcd8dc694d0cec4df2cc04cab1120ac /src | |
| parent | 8a4e25c2a7d6235d726499d43fd1721104314e86 (diff) | |
Wrap the database pool in an App struct.
This is a jumping-off point for adding logic that needs more than just the DB for state, such as chat message handling.
The name sucks, but it's the best I've got.
Diffstat (limited to 'src')
| -rw-r--r-- | src/app.rs | 12 | ||||
| -rw-r--r-- | src/channel/routes.rs | 9 | ||||
| -rw-r--r-- | src/cli.rs | 6 | ||||
| -rw-r--r-- | src/index.rs | 18 | ||||
| -rw-r--r-- | src/lib.rs | 1 | ||||
| -rw-r--r-- | src/login/extract/login.rs | 13 | ||||
| -rw-r--r-- | src/login/routes.rs | 13 |
7 files changed, 39 insertions, 33 deletions
diff --git a/src/app.rs b/src/app.rs new file mode 100644 index 0000000..eff1b5e --- /dev/null +++ b/src/app.rs @@ -0,0 +1,12 @@ +use sqlx::sqlite::SqlitePool; + +#[derive(Clone)] +pub struct App { + pub db: SqlitePool, +} + +impl App { + pub fn from(db: SqlitePool) -> Self { + Self { db } + } +} diff --git a/src/channel/routes.rs b/src/channel/routes.rs index 014a57b..6e06cc9 100644 --- a/src/channel/routes.rs +++ b/src/channel/routes.rs @@ -4,12 +4,11 @@ use axum::{ routing::post, Router, }; -use sqlx::sqlite::SqlitePool; use super::repo::Provider as _; -use crate::{error::InternalError, login::repo::logins::Login}; +use crate::{app::App, error::InternalError, login::repo::logins::Login}; -pub fn router() -> Router<SqlitePool> { +pub fn router() -> Router<App> { Router::new().route("/create", post(on_create)) } @@ -19,11 +18,11 @@ struct CreateRequest { } async fn on_create( - State(db): State<SqlitePool>, + State(app): State<App>, _: Login, // requires auth, but doesn't actually care who you are Form(form): Form<CreateRequest>, ) -> Result<impl IntoResponse, InternalError> { - let mut tx = db.begin().await?; + let mut tx = app.db.begin().await?; tx.channels().create(&form.name).await?; tx.commit().await?; @@ -6,7 +6,7 @@ use clap::Parser; use sqlx::sqlite::{SqliteConnectOptions, SqlitePool, SqlitePoolOptions}; use tokio::net; -use crate::{channel, clock, error::BoxedError, index, login}; +use crate::{app::App, channel, clock, error::BoxedError, index, login}; pub type Result<T> = std::result::Result<T, BoxedError>; @@ -30,7 +30,7 @@ impl Args { let app = routers() .route_layer(middleware::from_fn(clock::middleware)) - .with_state(pool); + .with_state(App::from(pool)); let listener = self.listener().await?; let started_msg = started_msg(&listener)?; @@ -62,7 +62,7 @@ impl Args { } } -fn routers() -> Router<SqlitePool> { +fn routers() -> Router<App> { [channel::router(), login::router()] .into_iter() .fold(index::router(), Router::merge) diff --git a/src/index.rs b/src/index.rs index 9efd7cc..843cb77 100644 --- a/src/index.rs +++ b/src/index.rs @@ -1,28 +1,26 @@ use axum::{extract::State, routing::get, Router}; use maud::Markup; -use sqlx::sqlite::SqlitePool; -use crate::{channel::repo::Provider as _, error::InternalError, login::repo::logins::Login}; +use crate::{ + app::App, channel::repo::Provider as _, error::InternalError, login::repo::logins::Login, +}; -async fn index( - State(db): State<SqlitePool>, - login: Option<Login>, -) -> Result<Markup, InternalError> { +async fn index(State(app): State<App>, login: Option<Login>) -> Result<Markup, InternalError> { match login { None => Ok(templates::unauthenticated()), - Some(login) => index_authenticated(db, login).await, + Some(login) => index_authenticated(app, login).await, } } -async fn index_authenticated(db: SqlitePool, login: Login) -> Result<Markup, InternalError> { - let mut tx = db.begin().await?; +async fn index_authenticated(app: App, login: Login) -> Result<Markup, InternalError> { + let mut tx = app.db.begin().await?; let channels = tx.channels().all().await?; tx.commit().await?; Ok(templates::authenticated(login, &channels)) } -pub fn router() -> Router<SqlitePool> { +pub fn router() -> Router<App> { Router::new().route("/", get(index)) } @@ -1,3 +1,4 @@ +mod app; mod channel; pub mod cli; mod clock; diff --git a/src/login/extract/login.rs b/src/login/extract/login.rs index da0a90e..4155ec2 100644 --- a/src/login/extract/login.rs +++ b/src/login/extract/login.rs @@ -3,9 +3,9 @@ use axum::{ http::{request::Parts, StatusCode}, response::{IntoResponse, Response}, }; -use sqlx::sqlite::SqlitePool; use crate::{ + app::App, clock::RequestedAt, error::InternalError, login::{ @@ -15,13 +15,10 @@ use crate::{ }; #[async_trait::async_trait] -impl FromRequestParts<SqlitePool> for Login { +impl FromRequestParts<App> for Login { type Rejection = LoginError<InternalError>; - async fn from_request_parts( - parts: &mut Parts, - state: &SqlitePool, - ) -> Result<Self, Self::Rejection> { + async fn from_request_parts(parts: &mut Parts, state: &App) -> Result<Self, Self::Rejection> { // After Rust 1.82 (and #[feature(min_exhaustive_patterns)] lands on // stable), the following can be replaced: // @@ -31,8 +28,8 @@ impl FromRequestParts<SqlitePool> for Login { let secret = identity_token.secret().ok_or(LoginError::Forbidden)?; - let db = State::<SqlitePool>::from_request_parts(parts, state).await?; - let mut tx = db.begin().await?; + let app = State::<App>::from_request_parts(parts, state).await?; + let mut tx = app.db.begin().await?; tx.tokens().expire(requested_at).await?; let login = tx.tokens().validate(secret, requested_at).await?; tx.commit().await?; diff --git a/src/login/routes.rs b/src/login/routes.rs index c30bcb1..9cefe38 100644 --- a/src/login/routes.rs +++ b/src/login/routes.rs @@ -5,16 +5,15 @@ use axum::{ routing::post, Router, }; -use sqlx::sqlite::SqlitePool; -use crate::{clock::RequestedAt, error::InternalError}; +use crate::{app::App, clock::RequestedAt, error::InternalError}; use super::{ extract::IdentityToken, repo::{logins::Provider as _, tokens::Provider as _}, }; -pub fn router() -> Router<SqlitePool> { +pub fn router() -> Router<App> { Router::new() .route("/login", post(on_login)) .route("/logout", post(on_logout)) @@ -27,12 +26,12 @@ struct LoginRequest { } async fn on_login( - State(db): State<SqlitePool>, + State(app): State<App>, RequestedAt(now): RequestedAt, identity: IdentityToken, Form(form): Form<LoginRequest>, ) -> Result<impl IntoResponse, InternalError> { - let mut tx = db.begin().await?; + let mut tx = app.db.begin().await?; // Spelling the following in the more conventional form, // if let Some(…) = create().await? {} @@ -88,11 +87,11 @@ impl IntoResponse for LoginResponse { } async fn on_logout( - State(db): State<SqlitePool>, + State(app): State<App>, identity: IdentityToken, ) -> Result<impl IntoResponse, InternalError> { if let Some(secret) = identity.secret() { - let mut tx = db.begin().await?; + let mut tx = app.db.begin().await?; tx.tokens().revoke(secret).await?; tx.commit().await?; } |
