alibi_core/plugin/
initialization.rs1use crate::plugin::MetadataMap;
2use crate::{
3 AuthConfig, AuthContext, AuthResult, AuthSchema, AuthStore, ContextExtensions, EmailProvider,
4 VerificationEmailOverride, VerificationEmailOverrideHandle,
5};
6use std::sync::Arc;
7pub struct AuthInitParts {
8 pub metadata: MetadataMap,
9 pub email_provider: Option<Arc<dyn EmailProvider>>,
10 pub extensions: ContextExtensions,
11}
12
13pub struct AuthInitContext<S: AuthSchema> {
15 pub config: Arc<AuthConfig>,
16 pub database: Arc<dyn AuthStore<S>>,
17 pub email_provider: Option<Arc<dyn EmailProvider>>,
18 pub metadata: MetadataMap,
19 pub extensions: ContextExtensions,
20}
21
22impl<S: AuthSchema> AuthInitContext<S> {
23 #[must_use]
24 pub fn new(config: Arc<AuthConfig>, database: Arc<dyn AuthStore<S>>) -> Self {
25 let email_provider = config.email_provider.clone();
26 Self {
27 config,
28 database,
29 email_provider,
30 metadata: MetadataMap::new(),
31 extensions: ContextExtensions::default(),
32 }
33 }
34
35 pub fn set_metadata(&mut self, key: impl Into<String>, value: serde_json::Value) {
36 _ = self.metadata.insert(key.into(), value);
37 }
38
39 pub fn register_password_hash_hook(
42 &mut self,
43 hook: Arc<dyn crate::utils::password::PasswordHashHook>,
44 ) {
45 let mut hooks = self
46 .extensions
47 .cloned_or_default::<crate::utils::password::PasswordHashHooks>();
48 hooks.0.push(hook);
49 self.extensions.insert(hooks);
50 }
51
52 #[must_use]
53 pub fn get_metadata(&self, key: &str) -> Option<&serde_json::Value> {
54 self.metadata.get(key)
55 }
56
57 pub fn register_user_create_transform<F>(&mut self, transform: F)
59 where
60 F: Fn(crate::types::CreateUser) -> AuthResult<crate::types::CreateUser>
61 + Send
62 + Sync
63 + 'static,
64 {
65 let mut transforms = self
66 .extensions
67 .cloned_or_default::<crate::store::UserTransforms>();
68 transforms.creates.push(Arc::new(transform));
69 self.extensions.insert(transforms);
70 }
71
72 pub fn register_user_creation_adapter_default<F>(&mut self, default: F)
75 where
76 F: Fn(crate::types::CreateUser) -> AuthResult<crate::types::CreateUser>
77 + Send
78 + Sync
79 + 'static,
80 {
81 let mut transforms = self
82 .extensions
83 .cloned_or_default::<crate::store::UserTransforms>();
84 transforms.adapter_defaults.0.push(Arc::new(default));
85 self.extensions.insert(transforms);
86 }
87
88 pub fn register_user_update_transform<F>(&mut self, transform: F)
90 where
91 F: Fn(&str, crate::types::UpdateUser) -> AuthResult<crate::types::UpdateUser>
92 + Send
93 + Sync
94 + 'static,
95 {
96 let mut transforms = self
97 .extensions
98 .cloned_or_default::<crate::store::UserTransforms>();
99 transforms.updates.push(Arc::new(transform));
100 self.extensions.insert(transforms);
101 }
102
103 pub fn register_session_created_hook(
108 &mut self,
109 callback: Arc<dyn crate::store::SessionCreatedHook<S>>,
110 ) {
111 let mut callbacks = self
112 .extensions
113 .cloned_or_default::<crate::store::SessionCreatedCallbacks<S>>();
114 callbacks.callbacks.push(callback);
115 self.extensions.insert(callbacks);
116 }
117
118 pub fn register_adapter_after_hook(
121 &mut self,
122 callback: Arc<dyn crate::store::AdapterAfterHook<S>>,
123 ) {
124 let mut callbacks = self
125 .extensions
126 .cloned_or_default::<crate::store::AdapterCallbacks<S>>();
127 callbacks.0.push(callback);
128 self.extensions.insert(callbacks);
129 }
130
131 pub fn register_session_deletion_hook(
133 &mut self,
134 hook: Arc<dyn crate::store::SessionDeletionHook<S>>,
135 ) {
136 let mut hooks = self
137 .extensions
138 .cloned_or_default::<crate::store::SessionDeletionHooks<S>>();
139 hooks.0.push(hook);
140 self.extensions.insert(hooks);
141 }
142 #[must_use]
144 pub fn database_with_registered_transforms(&self) -> Arc<dyn AuthStore<S>> {
145 let transforms = self
146 .extensions
147 .cloned_or_default::<crate::store::UserTransforms>();
148 let session_callbacks = self
149 .extensions
150 .cloned_or_default::<crate::store::SessionCreatedCallbacks<S>>();
151 let fields = self.extensions.get::<crate::field_policy::SessionFields>();
152 if self.config.session.secondary_storage.is_none()
153 && transforms.creates.is_empty()
154 && transforms.updates.is_empty()
155 && session_callbacks.callbacks.is_empty()
156 && fields.is_none()
157 && self.config.user.additional_fields.is_empty()
158 && self.config.session.additional_fields.is_empty()
159 && self.config.account.additional_fields.is_empty()
160 && self
161 .extensions
162 .get::<crate::store::AdapterCallbacks<S>>()
163 .is_none_or(|callbacks| callbacks.0.is_empty())
164 && self
165 .extensions
166 .get::<crate::store::SessionDeletionHooks<S>>()
167 .is_none_or(|hooks| hooks.0.is_empty())
168 && self.config.user_validation.is_none()
169 {
170 return Arc::clone(&self.database);
171 }
172 Arc::new(crate::store::PluginStore::new(
173 Arc::clone(&self.database),
174 Arc::clone(&self.config),
175 transforms,
176 session_callbacks,
177 fields.map_or_else(
178 || {
179 crate::field_policy::SessionFields(
180 self.config.session.additional_fields.clone(),
181 )
182 },
183 |fields| (*fields).clone(),
184 ),
185 self.extensions
186 .get::<crate::field_policy::SessionAdapterFields>()
187 .map_or_else(
188 || {
189 crate::field_policy::SessionAdapterFields(Arc::new(
190 self.config.session.additional_fields.clone(),
191 ))
192 },
193 |fields| (*fields).clone(),
194 ),
195 AuthContext::with_metadata(
196 Arc::clone(&self.config),
197 Arc::clone(&self.database),
198 self.metadata.clone(),
199 )
200 .with_extensions(self.extensions.clone()),
201 ))
202 }
203
204 pub fn set_email_verification_override(
205 &mut self,
206 sender: Arc<dyn VerificationEmailOverride<S>>,
207 ) {
208 self.extensions
209 .insert(VerificationEmailOverrideHandle(sender));
210 }
211
212 #[must_use]
213 pub fn into_parts(self) -> AuthInitParts {
214 AuthInitParts {
215 metadata: self.metadata,
216 email_provider: self.email_provider,
217 extensions: self.extensions,
218 }
219 }
220}
221
222impl std::fmt::Debug for AuthInitParts {
223 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
224 f.debug_struct("AuthInitParts").finish_non_exhaustive()
225 }
226}
227
228impl<S: AuthSchema> std::fmt::Debug for AuthInitContext<S> {
229 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
230 f.debug_struct("AuthInitContext").finish_non_exhaustive()
231 }
232}