use std::collections::BTreeSet;
use std::io;
use std::marker::PhantomData;
use hyper;
use hyper::{Request, Response, Error};
use super::Push;
#[derive(Clone, Debug, PartialEq)]
pub enum Scopes {
Some(BTreeSet<String>),
All,
}
#[derive(Clone, Debug, PartialEq)]
pub struct Authorization {
pub subject: String,
pub scopes: Scopes,
pub issuer: Option<String>,
}
#[derive(Clone, Debug, PartialEq)]
pub enum AuthData {
Basic(hyper::header::Basic),
Bearer(hyper::header::Bearer),
ApiKey(String),
}
impl AuthData {
pub fn basic(username: &str, password: &str) -> Self {
AuthData::Basic(hyper::header::Basic {
username: username.to_owned(),
password: Some(password.to_owned()),
})
}
pub fn bearer(token: &str) -> Self {
AuthData::Bearer(hyper::header::Bearer { token: token.to_owned() })
}
pub fn apikey(apikey: &str) -> Self {
AuthData::ApiKey(apikey.to_owned())
}
}
#[derive(Debug)]
pub struct AllowAllAuthenticator<T, C>
where
C: Push<Option<Authorization>>,
{
inner: T,
subject: String,
marker: PhantomData<C>,
}
impl<T, C> AllowAllAuthenticator<T, C>
where
C: Push<Option<Authorization>>,
{
pub fn new<U: Into<String>>(inner: T, subject: U) -> AllowAllAuthenticator<T, C> {
AllowAllAuthenticator {
inner,
subject: subject.into(),
marker: PhantomData,
}
}
}
impl<T, C> hyper::server::NewService for AllowAllAuthenticator<T, C>
where
C: Push<Option<Authorization>>,
T: hyper::server::NewService<Request=(Request, C::Result), Response=Response, Error=Error>,
{
type Request = (Request, C);
type Response = Response;
type Error = Error;
type Instance = AllowAllAuthenticator<T::Instance, C>;
fn new_service(&self) -> Result<Self::Instance, io::Error> {
self.inner.new_service().map(|s| AllowAllAuthenticator::new(s, self.subject.clone()))
}
}
impl<T, C> hyper::server::Service for AllowAllAuthenticator<T, C>
where
C : Push<Option<Authorization>>,
T: hyper::server::Service<Request=(Request, C::Result), Response=Response, Error=Error>,
{
type Request = (Request, C);
type Response = Response;
type Error = Error;
type Future = T::Future;
fn call(&self, (req, context): Self::Request) -> Self::Future {
let context = context.push(
Some(Authorization{
subject: self.subject.clone(),
scopes: Scopes::All,
issuer: None,
}));
self.inner.call((req, context))
}
}