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 #[must_use]
133 pub fn database_with_registered_transforms(&self) -> Arc<dyn AuthStore<S>> {
134 let transforms = self
135 .extensions
136 .cloned_or_default::<crate::store::UserTransforms>();
137 let session_callbacks = self
138 .extensions
139 .cloned_or_default::<crate::store::SessionCreatedCallbacks<S>>();
140 let fields = self.extensions.get::<crate::field_policy::SessionFields>();
141 if self.config.session.secondary_storage.is_none()
142 && transforms.creates.is_empty()
143 && transforms.updates.is_empty()
144 && session_callbacks.callbacks.is_empty()
145 && fields.is_none()
146 && self.config.user.additional_fields.is_empty()
147 && self.config.session.additional_fields.is_empty()
148 && self.config.account.additional_fields.is_empty()
149 && self
150 .extensions
151 .get::<crate::store::AdapterCallbacks<S>>()
152 .is_none_or(|callbacks| callbacks.0.is_empty())
153 && self.config.user_validation.is_none()
154 {
155 return Arc::clone(&self.database);
156 }
157 Arc::new(crate::store::PluginStore::new(
158 Arc::clone(&self.database),
159 Arc::clone(&self.config),
160 transforms,
161 session_callbacks,
162 fields.map_or_else(
163 || {
164 crate::field_policy::SessionFields(
165 self.config.session.additional_fields.clone(),
166 )
167 },
168 |fields| (*fields).clone(),
169 ),
170 self.extensions
171 .get::<crate::field_policy::SessionAdapterFields>()
172 .map_or_else(
173 || {
174 crate::field_policy::SessionAdapterFields(Arc::new(
175 self.config.session.additional_fields.clone(),
176 ))
177 },
178 |fields| (*fields).clone(),
179 ),
180 AuthContext::with_metadata(
181 Arc::clone(&self.config),
182 Arc::clone(&self.database),
183 self.metadata.clone(),
184 )
185 .with_extensions(self.extensions.clone()),
186 ))
187 }
188
189 pub fn set_email_verification_override(
190 &mut self,
191 sender: Arc<dyn VerificationEmailOverride<S>>,
192 ) {
193 self.extensions
194 .insert(VerificationEmailOverrideHandle(sender));
195 }
196
197 #[must_use]
198 pub fn into_parts(self) -> AuthInitParts {
199 AuthInitParts {
200 metadata: self.metadata,
201 email_provider: self.email_provider,
202 extensions: self.extensions,
203 }
204 }
205}
206
207impl std::fmt::Debug for AuthInitParts {
208 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
209 f.debug_struct("AuthInitParts").finish_non_exhaustive()
210 }
211}
212
213impl<S: AuthSchema> std::fmt::Debug for AuthInitContext<S> {
214 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
215 f.debug_struct("AuthInitContext").finish_non_exhaustive()
216 }
217}