use better_auth_core::{AuthResult, wire::UserView};
use std::{fmt, future::Future, pin::Pin, sync::Arc};
pub type BannedUserMessageFuture<'a> =
Pin<Box<dyn Future<Output = AuthResult<String>> + Send + 'a>>;
type MessageCallback = dyn for<'a> Fn(&'a UserView) -> BannedUserMessageFuture<'a> + Send + Sync;
#[derive(Clone)]
pub enum BannedUserMessage {
Text(String),
Callback(Arc<MessageCallback>),
}
impl BannedUserMessage {
pub fn callback<F>(callback: F) -> Self
where
F: for<'a> Fn(&'a UserView) -> BannedUserMessageFuture<'a> + Send + Sync + 'static,
{
Self::Callback(Arc::new(callback))
}
pub(crate) async fn resolve(&self, user: &UserView) -> AuthResult<String> {
match self {
Self::Text(message) => Ok(message.clone()),
Self::Callback(callback) => callback(user).await,
}
}
}
impl Default for BannedUserMessage {
fn default() -> Self {
Self::Text("You have been banned from this application. Please contact support if you believe this is an error.".into())
}
}
impl From<String> for BannedUserMessage {
fn from(message: String) -> Self {
Self::Text(message)
}
}
impl From<&str> for BannedUserMessage {
fn from(message: &str) -> Self {
Self::Text(message.into())
}
}
impl fmt::Debug for BannedUserMessage {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Text(message) => formatter.debug_tuple("Text").field(message).finish(),
Self::Callback(_) => formatter.write_str("Callback(..)"),
}
}
}