From 4ca0c24b1989fcd12c453d428af70f58456f7651 Mon Sep 17 00:00:00 2001 From: Vika Date: Thu, 1 Aug 2024 20:01:12 +0300 Subject: Migrate from axum::Extension to axum::extract::State This somehow allowed me to shrink the construction phase of Kittybox by a huge amount of code. --- src/lib.rs | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 116 insertions(+), 2 deletions(-) (limited to 'src/lib.rs') diff --git a/src/lib.rs b/src/lib.rs index 04b3298..1cc01c2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,17 @@ #![forbid(unsafe_code)] #![warn(clippy::todo)] +use std::sync::Arc; + +use axum::extract::FromRef; +use axum_extra::extract::cookie::Key; +use database::{FileStorage, PostgresStorage, Storage}; +use indieauth::backend::{AuthBackend, FileBackend as FileAuthBackend}; +use kittybox_util::queue::{JobItem, JobQueue}; +use media::storage::{MediaStore, file::FileStore as FileMediaStore}; +use tokio::{sync::Mutex, task::JoinSet}; +use webmentions::queue::{PostgresJobItem, PostgresJobQueue}; + /// Database abstraction layer for Kittybox, allowing the CMS to work with any kind of database. pub mod database; pub mod frontend; @@ -9,6 +20,110 @@ pub mod micropub; pub mod indieauth; pub mod webmentions; pub mod login; +//pub mod admin; + +#[derive(Clone)] +pub struct AppState +where +A: AuthBackend + Sized + 'static, +S: Storage + Sized + 'static, +M: MediaStore + Sized + 'static, +Q: JobQueue + Sized +{ + pub auth_backend: A, + pub storage: S, + pub media_store: M, + pub job_queue: Q, + pub http: reqwest::Client, + pub background_jobs: Arc>>, + pub cookie_key: Key +} + +// This is really regrettable, but I can't write: +// +// ```compile-error +// impl FromRef> for A +// where A: AuthBackend, S: Storage, M: MediaStore { +// fn from_ref(input: &AppState) -> A { +// input.auth_backend.clone() +// } +// } +// ``` +// +// ...because of the orphan rule. +// +// I wonder if this would stifle external implementations. I think it +// shouldn't, because my AppState type is generic, and since the +// target type is local, the orphan rule will not kick in. You just +// have to repeat this magic invocation. + +impl FromRef> for FileAuthBackend +// where S: Storage, M: MediaStore +where S: Storage, M: MediaStore, Q: JobQueue +{ + fn from_ref(input: &AppState) -> Self { + input.auth_backend.clone() + } +} + +impl FromRef> for PostgresStorage +// where A: AuthBackend, M: MediaStore +where A: AuthBackend, M: MediaStore, Q: JobQueue +{ + fn from_ref(input: &AppState) -> Self { + input.storage.clone() + } +} + +impl FromRef> for FileStorage +where A: AuthBackend, M: MediaStore, Q: JobQueue +{ + fn from_ref(input: &AppState) -> Self { + input.storage.clone() + } +} + +impl FromRef> for FileMediaStore +// where A: AuthBackend, S: Storage +where A: AuthBackend, S: Storage, Q: JobQueue +{ + fn from_ref(input: &AppState) -> Self { + input.media_store.clone() + } +} + +impl FromRef> for Key +where A: AuthBackend, S: Storage, M: MediaStore, Q: JobQueue +{ + fn from_ref(input: &AppState) -> Self { + input.cookie_key.clone() + } +} + +impl FromRef> for reqwest::Client +where A: AuthBackend, S: Storage, M: MediaStore, Q: JobQueue +{ + fn from_ref(input: &AppState) -> Self { + input.http.clone() + } +} + +impl FromRef> for Arc>> +where A: AuthBackend, S: Storage, M: MediaStore, Q: JobQueue +{ + fn from_ref(input: &AppState) -> Self { + input.background_jobs.clone() + } +} + +#[cfg(feature = "sqlx")] +impl FromRef> for PostgresJobQueue +where A: AuthBackend, S: Storage, M: MediaStore +{ + fn from_ref(input: &AppState) -> Self { + input.job_queue.clone() + } +} pub mod companion { use std::{collections::HashMap, sync::Arc}; @@ -52,8 +167,7 @@ pub mod companion { } } - #[must_use] - pub fn router() -> axum::Router { + pub fn router() -> axum::Router { let resources: ResourceTable = { let mut map = HashMap::new(); -- cgit 1.4.1