mirror of
https://github.com/meilisearch/meilisearch.git
synced 2024-11-22 18:17:39 +08:00
async auth
This commit is contained in:
parent
d6400aef27
commit
af8a5f2c21
@ -2,28 +2,88 @@ mod error;
|
|||||||
|
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
use std::pin::Pin;
|
||||||
|
|
||||||
use actix_web::FromRequest;
|
use actix_web::FromRequest;
|
||||||
use futures::future::err;
|
use futures::future::err;
|
||||||
use futures::future::{ok, Ready};
|
use futures::Future;
|
||||||
use meilisearch_error::ResponseError;
|
use meilisearch_error::{Code, ResponseError};
|
||||||
|
|
||||||
use error::AuthenticationError;
|
use error::AuthenticationError;
|
||||||
use meilisearch_auth::{AuthController, AuthFilter};
|
use meilisearch_auth::{AuthController, AuthFilter};
|
||||||
|
|
||||||
pub struct GuardedData<T, D> {
|
pub struct GuardedData<P, D> {
|
||||||
data: D,
|
data: D,
|
||||||
filters: AuthFilter,
|
filters: AuthFilter,
|
||||||
_marker: PhantomData<T>,
|
_marker: PhantomData<P>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, D> GuardedData<T, D> {
|
impl<P, D> GuardedData<P, D> {
|
||||||
pub fn filters(&self) -> &AuthFilter {
|
pub fn filters(&self) -> &AuthFilter {
|
||||||
&self.filters
|
&self.filters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn auth_bearer(
|
||||||
|
auth: AuthController,
|
||||||
|
token: String,
|
||||||
|
index: Option<String>,
|
||||||
|
data: Option<D>,
|
||||||
|
) -> Result<Self, ResponseError>
|
||||||
|
where
|
||||||
|
P: Policy + 'static,
|
||||||
|
{
|
||||||
|
match Self::authenticate(auth, token, index).await? {
|
||||||
|
(_, Some(filters)) => match data {
|
||||||
|
Some(data) => Ok(Self {
|
||||||
|
data,
|
||||||
|
filters,
|
||||||
|
_marker: PhantomData,
|
||||||
|
}),
|
||||||
|
None => Err(AuthenticationError::IrretrievableState.into()),
|
||||||
|
},
|
||||||
|
(token, None) => {
|
||||||
|
let token = token.to_string();
|
||||||
|
Err(AuthenticationError::InvalidToken(token).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn auth_token(auth: AuthController, data: Option<D>) -> Result<Self, ResponseError>
|
||||||
|
where
|
||||||
|
P: Policy + 'static,
|
||||||
|
{
|
||||||
|
match Self::authenticate(auth, "", None).await?.1 {
|
||||||
|
Some(filters) => match data {
|
||||||
|
Some(data) => Ok(Self {
|
||||||
|
data,
|
||||||
|
filters,
|
||||||
|
_marker: PhantomData,
|
||||||
|
}),
|
||||||
|
None => Err(AuthenticationError::IrretrievableState.into()),
|
||||||
|
},
|
||||||
|
None => Err(AuthenticationError::MissingAuthorizationHeader.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn authenticate<S>(
|
||||||
|
auth: AuthController,
|
||||||
|
token: S,
|
||||||
|
index: Option<String>,
|
||||||
|
) -> Result<(S, Option<AuthFilter>), ResponseError>
|
||||||
|
where
|
||||||
|
P: Policy + 'static,
|
||||||
|
S: AsRef<str> + 'static + Send,
|
||||||
|
{
|
||||||
|
Ok(tokio::task::spawn_blocking(move || {
|
||||||
|
let res = P::authenticate(auth, token.as_ref(), index.as_deref());
|
||||||
|
(token, res)
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.map_err(|e| ResponseError::from_msg(e.to_string(), Code::Internal))?)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, D> Deref for GuardedData<T, D> {
|
impl<P, D> Deref for GuardedData<P, D> {
|
||||||
type Target = D;
|
type Target = D;
|
||||||
|
|
||||||
fn deref(&self) -> &Self::Target {
|
fn deref(&self) -> &Self::Target {
|
||||||
@ -34,7 +94,7 @@ impl<T, D> Deref for GuardedData<T, D> {
|
|||||||
impl<P: Policy + 'static, D: 'static + Clone> FromRequest for GuardedData<P, D> {
|
impl<P: Policy + 'static, D: 'static + Clone> FromRequest for GuardedData<P, D> {
|
||||||
type Error = ResponseError;
|
type Error = ResponseError;
|
||||||
|
|
||||||
type Future = Ready<Result<Self, Self::Error>>;
|
type Future = Pin<Box<dyn Future<Output = Result<Self, Self::Error>>>>;
|
||||||
|
|
||||||
fn from_request(
|
fn from_request(
|
||||||
req: &actix_web::HttpRequest,
|
req: &actix_web::HttpRequest,
|
||||||
@ -51,40 +111,25 @@ impl<P: Policy + 'static, D: 'static + Clone> FromRequest for GuardedData<P, D>
|
|||||||
// TODO: find a less hardcoded way?
|
// TODO: find a less hardcoded way?
|
||||||
let index = req.match_info().get("index_uid");
|
let index = req.match_info().get("index_uid");
|
||||||
match type_token.next() {
|
match type_token.next() {
|
||||||
Some(token) => match P::authenticate(auth, token, index) {
|
Some(token) => Box::pin(Self::auth_bearer(
|
||||||
Some(filters) => match req.app_data::<D>().cloned() {
|
auth,
|
||||||
Some(data) => ok(Self {
|
token.to_string(),
|
||||||
data,
|
index.map(String::from),
|
||||||
filters,
|
req.app_data::<D>().cloned(),
|
||||||
_marker: PhantomData,
|
)),
|
||||||
}),
|
None => Box::pin(err(AuthenticationError::InvalidToken(
|
||||||
None => err(AuthenticationError::IrretrievableState.into()),
|
"unknown".to_string(),
|
||||||
},
|
)
|
||||||
None => {
|
.into())),
|
||||||
let token = token.to_string();
|
|
||||||
err(AuthenticationError::InvalidToken(token).into())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
err(AuthenticationError::InvalidToken("unknown".to_string()).into())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_otherwise => err(AuthenticationError::MissingAuthorizationHeader.into()),
|
_otherwise => {
|
||||||
},
|
Box::pin(err(AuthenticationError::MissingAuthorizationHeader.into()))
|
||||||
None => match P::authenticate(auth, "", None) {
|
}
|
||||||
Some(filters) => match req.app_data::<D>().cloned() {
|
|
||||||
Some(data) => ok(Self {
|
|
||||||
data,
|
|
||||||
filters,
|
|
||||||
_marker: PhantomData,
|
|
||||||
}),
|
|
||||||
None => err(AuthenticationError::IrretrievableState.into()),
|
|
||||||
},
|
|
||||||
None => err(AuthenticationError::MissingAuthorizationHeader.into()),
|
|
||||||
},
|
},
|
||||||
|
None => Box::pin(Self::auth_token(auth, req.app_data::<D>().cloned())),
|
||||||
},
|
},
|
||||||
None => err(AuthenticationError::IrretrievableState.into()),
|
None => Box::pin(err(AuthenticationError::IrretrievableState.into())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user