use std::borrow::Cow;
use kayrx::web::dev::{Payload, ServiceRequest};
use kayrx::http::header::Header;
use kayrx::web::{FromRequest, HttpRequest};
use futures::future;
use super::config::AuthExtractorConfig;
use super::errors::AuthenticationError;
use super::AuthExtractor;
use crate::headers::authorization::{Authorization, Basic};
use crate::headers::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
}
}
#[allow(clippy::needless_doctest_main)]
#[derive(Debug, Clone)]
pub struct BasicAuth(Basic);
impl BasicAuth {
pub fn user_id(&self) -> &Cow<'static, str> {
&self.0.user_id()
}
pub fn password(&self) -> Option<&Cow<'static, str>> {
self.0.password()
}
}
impl FromRequest for BasicAuth {
type Future = future::Ready<Result<Self, Self::Error>>;
type Config = Config;
type Error = AuthenticationError<Challenge>;
fn from_request(
req: &HttpRequest,
_: &mut Payload,
) -> <Self as FromRequest>::Future {
future::ready(
Authorization::<Basic>::parse(req)
.map(|auth| BasicAuth(auth.into_scheme()))
.map_err(|_| {
let challenge = req
.app_data::<Self::Config>()
.map(|config| config.0.clone())
.unwrap_or_else(Default::default);
AuthenticationError::new(challenge)
}),
)
}
}
impl AuthExtractor for BasicAuth {
type Error = AuthenticationError<Challenge>;
type Future = future::Ready<Result<Self, Self::Error>>;
fn from_service_request(req: &ServiceRequest) -> Self::Future {
future::ready(
Authorization::<Basic>::parse(req)
.map(|auth| BasicAuth(auth.into_scheme()))
.map_err(|_| {
let challenge = req
.app_data::<Config>()
.map(|config| config.0.clone())
.unwrap_or_else(Default::default);
AuthenticationError::new(challenge)
}),
)
}
}