Skip to main content

shared/extensions/
manager.rs

1use crate::{
2    State,
3    extensions::{
4        ConstructedExtension, ExtensionPermissionsBuilder, ExtensionRouteBuilder,
5        commands::CliCommandGroupBuilder,
6    },
7};
8use std::sync::Arc;
9use tokio::sync::{RwLock, RwLockReadGuard};
10
11pub struct ExtensionManager {
12    vec: RwLock<Vec<ConstructedExtension>>,
13}
14
15impl ExtensionManager {
16    pub fn new(vec: Vec<ConstructedExtension>) -> Self {
17        Self {
18            vec: RwLock::new(vec),
19        }
20    }
21
22    pub async fn init(
23        &self,
24        state: State,
25    ) -> (
26        ExtensionRouteBuilder,
27        super::background_tasks::BackgroundTaskBuilder,
28        super::shutdown_handlers::ShutdownHandlerBuilder,
29    ) {
30        let mut route_builder = ExtensionRouteBuilder::new(state.clone());
31        let mut email_templates_builder =
32            super::email_templates::ExtensionEmailTemplateBuilder::default();
33        let mut background_tasks_builder =
34            super::background_tasks::BackgroundTaskBuilder::new(state.clone());
35        let mut shutdown_handlers_builder =
36            super::shutdown_handlers::ShutdownHandlerBuilder::new(state.clone());
37        let mut permissions_builder = ExtensionPermissionsBuilder::new(
38            crate::permissions::BASE_USER_PERMISSIONS.clone(),
39            crate::permissions::BASE_ADMIN_PERMISSIONS.clone(),
40            crate::permissions::BASE_SERVER_PERMISSIONS.clone(),
41        );
42
43        for ext in self.vec.read().await.iter() {
44            let deserializer = ext.settings_deserializer(state.clone()).await;
45            crate::settings::SETTINGS_DESER_EXTENSIONS
46                .write()
47                .unwrap()
48                .insert(ext.package_name, deserializer);
49        }
50        state.settings.invalidate_cache().await;
51
52        for ext in self.vec.write().await.iter_mut() {
53            let ext = match Arc::get_mut(&mut ext.extension) {
54                Some(ext) => ext,
55                None => {
56                    panic!(
57                        "Failed to get mutable reference to extension {}. This should NEVER happen.",
58                        ext.package_name
59                    );
60                }
61            };
62
63            ext.initialize(state.clone()).await;
64
65            route_builder = ext.initialize_router(state.clone(), route_builder).await;
66            email_templates_builder = ext
67                .initialize_email_templates(state.clone(), email_templates_builder)
68                .await;
69            background_tasks_builder = ext
70                .initialize_background_tasks(state.clone(), background_tasks_builder)
71                .await;
72            shutdown_handlers_builder = ext
73                .initialize_shutdown_handlers(state.clone(), shutdown_handlers_builder)
74                .await;
75            permissions_builder = ext
76                .initialize_permissions(state.clone(), permissions_builder)
77                .await;
78        }
79
80        *state.mail.templates.templates.write().unwrap() = email_templates_builder.finish();
81
82        crate::permissions::USER_PERMISSIONS
83            .write()
84            .unwrap()
85            .replace(permissions_builder.user_permissions);
86        crate::permissions::ADMIN_PERMISSIONS
87            .write()
88            .unwrap()
89            .replace(permissions_builder.admin_permissions);
90        crate::permissions::SERVER_PERMISSIONS
91            .write()
92            .unwrap()
93            .replace(permissions_builder.server_permissions);
94
95        (
96            route_builder,
97            background_tasks_builder,
98            shutdown_handlers_builder,
99        )
100    }
101
102    pub async fn init_cli(
103        &self,
104        env: Option<&Arc<crate::env::Env>>,
105        mut builder: CliCommandGroupBuilder,
106    ) -> CliCommandGroupBuilder {
107        for ext in self.vec.write().await.iter_mut() {
108            let ext = match Arc::get_mut(&mut ext.extension) {
109                Some(ext) => ext,
110                None => {
111                    panic!(
112                        "Failed to get mutable reference to extension {}. This should NEVER happen.",
113                        ext.package_name
114                    );
115                }
116            };
117
118            builder = ext.initialize_cli(env, builder).await;
119        }
120
121        builder
122    }
123
124    #[inline]
125    pub async fn extensions(&self) -> RwLockReadGuard<'_, Vec<ConstructedExtension>> {
126        self.vec.read().await
127    }
128
129    #[inline]
130    pub fn blocking_extensions(&self) -> RwLockReadGuard<'_, Vec<ConstructedExtension>> {
131        self.vec.blocking_read()
132    }
133
134    pub async fn call(
135        &self,
136        name: impl AsRef<str>,
137        args: &[super::ExtensionCallValue],
138    ) -> Option<super::ExtensionCallValue> {
139        for ext in self.extensions().await.iter() {
140            if let Some(ret) = ext.process_call(name.as_ref(), args).await {
141                return Some(ret);
142            }
143        }
144
145        None
146    }
147}