alibi_api/plugins/admin/
callbacks.rs1use alibi_core::{AuthError, AuthResult, entity::AuthUser};
3use async_trait::async_trait;
4use std::{
5 any::{Any, TypeId},
6 fmt,
7 sync::Arc,
8};
9
10#[async_trait]
19pub trait AdminBannedUserMessage<U: AuthUser>: Send + Sync + 'static {
20 async fn message(&self, user: &U) -> AuthResult<String>;
21}
22
23#[async_trait]
24trait ErasedMessage: Send + Sync {
25 fn user_type(&self) -> TypeId;
26 async fn message(&self, user: &(dyn Any + Send + Sync)) -> AuthResult<String>;
27}
28struct TypedMessage<U, H> {
29 handler: H,
30 marker: std::marker::PhantomData<fn() -> U>,
31}
32#[async_trait]
33impl<U: AuthUser, H: AdminBannedUserMessage<U>> ErasedMessage for TypedMessage<U, H> {
34 fn user_type(&self) -> TypeId {
35 TypeId::of::<U>()
36 }
37 async fn message(&self, user: &(dyn Any + Send + Sync)) -> AuthResult<String> {
38 let user = user.downcast_ref::<U>().or_else(|| user.downcast_ref::<alibi_core::AdapterRecord<U>>().map(alibi_core::AdapterRecord::stored)).ok_or_else(|| AuthError::config(
39 "Admin banned-user message callback user type does not match the authentication schema"
40 ))?;
41 self.handler
42 .message(user)
43 .await
44 .map_err(|error| match error {
45 AuthError::Internal(_) => AuthError::CallbackFailure(Box::new(error)),
46 other => other,
47 })
48 }
49}
50
51#[derive(Clone)]
53pub struct AdminBannedUserMessageHandler(Arc<dyn ErasedMessage>);
54impl fmt::Debug for AdminBannedUserMessageHandler {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 f.write_str("AdminBannedUserMessageHandler(..)")
57 }
58}
59impl AdminBannedUserMessageHandler {
60 #[must_use]
62 pub fn new<U: AuthUser, H: AdminBannedUserMessage<U>>(handler: H) -> Self {
63 Self(Arc::new(TypedMessage::<U, H> {
64 handler,
65 marker: std::marker::PhantomData,
66 }))
67 }
68 pub(super) fn validate<U: AuthUser>(&self) -> AuthResult<()> {
72 if self.0.user_type() != TypeId::of::<U>()
73 && self.0.user_type() != TypeId::of::<alibi_core::AdapterRecord<U>>()
74 {
75 return Err(AuthError::config(
76 "Admin banned-user message callback user type does not match the authentication schema",
77 ));
78 }
79 Ok(())
80 }
81 pub(super) async fn message<U: AuthUser>(&self, user: &U) -> AuthResult<String> {
85 self.0.message(user).await
86 }
87}
88
89#[derive(Clone)]
90pub(in crate::plugins) struct BannedUserMessagePolicy(pub(super) AdminBannedUserMessageHandler);
91impl BannedUserMessagePolicy {
92 pub(in crate::plugins) async fn message<U: AuthUser>(&self, user: &U) -> AuthResult<String> {
96 self.0.message(user).await
97 }
98}