alibi_core/plugin/
contracts.rs1use crate::{
2 AuthContext, AuthError, AuthInitContext, AuthRequest, AuthResponse, AuthResult, AuthRoute,
3 AuthSchema,
4};
5use async_trait::async_trait;
6use std::collections::HashMap;
7use std::sync::Arc;
8#[async_trait]
10pub trait VerificationEmailOverride<S: AuthSchema>: Send + Sync {
11 async fn send(
12 &self,
13 user: &crate::wire::UserView,
14 request: Option<&AuthRequest>,
15 ctx: &AuthContext<S>,
16 ) -> AuthResult<()>;
17
18 async fn send_in_transaction(
19 &self,
20 user: &crate::wire::UserView,
21 request: Option<&AuthRequest>,
22 ctx: &AuthContext<S>,
23 _transaction: &dyn crate::store::AuthTransaction<S>,
24 ) -> AuthResult<()> {
25 self.send(user, request, ctx).await
26 }
27}
28
29pub struct VerificationEmailOverrideHandle<S: AuthSchema>(
30 pub Arc<dyn VerificationEmailOverride<S>>,
31);
32
33#[derive(Debug)]
35#[expect(
36 clippy::large_enum_variant,
37 reason = "Preserve public InjectSession construction as session views gain configured output policies"
38)]
39pub enum BeforeRequestAction {
40 Respond(AuthResponse),
42 InjectSession { session: crate::wire::SessionView },
44 ReplaceHeaders { headers: HashMap<String, String> },
48}
49
50#[derive(Debug)]
52pub enum HttpRequestAction {
53 Respond(AuthResponse),
55 ReplaceRequest(Box<AuthRequest>),
58}
59
60#[derive(Debug)]
64pub enum HttpEndpointResponse {
65 Value(AuthResponse),
66 Raw(AuthResponse),
67}
68
69#[async_trait]
71pub trait AuthPlugin<S: AuthSchema>: Send + Sync {
72 fn name(&self) -> &'static str;
74
75 fn routes(&self) -> Vec<AuthRoute>;
77
78 fn rate_limits(&self) -> Vec<crate::middleware::rate_limit::PluginRateLimit> {
80 Vec::new()
81 }
82
83 fn server_endpoints(&self) -> Vec<crate::endpoint::EndpointDefinition> {
85 Vec::new()
86 }
87
88 fn endpoint_hooks(&self) -> Vec<&dyn crate::endpoint::EndpointHook<S>> {
90 Vec::new()
91 }
92
93 fn validate_endpoint(
97 &self,
98 call: &crate::endpoint::EndpointCall,
99 _ctx: &AuthContext<S>,
100 ) -> AuthResult<crate::endpoint::EndpointInput> {
101 Ok(crate::endpoint::EndpointInput {
102 body: call.body().cloned(),
103 query: call.query().cloned(),
104 })
105 }
106
107 async fn on_endpoint(
111 &self,
112 _call: &crate::endpoint::EndpointCall,
113 _ctx: &AuthContext<S>,
114 ) -> AuthResult<crate::endpoint::EndpointResponse> {
115 Err(AuthError::not_implemented(
116 "This plugin does not implement trusted endpoint calls",
117 ))
118 }
119
120 fn allowed_media_types(&self, _route: &AuthRoute) -> Vec<&'static str> {
123 vec!["application/json"]
124 }
125
126 fn origin_check_skip_paths(&self) -> Vec<&'static str> {
128 Vec::new()
129 }
130
131 fn session_fields(&self) -> indexmap::IndexMap<String, crate::field_policy::FieldConfig> {
133 indexmap::IndexMap::new()
134 }
135
136 fn user_fields(&self) -> crate::field_policy::FieldConfigs {
137 crate::field_policy::FieldConfigs::new()
138 }
139
140 fn account_fields(&self) -> crate::field_policy::FieldConfigs {
141 crate::field_policy::FieldConfigs::new()
142 }
143
144 fn openapi_metadata(&self, _ctx: &AuthInitContext<S>) -> crate::openapi::PluginOpenApiMetadata {
147 self.static_openapi_metadata()
148 }
149
150 fn static_openapi_metadata(&self) -> crate::openapi::PluginOpenApiMetadata {
152 crate::openapi::annotations::route_metadata(&self.routes())
153 }
154
155 async fn on_init(&self, _ctx: &mut AuthInitContext<S>) -> AuthResult<()> {
157 Ok(())
158 }
159
160 async fn on_http_request(
165 &self,
166 _req: &AuthRequest,
167 _ctx: &AuthContext<S>,
168 ) -> AuthResult<Option<AuthResponse>> {
169 Ok(None)
170 }
171
172 async fn on_http_request_action(
176 &self,
177 req: &AuthRequest,
178 ctx: &AuthContext<S>,
179 ) -> AuthResult<Option<HttpRequestAction>> {
180 Ok(self
181 .on_http_request(req, ctx)
182 .await?
183 .map(HttpRequestAction::Respond))
184 }
185
186 async fn on_http_response(
191 &self,
192 _req: &AuthRequest,
193 _ctx: &AuthContext<S>,
194 _response: &AuthResponse,
195 ) -> AuthResult<Option<AuthResponse>> {
196 Ok(None)
197 }
198
199 async fn before_request(
207 &self,
208 _req: &AuthRequest,
209 _ctx: &AuthContext<S>,
210 ) -> AuthResult<Option<BeforeRequestAction>> {
211 Ok(None)
212 }
213
214 async fn on_request(
216 &self,
217 req: &AuthRequest,
218 ctx: &AuthContext<S>,
219 ) -> AuthResult<Option<AuthResponse>>;
220
221 async fn on_http_endpoint(
225 &self,
226 req: &AuthRequest,
227 ctx: &AuthContext<S>,
228 ) -> AuthResult<Option<HttpEndpointResponse>> {
229 Ok(self
230 .on_request(req, ctx)
231 .await?
232 .map(HttpEndpointResponse::Value))
233 }
234
235 async fn after_request(
240 &self,
241 _req: &AuthRequest,
242 _ctx: &AuthContext<S>,
243 response: AuthResponse,
244 ) -> AuthResult<AuthResponse> {
245 Ok(response)
246 }
247
248 async fn on_user_created(&self, _user: &S::User, _ctx: &AuthContext<S>) -> AuthResult<()> {
250 Ok(())
251 }
252
253 async fn on_session_created(
255 &self,
256 _session: &S::Session,
257 _ctx: &AuthContext<S>,
258 ) -> AuthResult<()> {
259 Ok(())
260 }
261
262 async fn on_user_deleted(&self, _user_id: &str, _ctx: &AuthContext<S>) -> AuthResult<()> {
264 Ok(())
265 }
266
267 async fn on_session_deleted(
269 &self,
270 _session_token: &str,
271 _ctx: &AuthContext<S>,
272 ) -> AuthResult<()> {
273 Ok(())
274 }
275}
276
277impl<S: AuthSchema> std::fmt::Debug for VerificationEmailOverrideHandle<S> {
278 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
279 f.debug_struct("VerificationEmailOverrideHandle")
280 .finish_non_exhaustive()
281 }
282}