use super::UserManagementPlugin;
use crate::plugins::{
email_verification::VerificationEmail,
endpoint_context::{EndpointContext, WithCallbacks},
};
use better_auth_core::{AuthPlugin, AuthResult, AuthSchema, background::BackgroundFuture};
use std::sync::Arc;
#[derive(Clone)]
pub struct ChangeEmailConfirmation {
pub user: better_auth_core::FieldValue,
pub new_email: String,
pub url: String,
pub token: String,
}
impl ChangeEmailConfirmation {
pub fn user_view(&self) -> AuthResult<better_auth_core::wire::UserView> {
let fields = self.user.as_object().ok_or_else(|| {
better_auth_core::AuthError::internal("Confirmation User must be an object")
})?;
better_auth_core::wire::UserView::try_from(fields.snapshot_fields()?)
}
}
type Sender<S, M> =
dyn Fn(&M, &EndpointContext<'_, S>) -> AuthResult<Option<BackgroundFuture>> + Send + Sync;
pub struct UserManagementCallbacks<S: AuthSchema> {
pub(super) confirmation: Option<Arc<Sender<S, ChangeEmailConfirmation>>>,
pub(super) deletion: Option<Arc<Sender<S, VerificationEmail>>>,
}
impl<S: AuthSchema> Default for UserManagementCallbacks<S> {
fn default() -> Self {
Self {
confirmation: None,
deletion: None,
}
}
}
impl<S: AuthSchema> UserManagementCallbacks<S> {
pub(crate) fn has_confirmation_sender(&self) -> bool {
self.confirmation.is_some()
}
pub fn new() -> Self {
Self::default()
}
pub fn change_email_confirmation(
mut self,
callback: impl Fn(
&ChangeEmailConfirmation,
&EndpointContext<'_, S>,
) -> AuthResult<Option<BackgroundFuture>>
+ Send
+ Sync
+ 'static,
) -> Self {
self.confirmation = Some(Arc::new(callback));
self
}
pub fn delete_account_verification(
mut self,
callback: impl Fn(
&VerificationEmail,
&EndpointContext<'_, S>,
) -> AuthResult<Option<BackgroundFuture>>
+ Send
+ Sync
+ 'static,
) -> Self {
self.deletion = Some(Arc::new(callback));
self
}
}
impl UserManagementPlugin {
pub fn callbacks<S: AuthSchema>(
self,
callbacks: UserManagementCallbacks<S>,
) -> impl AuthPlugin<S> {
WithCallbacks {
plugin: self,
callbacks: Arc::new(callbacks),
}
}
}