use std::fmt;
use std::sync::Arc;
use http::Request;
use crate::db::User;
use crate::error::OpenAuthError;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct VerificationEmail {
pub user: User,
pub url: String,
pub token: String,
}
pub trait SendVerificationEmail: Send + Sync + 'static {
fn send_verification_email(
&self,
email: VerificationEmail,
request: Option<&Request<Vec<u8>>>,
) -> Result<(), OpenAuthError>;
}
impl<F> SendVerificationEmail for F
where
F: for<'a> Fn(VerificationEmail, Option<&'a Request<Vec<u8>>>) -> Result<(), OpenAuthError>
+ Send
+ Sync
+ 'static,
{
fn send_verification_email(
&self,
email: VerificationEmail,
request: Option<&Request<Vec<u8>>>,
) -> Result<(), OpenAuthError> {
self(email, request)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EmailVerificationCallbackPayload {
pub user: User,
}
pub trait BeforeEmailVerification: Send + Sync + 'static {
fn before_email_verification(
&self,
payload: EmailVerificationCallbackPayload,
request: Option<&Request<Vec<u8>>>,
) -> Result<(), OpenAuthError>;
}
impl<F> BeforeEmailVerification for F
where
F: for<'a> Fn(
EmailVerificationCallbackPayload,
Option<&'a Request<Vec<u8>>>,
) -> Result<(), OpenAuthError>
+ Send
+ Sync
+ 'static,
{
fn before_email_verification(
&self,
payload: EmailVerificationCallbackPayload,
request: Option<&Request<Vec<u8>>>,
) -> Result<(), OpenAuthError> {
self(payload, request)
}
}
pub trait AfterEmailVerification: Send + Sync + 'static {
fn after_email_verification(
&self,
payload: EmailVerificationCallbackPayload,
request: Option<&Request<Vec<u8>>>,
) -> Result<(), OpenAuthError>;
}
impl<F> AfterEmailVerification for F
where
F: for<'a> Fn(
EmailVerificationCallbackPayload,
Option<&'a Request<Vec<u8>>>,
) -> Result<(), OpenAuthError>
+ Send
+ Sync
+ 'static,
{
fn after_email_verification(
&self,
payload: EmailVerificationCallbackPayload,
request: Option<&Request<Vec<u8>>>,
) -> Result<(), OpenAuthError> {
self(payload, request)
}
}
#[derive(Clone, Default)]
pub struct EmailVerificationOptions {
pub send_verification_email: Option<Arc<dyn SendVerificationEmail>>,
pub before_email_verification: Option<Arc<dyn BeforeEmailVerification>>,
pub after_email_verification: Option<Arc<dyn AfterEmailVerification>>,
pub expires_in: Option<u64>,
pub auto_sign_in_after_verification: bool,
}
impl EmailVerificationOptions {
pub fn new() -> Self {
Self::default()
}
pub fn builder() -> Self {
Self::new()
}
#[must_use]
pub fn send_verification_email<S>(mut self, sender: S) -> Self
where
S: SendVerificationEmail,
{
self.send_verification_email = Some(Arc::new(sender));
self
}
#[must_use]
pub fn before_email_verification<B>(mut self, callback: B) -> Self
where
B: BeforeEmailVerification,
{
self.before_email_verification = Some(Arc::new(callback));
self
}
#[must_use]
pub fn after_email_verification<A>(mut self, callback: A) -> Self
where
A: AfterEmailVerification,
{
self.after_email_verification = Some(Arc::new(callback));
self
}
#[must_use]
pub fn expires_in(mut self, expires_in: u64) -> Self {
self.expires_in = Some(expires_in);
self
}
#[must_use]
pub fn auto_sign_in_after_verification(mut self, enabled: bool) -> Self {
self.auto_sign_in_after_verification = enabled;
self
}
}
impl fmt::Debug for EmailVerificationOptions {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("EmailVerificationOptions")
.field(
"send_verification_email",
&self
.send_verification_email
.as_ref()
.map(|_| "<send-verification-email>"),
)
.field(
"before_email_verification",
&self
.before_email_verification
.as_ref()
.map(|_| "<before-email-verification>"),
)
.field(
"after_email_verification",
&self
.after_email_verification
.as_ref()
.map(|_| "<after-email-verification>"),
)
.field("expires_in", &self.expires_in)
.field(
"auto_sign_in_after_verification",
&self.auto_sign_in_after_verification,
)
.finish()
}
}