use std::borrow::Cow;
use actix_utils::future::{ready, Ready};
use actix_web::{dev::Payload, http::header::Header, FromRequest, HttpRequest};
use super::{config::AuthExtractorConfig, errors::AuthenticationError};
use crate::headers::{
authorization::{Authorization, Basic},
www_authenticate::basic::Basic as Challenge,
};
#[derive(Debug, Clone, Default)]
pub struct Config(Challenge);
impl Config {
pub fn realm<T>(mut self, value: T) -> Config
where
T: Into<Cow<'static, str>>,
{
self.0.realm = Some(value.into());
self
}
}
impl AsRef<Challenge> for Config {
fn as_ref(&self) -> &Challenge {
&self.0
}
}
impl AuthExtractorConfig for Config {
type Inner = Challenge;
fn into_inner(self) -> Self::Inner {
self.0
}
}
#[derive(Debug, Clone)]
pub struct BasicAuth(Basic);
impl BasicAuth {
pub fn user_id(&self) -> &str {
self.0.user_id()
}
pub fn password(&self) -> Option<&str> {
self.0.password()
}
}
impl From<Basic> for BasicAuth {
fn from(basic: Basic) -> Self {
Self(basic)
}
}
impl FromRequest for BasicAuth {
type Future = Ready<Result<Self, Self::Error>>;
type Error = AuthenticationError<Challenge>;
fn from_request(req: &HttpRequest, _: &mut Payload) -> <Self as FromRequest>::Future {
ready(
Authorization::<Basic>::parse(req)
.map(|auth| BasicAuth(auth.into_scheme()))
.map_err(|err| {
log::debug!("`BasicAuth` extract error: {}", err);
let challenge = req
.app_data::<Config>()
.map(|config| config.0.clone())
.unwrap_or_default();
AuthenticationError::new(challenge)
}),
)
}
}