use std::fmt::Debug;
use std::sync::Arc;
use unftp_core::auth::{AuthenticationError, Authenticator, Credentials, UserDetail, UserDetailProvider};
#[derive(Debug)]
pub struct AuthenticationPipeline<User>
where
User: UserDetail,
{
authenticator: Arc<dyn Authenticator + Send + Sync>,
user_provider: Arc<dyn UserDetailProvider<User = User> + Send + Sync>,
}
impl<User> AuthenticationPipeline<User>
where
User: UserDetail,
{
pub fn new(authenticator: Arc<dyn Authenticator + Send + Sync>, user_provider: Arc<dyn UserDetailProvider<User = User> + Send + Sync>) -> Self {
Self { authenticator, user_provider }
}
pub async fn authenticate_and_get_user(&self, username: &str, creds: &Credentials) -> Result<User, AuthenticationError> {
let principal = self.authenticator.authenticate(username, creds).await?;
self.user_provider.provide_user_detail(&principal).await.map_err(|e| match e {
unftp_core::auth::UserDetailError::UserNotFound { .. } => AuthenticationError::BadUser,
unftp_core::auth::UserDetailError::Generic(msg) => AuthenticationError::new(msg),
unftp_core::auth::UserDetailError::ImplPropagated(msg, source) => AuthenticationError::ImplPropagated(msg, source),
})
}
pub async fn cert_auth_sufficient(&self, username: &str) -> bool {
self.authenticator.cert_auth_sufficient(username).await
}
pub fn name(&self) -> &str {
self.authenticator.name()
}
}