1#![allow(unused_variables)]
2
3use crate::{State, permissions::PermissionGroup};
4use indexmap::IndexMap;
5use serde::Serialize;
6use std::{ops::Deref, sync::Arc};
7use utoipa::ToSchema;
8use utoipa_axum::router::OpenApiRouter;
9
10pub mod background_tasks;
11pub mod commands;
12pub mod distr;
13pub mod manager;
14pub mod settings;
15pub mod shutdown_handlers;
16
17pub struct ExtensionRouteBuilder {
18 state: State,
19 pub global: Option<Box<OpenApiRouter<State>>>,
20 pub api_admin: Option<Box<OpenApiRouter<State>>>,
21 pub api_auth: Option<Box<OpenApiRouter<State>>>,
22 pub api_client: Option<Box<OpenApiRouter<State>>>,
23 pub api_client_servers_server: Option<Box<OpenApiRouter<State>>>,
24 pub api_remote: Option<Box<OpenApiRouter<State>>>,
25 pub api_remote_servers_server: Option<Box<OpenApiRouter<State>>>,
26}
27
28impl ExtensionRouteBuilder {
29 pub fn new(state: State) -> Self {
30 Self {
31 state,
32 global: None,
33 api_admin: None,
34 api_auth: None,
35 api_client: None,
36 api_client_servers_server: None,
37 api_remote: None,
38 api_remote_servers_server: None,
39 }
40 }
41
42 pub fn add_global_router(
44 mut self,
45 router: impl FnOnce(OpenApiRouter<State>) -> OpenApiRouter<State>,
46 ) -> Self {
47 self.global = Some(Box::new(router(self.global.map_or_else(
48 || OpenApiRouter::new().with_state(self.state.clone()),
49 |b| *b,
50 ))));
51
52 self
53 }
54
55 pub fn add_admin_api_router(
58 mut self,
59 router: impl FnOnce(OpenApiRouter<State>) -> OpenApiRouter<State>,
60 ) -> Self {
61 self.api_admin = Some(Box::new(router(self.api_admin.map_or_else(
62 || OpenApiRouter::new().with_state(self.state.clone()),
63 |b| *b,
64 ))));
65
66 self
67 }
68
69 pub fn add_auth_api_router(
71 mut self,
72 router: impl FnOnce(OpenApiRouter<State>) -> OpenApiRouter<State>,
73 ) -> Self {
74 self.api_auth = Some(Box::new(router(self.api_auth.map_or_else(
75 || OpenApiRouter::new().with_state(self.state.clone()),
76 |b| *b,
77 ))));
78
79 self
80 }
81
82 pub fn add_client_api_router(
85 mut self,
86 router: impl FnOnce(OpenApiRouter<State>) -> OpenApiRouter<State>,
87 ) -> Self {
88 self.api_client = Some(Box::new(router(self.api_client.map_or_else(
89 || OpenApiRouter::new().with_state(self.state.clone()),
90 |b| *b,
91 ))));
92
93 self
94 }
95
96 pub fn add_client_server_api_router(
99 mut self,
100 router: impl FnOnce(OpenApiRouter<State>) -> OpenApiRouter<State>,
101 ) -> Self {
102 self.api_client_servers_server = Some(Box::new(router(
103 self.api_client_servers_server.map_or_else(
104 || OpenApiRouter::new().with_state(self.state.clone()),
105 |b| *b,
106 ),
107 )));
108
109 self
110 }
111
112 pub fn add_remote_api_router(
115 mut self,
116 router: impl FnOnce(OpenApiRouter<State>) -> OpenApiRouter<State>,
117 ) -> Self {
118 self.api_remote = Some(Box::new(router(self.api_remote.map_or_else(
119 || OpenApiRouter::new().with_state(self.state.clone()),
120 |b| *b,
121 ))));
122
123 self
124 }
125
126 pub fn add_remote_server_api_router(
129 mut self,
130 router: impl FnOnce(OpenApiRouter<State>) -> OpenApiRouter<State>,
131 ) -> Self {
132 self.api_remote_servers_server = Some(Box::new(router(
133 self.api_remote_servers_server.map_or_else(
134 || OpenApiRouter::new().with_state(self.state.clone()),
135 |b| *b,
136 ),
137 )));
138
139 self
140 }
141}
142
143type RawPermissionMap = IndexMap<&'static str, PermissionGroup>;
144pub struct ExtensionPermissionsBuilder {
145 pub user_permissions: RawPermissionMap,
146 pub admin_permissions: RawPermissionMap,
147 pub server_permissions: RawPermissionMap,
148}
149
150impl ExtensionPermissionsBuilder {
151 pub fn new(
152 user_permissions: RawPermissionMap,
153 admin_permissions: RawPermissionMap,
154 server_permissions: RawPermissionMap,
155 ) -> Self {
156 Self {
157 user_permissions,
158 admin_permissions,
159 server_permissions,
160 }
161 }
162
163 pub fn add_user_permission_group(
165 mut self,
166 group_name: &'static str,
167 group: PermissionGroup,
168 ) -> Self {
169 self.user_permissions.insert(group_name, group);
170
171 self
172 }
173
174 pub fn add_admin_permission_group(
176 mut self,
177 group_name: &'static str,
178 group: PermissionGroup,
179 ) -> Self {
180 self.admin_permissions.insert(group_name, group);
181
182 self
183 }
184
185 pub fn add_server_permission_group(
187 mut self,
188 group_name: &'static str,
189 group: PermissionGroup,
190 ) -> Self {
191 self.server_permissions.insert(group_name, group);
192
193 self
194 }
195}
196
197pub type ExtensionCallValue = Box<dyn std::any::Any + Send + Sync>;
198
199#[async_trait::async_trait]
200pub trait Extension: Send + Sync {
201 async fn initialize(&mut self, state: State) {}
203
204 async fn initialize_cli(
206 &mut self,
207 env: Option<&Arc<crate::env::Env>>,
208 builder: commands::CliCommandGroupBuilder,
209 ) -> commands::CliCommandGroupBuilder {
210 builder
211 }
212
213 async fn initialize_router(
215 &mut self,
216 state: State,
217 builder: ExtensionRouteBuilder,
218 ) -> ExtensionRouteBuilder {
219 builder
220 }
221
222 async fn initialize_background_tasks(
224 &mut self,
225 state: State,
226 builder: background_tasks::BackgroundTaskBuilder,
227 ) -> background_tasks::BackgroundTaskBuilder {
228 builder
229 }
230
231 async fn initialize_shutdown_handlers(
233 &mut self,
234 state: State,
235 builder: shutdown_handlers::ShutdownHandlerBuilder,
236 ) -> shutdown_handlers::ShutdownHandlerBuilder {
237 builder
238 }
239
240 async fn initialize_permissions(
242 &mut self,
243 state: State,
244 builder: ExtensionPermissionsBuilder,
245 ) -> ExtensionPermissionsBuilder {
246 builder
247 }
248
249 async fn settings_deserializer(&self, state: State) -> settings::ExtensionSettingsDeserializer {
253 Arc::new(settings::EmptySettings)
254 }
255
256 async fn process_call(
261 &self,
262 name: &str,
263 args: &[ExtensionCallValue],
264 ) -> Option<ExtensionCallValue> {
265 None
266 }
267
268 async fn process_call_owned(
275 &self,
276 name: &str,
277 args: Vec<ExtensionCallValue>,
278 ) -> Option<ExtensionCallValue> {
279 self.process_call(name, &args).await
280 }
281}
282
283#[derive(ToSchema, Serialize, Clone)]
284pub struct ConstructedExtension {
285 pub metadata_toml: distr::MetadataToml,
286 pub package_name: &'static str,
287 pub description: &'static str,
288 pub authors: &'static [&'static str],
289 #[schema(value_type = String)]
290 pub version: semver::Version,
291
292 #[serde(skip)]
293 #[schema(ignore)]
294 pub extension: Arc<dyn Extension>,
295}
296
297impl Deref for ConstructedExtension {
298 type Target = Arc<dyn Extension>;
299
300 fn deref(&self) -> &Self::Target {
301 &self.extension
302 }
303}