Skip to main content

cloudillo_core/
app.rs

1// SPDX-FileCopyrightText: Szilárd Hajba
2// SPDX-License-Identifier: LGPL-3.0-or-later
3
4//! App state type
5
6use rustls::sign::CertifiedKey;
7use std::{
8	collections::HashMap,
9	path::Path,
10	sync::{Arc, RwLock},
11};
12
13use crate::bundled_apps::BundledAppRegistry;
14use crate::extensions::Extensions;
15use crate::prelude::*;
16use crate::profile_me_cache::ProfileMeCache;
17use crate::proxy_token_cache::ProxyTokenCache;
18use crate::{abac, request, scheduler, ws_broadcast::BroadcastManager};
19
20use cloudillo_types::auth_adapter::AuthAdapter;
21use cloudillo_types::blob_adapter::BlobAdapter;
22use cloudillo_types::crdt_adapter::CrdtAdapter;
23use cloudillo_types::identity_provider_adapter::IdentityProviderAdapter;
24use cloudillo_types::meta_adapter::MetaAdapter;
25use cloudillo_types::rtdb_adapter::RtdbAdapter;
26use cloudillo_types::worker;
27
28use crate::rate_limit::RateLimitManager;
29use crate::settings::service::SettingsService;
30use crate::settings::types::FrozenSettingsRegistry;
31
32pub const VERSION: &str = env!("CARGO_PKG_VERSION");
33
34#[derive(Debug, Clone, Copy)]
35pub enum ServerMode {
36	Standalone,
37	Proxy,
38	StreamProxy,
39}
40
41pub struct AppState {
42	pub scheduler: Arc<scheduler::Scheduler<App>>,
43	pub worker: Arc<worker::WorkerPool>,
44	pub request: request::Request,
45	pub proxy_tokens: Arc<ProxyTokenCache>,
46	pub profile_me: Arc<ProfileMeCache>,
47	pub acme_challenge_map: RwLock<HashMap<Box<str>, Box<str>>>,
48	pub certs: RwLock<HashMap<Box<str>, Arc<CertifiedKey>>>,
49	pub opts: AppBuilderOpts,
50	pub broadcast: BroadcastManager,
51	pub permission_checker: Arc<tokio::sync::RwLock<abac::PermissionChecker>>,
52	/// Doc formats this build ships, loaded once from `opts.dist_dir`. The global tier
53	/// under every tenant's own rows — resolve through [`crate::doc_format::resolve`]
54	/// rather than reading it directly.
55	pub bundled_apps: Arc<BundledAppRegistry>,
56
57	pub auth_adapter: Arc<dyn AuthAdapter>,
58	pub meta_adapter: Arc<dyn MetaAdapter>,
59	pub blob_adapter: Arc<dyn BlobAdapter>,
60	pub crdt_adapter: Arc<dyn CrdtAdapter>,
61	pub rtdb_adapter: Arc<dyn RtdbAdapter>,
62	pub idp_adapter: Option<Arc<dyn IdentityProviderAdapter>>,
63
64	// Settings subsystem
65	pub settings: Arc<SettingsService>,
66	pub settings_registry: Arc<FrozenSettingsRegistry>,
67
68	// Rate limiter
69	pub rate_limiter: Arc<RateLimitManager>,
70
71	// Type-erased extension map for feature-specific state
72	pub extensions: Extensions,
73}
74
75impl AppState {
76	/// Get a registered extension by type. Returns error if not found.
77	pub fn ext<T: Send + Sync + 'static>(&self) -> ClResult<&T> {
78		self.extensions.get::<T>().ok_or_else(|| {
79			Error::Internal(format!("Extension {} not registered", std::any::type_name::<T>()))
80		})
81	}
82}
83
84pub type App = Arc<AppState>;
85
86pub struct Adapters {
87	pub auth_adapter: Option<Arc<dyn AuthAdapter>>,
88	pub meta_adapter: Option<Arc<dyn MetaAdapter>>,
89	pub blob_adapter: Option<Arc<dyn BlobAdapter>>,
90	pub crdt_adapter: Option<Arc<dyn CrdtAdapter>>,
91	pub rtdb_adapter: Option<Arc<dyn RtdbAdapter>>,
92	pub idp_adapter: Option<Arc<dyn IdentityProviderAdapter>>,
93}
94
95#[derive(Debug)]
96pub struct AppBuilderOpts {
97	pub mode: ServerMode,
98	pub listen: Box<str>,
99	pub listen_http: Option<Box<str>>,
100	pub base_id_tag: Option<Box<str>>,
101	pub base_app_domain: Option<Box<str>>,
102	pub base_password: Option<Box<str>>,
103	pub dist_dir: Box<Path>,
104	pub tmp_dir: Box<Path>,
105	pub acme_email: Option<Box<str>>,
106	pub local_address: Box<[Box<str>]>,
107	/// Disable HTTP caching (for development)
108	pub disable_cache: bool,
109}
110
111// vim: ts=4