Built for people who think better out loud.
at main 129 lines 4.0 kB view raw
1use axum::extract::FromRef; 2use atproto_identity::key::KeyData; 3use atproto_identity::traits::{DidDocumentStorage, IdentityResolver, KeyResolver}; 4use atproto_oauth::storage::OAuthRequestStorage; 5use atproto_oauth_axum::state::OAuthClientConfig; 6use sqlx::PgPool; 7use std::sync::Arc; 8 9use crate::logging::Logger; 10use crate::infrastructure::whisper::WhisperClient; 11 12/// Shared application state for handlers and middleware. 13/// 14/// Usage: 15/// ```rust,ignore 16/// # use slipnote_backend::logging::Logger; 17/// # use slipnote_backend::infrastructure::whisper::WhisperClient; 18/// # use slipnote_backend::state::AppState; 19/// # use slipnote_backend::config::Config; 20/// let config = Config::from_env().expect("config"); 21/// let whisper = WhisperClient::new(config.clone()); 22/// let logger = Logger::from_config(&config).expect("logger"); 23/// let pool = PgPool::connect_lazy(&config.database_url).expect("pool"); 24/// let oauth = slipnote_backend::infrastructure::oauth::build_oauth_dependencies(&config, pool.clone()); 25/// let _state = AppState { 26/// config, 27/// whisper_client: whisper, 28/// logger, 29/// db_pool: pool, 30/// http_client: oauth.http_client, 31/// oauth_client_config: oauth.oauth_client_config, 32/// oauth_request_storage: oauth.oauth_request_storage, 33/// did_document_storage: oauth.did_document_storage, 34/// key_resolver: oauth.key_resolver, 35/// identity_resolver: oauth.identity_resolver, 36/// oauth_signing_key: oauth.oauth_signing_key, 37/// }; 38/// ``` 39#[derive(Clone)] 40pub struct AppState { 41 /// Application configuration for handlers. 42 pub config: crate::config::Config, 43 /// Whisper client for `OpenAI` requests. 44 pub whisper_client: WhisperClient, 45 /// Logger used by request middleware. 46 pub logger: Logger, 47 /// Postgres connection pool. 48 pub db_pool: PgPool, 49 /// HTTP client for OAuth and identity calls. 50 pub http_client: reqwest::Client, 51 /// OAuth client metadata configuration. 52 pub oauth_client_config: OAuthClientConfig, 53 /// OAuth request storage for state validation. 54 pub oauth_request_storage: Arc<dyn OAuthRequestStorage>, 55 /// DID document storage for identity resolution. 56 pub did_document_storage: Arc<dyn DidDocumentStorage>, 57 /// Key resolver for signing keys. 58 pub key_resolver: Arc<dyn KeyResolver>, 59 /// Identity resolver for handles and DIDs. 60 pub identity_resolver: Arc<dyn IdentityResolver>, 61 /// OAuth signing key used for client assertions. 62 pub oauth_signing_key: KeyData, 63} 64 65impl FromRef<AppState> for WhisperClient { 66 fn from_ref(state: &AppState) -> Self { 67 state.whisper_client.clone() 68 } 69} 70 71impl FromRef<AppState> for Logger { 72 fn from_ref(state: &AppState) -> Self { 73 state.logger.clone() 74 } 75} 76 77impl FromRef<AppState> for PgPool { 78 fn from_ref(state: &AppState) -> Self { 79 state.db_pool.clone() 80 } 81} 82 83impl FromRef<AppState> for crate::config::Config { 84 fn from_ref(state: &AppState) -> Self { 85 state.config.clone() 86 } 87} 88 89impl FromRef<AppState> for reqwest::Client { 90 fn from_ref(state: &AppState) -> Self { 91 state.http_client.clone() 92 } 93} 94 95impl FromRef<AppState> for OAuthClientConfig { 96 fn from_ref(state: &AppState) -> Self { 97 state.oauth_client_config.clone() 98 } 99} 100 101impl FromRef<AppState> for Arc<dyn OAuthRequestStorage> { 102 fn from_ref(state: &AppState) -> Self { 103 state.oauth_request_storage.clone() 104 } 105} 106 107impl FromRef<AppState> for Arc<dyn DidDocumentStorage> { 108 fn from_ref(state: &AppState) -> Self { 109 state.did_document_storage.clone() 110 } 111} 112 113impl FromRef<AppState> for Arc<dyn KeyResolver> { 114 fn from_ref(state: &AppState) -> Self { 115 state.key_resolver.clone() 116 } 117} 118 119impl FromRef<AppState> for Arc<dyn IdentityResolver> { 120 fn from_ref(state: &AppState) -> Self { 121 state.identity_resolver.clone() 122 } 123} 124 125impl FromRef<AppState> for KeyData { 126 fn from_ref(state: &AppState) -> Self { 127 state.oauth_signing_key.clone() 128 } 129}