use super::*;
#[async_trait]
pub trait VerificationEmailOverride<S: AuthSchema>: Send + Sync {
async fn send(
&self,
user: &crate::wire::UserView,
request: Option<&AuthRequest>,
ctx: &AuthContext<S>,
) -> AuthResult<()>;
async fn send_in_transaction(
&self,
user: &crate::wire::UserView,
request: Option<&AuthRequest>,
ctx: &AuthContext<S>,
_transaction: &dyn crate::store::AuthTransaction<S>,
) -> AuthResult<()> {
self.send(user, request, ctx).await
}
}
pub struct VerificationEmailOverrideHandle<S: AuthSchema>(
pub Arc<dyn VerificationEmailOverride<S>>,
);
#[derive(Debug)]
#[expect(
clippy::large_enum_variant,
reason = "Preserve public InjectSession construction as session views gain configured output policies"
)]
pub enum BeforeRequestAction {
Respond(AuthResponse),
InjectSession { session: crate::wire::SessionView },
ReplaceHeaders { headers: HashMap<String, String> },
}
#[derive(Debug)]
pub enum HttpRequestAction {
Respond(AuthResponse),
ReplaceRequest(Box<AuthRequest>),
}
#[derive(Debug)]
pub enum HttpEndpointResponse {
Value(AuthResponse),
Raw(AuthResponse),
}
#[async_trait]
pub trait AuthPlugin<S: AuthSchema>: Send + Sync {
fn name(&self) -> &'static str;
fn routes(&self) -> Vec<AuthRoute>;
fn rate_limits(&self) -> Vec<crate::middleware::rate_limit::PluginRateLimit> {
Vec::new()
}
fn server_endpoints(&self) -> Vec<crate::endpoint::EndpointDefinition> {
Vec::new()
}
fn endpoint_hooks(&self) -> Vec<&dyn crate::endpoint::EndpointHook<S>> {
Vec::new()
}
fn validate_endpoint(
&self,
call: &crate::endpoint::EndpointCall,
_ctx: &AuthContext<S>,
) -> AuthResult<crate::endpoint::EndpointInput> {
Ok(crate::endpoint::EndpointInput {
body: call.body().cloned(),
query: call.query().cloned(),
})
}
async fn on_endpoint(
&self,
_call: &crate::endpoint::EndpointCall,
_ctx: &AuthContext<S>,
) -> AuthResult<crate::endpoint::EndpointResponse> {
Err(AuthError::not_implemented(
"This plugin does not implement trusted endpoint calls",
))
}
fn allowed_media_types(&self, _route: &AuthRoute) -> Vec<&'static str> {
vec!["application/json"]
}
fn session_fields(&self) -> indexmap::IndexMap<String, crate::field_policy::FieldConfig> {
indexmap::IndexMap::new()
}
fn user_fields(&self) -> crate::field_policy::FieldConfigs {
crate::field_policy::FieldConfigs::new()
}
fn account_fields(&self) -> crate::field_policy::FieldConfigs {
crate::field_policy::FieldConfigs::new()
}
fn openapi_metadata(&self, _ctx: &AuthInitContext<S>) -> crate::openapi::PluginOpenApiMetadata {
self.static_openapi_metadata()
}
fn static_openapi_metadata(&self) -> crate::openapi::PluginOpenApiMetadata {
crate::openapi::annotations::route_metadata(&self.routes())
}
async fn on_init(&self, _ctx: &mut AuthInitContext<S>) -> AuthResult<()> {
Ok(())
}
async fn on_http_request(
&self,
_req: &AuthRequest,
_ctx: &AuthContext<S>,
) -> AuthResult<Option<AuthResponse>> {
Ok(None)
}
async fn on_http_request_action(
&self,
req: &AuthRequest,
ctx: &AuthContext<S>,
) -> AuthResult<Option<HttpRequestAction>> {
Ok(self
.on_http_request(req, ctx)
.await?
.map(HttpRequestAction::Respond))
}
async fn on_http_response(
&self,
_req: &AuthRequest,
_ctx: &AuthContext<S>,
_response: &AuthResponse,
) -> AuthResult<Option<AuthResponse>> {
Ok(None)
}
async fn before_request(
&self,
_req: &AuthRequest,
_ctx: &AuthContext<S>,
) -> AuthResult<Option<BeforeRequestAction>> {
Ok(None)
}
async fn on_request(
&self,
req: &AuthRequest,
ctx: &AuthContext<S>,
) -> AuthResult<Option<AuthResponse>>;
async fn on_http_endpoint(
&self,
req: &AuthRequest,
ctx: &AuthContext<S>,
) -> AuthResult<Option<HttpEndpointResponse>> {
Ok(self
.on_request(req, ctx)
.await?
.map(HttpEndpointResponse::Value))
}
async fn after_request(
&self,
_req: &AuthRequest,
_ctx: &AuthContext<S>,
response: AuthResponse,
) -> AuthResult<AuthResponse> {
Ok(response)
}
async fn on_user_created(&self, _user: &S::User, _ctx: &AuthContext<S>) -> AuthResult<()> {
Ok(())
}
async fn on_session_created(
&self,
_session: &S::Session,
_ctx: &AuthContext<S>,
) -> AuthResult<()> {
Ok(())
}
async fn on_user_deleted(&self, _user_id: &str, _ctx: &AuthContext<S>) -> AuthResult<()> {
Ok(())
}
async fn on_session_deleted(
&self,
_session_token: &str,
_ctx: &AuthContext<S>,
) -> AuthResult<()> {
Ok(())
}
}
impl<S: AuthSchema> std::fmt::Debug for VerificationEmailOverrideHandle<S> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("VerificationEmailOverrideHandle")
.finish_non_exhaustive()
}
}