Skip to main content

better_auth_api/plugins/magic_link/
callbacks.rs

1use super::{MagicLinkMessage, MagicLinkPlugin};
2use crate::plugins::endpoint_context::{EndpointContext, WithCallbacks};
3use better_auth_core::{AuthPlugin, AuthResult, AuthSchema};
4use std::{future::Future, pin::Pin, sync::Arc};
5
6/// A sender future that can borrow the message and active endpoint.
7pub type MagicLinkCallbackFuture<'a> = Pin<Box<dyn Future<Output = AuthResult<()>> + Send + 'a>>;
8type Sender<S> = dyn for<'a> Fn(&'a MagicLinkMessage, &'a EndpointContext<'_, S>) -> MagicLinkCallbackFuture<'a>
9    + Send
10    + Sync;
11
12/// Magic-link delivery with the parsed input and typed authentication runtime.
13pub struct MagicLinkCallbacks<S: AuthSchema> {
14    pub(super) sender: Arc<Sender<S>>,
15}
16
17impl<S: AuthSchema> MagicLinkCallbacks<S> {
18    /// Deliver a link after the verification proof has been stored.
19    pub fn new<F>(sender: F) -> Self
20    where
21        F: for<'a> Fn(
22                &'a MagicLinkMessage,
23                &'a EndpointContext<'_, S>,
24            ) -> MagicLinkCallbackFuture<'a>
25            + Send
26            + Sync
27            + 'static,
28    {
29        Self {
30            sender: Arc::new(sender),
31        }
32    }
33}
34
35impl MagicLinkPlugin {
36    /// Attach schema-aware delivery after configuring plugin options.
37    pub fn callbacks<S: AuthSchema>(self, callbacks: MagicLinkCallbacks<S>) -> impl AuthPlugin<S> {
38        WithCallbacks {
39            plugin: self,
40            callbacks: Arc::new(callbacks),
41        }
42    }
43}