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 session_fields(&self) -> indexmap::IndexMap<String, crate::field_policy::FieldConfig> {
128 indexmap::IndexMap::new()
129 }
130
131 fn user_fields(&self) -> crate::field_policy::FieldConfigs {
132 crate::field_policy::FieldConfigs::new()
133 }
134
135 fn account_fields(&self) -> crate::field_policy::FieldConfigs {
136 crate::field_policy::FieldConfigs::new()
137 }
138
139 fn openapi_metadata(&self, _ctx: &AuthInitContext<S>) -> crate::openapi::PluginOpenApiMetadata {
142 self.static_openapi_metadata()
143 }
144
145 fn static_openapi_metadata(&self) -> crate::openapi::PluginOpenApiMetadata {
147 crate::openapi::annotations::route_metadata(&self.routes())
148 }
149
150 async fn on_init(&self, _ctx: &mut AuthInitContext<S>) -> AuthResult<()> {
152 Ok(())
153 }
154
155 async fn on_http_request(
160 &self,
161 _req: &AuthRequest,
162 _ctx: &AuthContext<S>,
163 ) -> AuthResult<Option<AuthResponse>> {
164 Ok(None)
165 }
166
167 async fn on_http_request_action(
171 &self,
172 req: &AuthRequest,
173 ctx: &AuthContext<S>,
174 ) -> AuthResult<Option<HttpRequestAction>> {
175 Ok(self
176 .on_http_request(req, ctx)
177 .await?
178 .map(HttpRequestAction::Respond))
179 }
180
181 async fn on_http_response(
186 &self,
187 _req: &AuthRequest,
188 _ctx: &AuthContext<S>,
189 _response: &AuthResponse,
190 ) -> AuthResult<Option<AuthResponse>> {
191 Ok(None)
192 }
193
194 async fn before_request(
202 &self,
203 _req: &AuthRequest,
204 _ctx: &AuthContext<S>,
205 ) -> AuthResult<Option<BeforeRequestAction>> {
206 Ok(None)
207 }
208
209 async fn on_request(
211 &self,
212 req: &AuthRequest,
213 ctx: &AuthContext<S>,
214 ) -> AuthResult<Option<AuthResponse>>;
215
216 async fn on_http_endpoint(
220 &self,
221 req: &AuthRequest,
222 ctx: &AuthContext<S>,
223 ) -> AuthResult<Option<HttpEndpointResponse>> {
224 Ok(self
225 .on_request(req, ctx)
226 .await?
227 .map(HttpEndpointResponse::Value))
228 }
229
230 async fn after_request(
235 &self,
236 _req: &AuthRequest,
237 _ctx: &AuthContext<S>,
238 response: AuthResponse,
239 ) -> AuthResult<AuthResponse> {
240 Ok(response)
241 }
242
243 async fn on_user_created(&self, _user: &S::User, _ctx: &AuthContext<S>) -> AuthResult<()> {
245 Ok(())
246 }
247
248 async fn on_session_created(
250 &self,
251 _session: &S::Session,
252 _ctx: &AuthContext<S>,
253 ) -> AuthResult<()> {
254 Ok(())
255 }
256
257 async fn on_user_deleted(&self, _user_id: &str, _ctx: &AuthContext<S>) -> AuthResult<()> {
259 Ok(())
260 }
261
262 async fn on_session_deleted(
264 &self,
265 _session_token: &str,
266 _ctx: &AuthContext<S>,
267 ) -> AuthResult<()> {
268 Ok(())
269 }
270}
271
272impl<S: AuthSchema> std::fmt::Debug for VerificationEmailOverrideHandle<S> {
273 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
274 f.debug_struct("VerificationEmailOverrideHandle")
275 .finish_non_exhaustive()
276 }
277}