1use crate::{Push, ContextualPayload};
4use hyper::HeaderMap;
5use std::collections::BTreeSet;
6use std::string::ToString;
7use std::marker::PhantomData;
8use std::task::{Context, Poll};
9
10#[derive(Clone, Debug, PartialEq)]
12pub enum Scopes {
13 Some(BTreeSet<String>),
15 All,
17}
18
19#[derive(Clone, Debug, PartialEq)]
22pub struct Authorization {
23 pub subject: String,
26
27 pub scopes: Scopes,
30
31 pub issuer: Option<String>,
42}
43
44#[derive(Clone, Debug, PartialEq)]
47pub enum AuthData {
48 Basic(headers::Authorization<headers::authorization::Basic>),
50 Bearer(headers::Authorization<headers::authorization::Bearer>),
52 ApiKey(String),
54}
55
56impl AuthData {
57 pub fn basic(username: &str, password: &str) -> Self {
59 AuthData::Basic(headers::Authorization::basic(
60 username,
61 password,
62 ))
63 }
64
65 pub fn bearer(token: &str) -> Self {
67 AuthData::Bearer(headers::Authorization::bearer(token).unwrap())
68 }
69
70 pub fn apikey(apikey: &str) -> Self {
72 AuthData::ApiKey(apikey.to_owned())
73 }
74}
75
76pub trait RcBound: Push<Option<Authorization>> + Send + Sync + 'static {}
78
79impl<T> RcBound for T where T: Push<Option<Authorization>> + Send + Sync + 'static {}
80
81pub fn api_key_from_header(headers: &HeaderMap, header: &str) -> Option<String> {
83 headers
84 .get(header)
85 .and_then(|v| v.to_str().ok())
86 .map(ToString::to_string)
87}
88
89#[derive(Debug)]
92pub struct AllowAllAuthenticatorMakeService<C> {
93 subject: String,
94 phantom: PhantomData<C>,
95}
96
97impl<C> AllowAllAuthenticatorMakeService<C> {
98 pub fn new<T: Into<String>>(subject: T) -> Self {
100 AllowAllAuthenticatorMakeService {
101 subject: subject.into(),
102 phantom: PhantomData,
103 }
104 }
105}
106
107impl<T, C> hyper::service::Service<T> for AllowAllAuthenticatorMakeService<C> {
108 type Response = AllowAllAuthenticator<T, C>;
109 type Error = std::io::Error;
110 type Future = futures::future::Ready<Result<Self::Response, Self::Error>>;
111
112 fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
113 Ok(()).into()
114 }
115
116 fn call(&mut self, inner: T) -> Self::Future {
117 futures::future::ok(AllowAllAuthenticator::new(inner, self.subject.clone()))
118 }
119}
120
121#[derive(Debug)]
127pub struct AllowAllAuthenticator<T, C> {
128 inner: T,
129 subject: String,
130 marker: PhantomData<C>,
131}
132
133impl<T, C> AllowAllAuthenticator<T, C> {
134 pub fn new<U: Into<String>>(inner: T, subject: U) -> Self {
136 AllowAllAuthenticator {
137 inner: inner,
138 subject: subject.into(),
139 marker: PhantomData,
140 }
141 }
142}
143
144impl<T, C> hyper::service::Service<ContextualPayload<C>> for AllowAllAuthenticator<T, C>
145 where
146 C: RcBound,
147 C::Result: Send + Sync + 'static,
148 T: hyper::service::Service<ContextualPayload<C::Result>>,
149{
150 type Response = T::Response;
151 type Error = T::Error;
152 type Future = T::Future;
153
154 fn poll_ready(&mut self, _cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
155 Ok(()).into()
156 }
157
158 fn call(&mut self, req: ContextualPayload<C>) -> Self::Future {
159 let auth = Authorization {
160 subject: self.subject.clone(),
161 scopes: Scopes::All,
162 issuer: None,
163 };
164 let context = req.context.push(Some(auth));
165
166 self.inner.call(ContextualPayload {
167 inner: req.inner,
168 context: context,
169 })
170 }
171}