From 12f6709e1c61c2960c8f5d8d6e2813017be5af2f Mon Sep 17 00:00:00 2001 From: marin postma Date: Wed, 23 Jun 2021 18:54:33 +0200 Subject: [PATCH] move authencation to extractor mod --- .../src/extractors/authentication/mod.rs | 117 ++++++++++++++++++ meilisearch-http/src/extractors/mod.rs | 1 + meilisearch-http/src/routes/search.rs | 112 +---------------- 3 files changed, 122 insertions(+), 108 deletions(-) create mode 100644 meilisearch-http/src/extractors/authentication/mod.rs diff --git a/meilisearch-http/src/extractors/authentication/mod.rs b/meilisearch-http/src/extractors/authentication/mod.rs new file mode 100644 index 000000000..a31847945 --- /dev/null +++ b/meilisearch-http/src/extractors/authentication/mod.rs @@ -0,0 +1,117 @@ +use std::collections::HashMap; +use std::marker::PhantomData; +use std::ops::Deref; +use std::any::{Any, TypeId}; + +use actix_web::FromRequest; +use futures::future::err; +use futures::future::{Ready, ok}; + +use crate::error::{AuthenticationError, ResponseError}; + +pub struct Public; + +impl Policy for Public { + fn authenticate(&self, _token: &[u8]) -> bool { + true + } +} + +pub struct GuardedData { + data: D, + _marker: PhantomData, +} + +impl Deref for GuardedData { + type Target = D; + + fn deref(&self) -> &Self::Target { + &self.data + } +} + +pub trait Policy { + fn authenticate(&self, token: &[u8]) -> bool; +} + +pub struct Policies { + inner: HashMap>, +} + +impl Policies { + pub fn new() -> Self { + Self { inner: HashMap::new() } + } + + pub fn insert(&mut self, policy: S) { + self.inner.insert(TypeId::of::(), Box::new(policy)); + } + + pub fn get(&self) -> Option<&S> { + self.inner + .get(&TypeId::of::()) + .and_then(|p| p.downcast_ref::()) + } +} + +impl Default for Policies { + fn default() -> Self { + Self::new() + } +} + +pub enum AuthConfig { + NoAuth, + Auth(Policies), +} + +impl Default for AuthConfig { + fn default() -> Self { + Self::NoAuth + } +} + +impl FromRequest for GuardedData { + type Config = AuthConfig; + + type Error = ResponseError; + + type Future = Ready>; + + fn from_request( + req: &actix_web::HttpRequest, + _payload: &mut actix_http::Payload, + ) -> Self::Future { + match req.app_data::() { + Some(config) => match config { + AuthConfig::NoAuth => match req.app_data::().cloned() { + Some(data) => ok(Self { + data, + _marker: PhantomData, + }), + None => todo!("Data not configured"), + }, + AuthConfig::Auth(policies) => match policies.get::

() { + Some(policy) => match req.headers().get("x-meili-api-key") { + Some(token) => { + if policy.authenticate(token.as_bytes()) { + match req.app_data::().cloned() { + Some(data) => ok(Self { + data, + _marker: PhantomData, + }), + None => todo!("Data not configured"), + } + } else { + err(AuthenticationError::InvalidToken(String::from("hello")).into()) + } + } + None => err(AuthenticationError::MissingAuthorizationHeader.into()), + }, + None => todo!("no policy found"), + }, + }, + None => todo!(), + } + } +} diff --git a/meilisearch-http/src/extractors/mod.rs b/meilisearch-http/src/extractors/mod.rs index fbb091fe2..8d2942f1d 100644 --- a/meilisearch-http/src/extractors/mod.rs +++ b/meilisearch-http/src/extractors/mod.rs @@ -1 +1,2 @@ pub mod payload; +pub mod authentication; diff --git a/meilisearch-http/src/routes/search.rs b/meilisearch-http/src/routes/search.rs index 2fbbfe4b3..0d3184ca9 100644 --- a/meilisearch-http/src/routes/search.rs +++ b/meilisearch-http/src/routes/search.rs @@ -1,119 +1,15 @@ -use std::any::{Any, TypeId}; -use std::collections::{BTreeSet, HashMap, HashSet}; -use std::marker::PhantomData; -use std::ops::Deref; +use std::collections::{BTreeSet, HashSet}; use log::debug; -use actix_web::{web, FromRequest, HttpResponse}; -use futures::future::{err, ok, Ready}; +use actix_web::{web, HttpResponse}; use serde::Deserialize; use serde_json::Value; -use crate::error::{AuthenticationError, ResponseError}; +use crate::error::ResponseError; use crate::index::{default_crop_length, SearchQuery, DEFAULT_SEARCH_LIMIT}; use crate::routes::IndexParam; use crate::Data; - -struct Public; - -impl Policy for Public { - fn authenticate(&self, _token: &[u8]) -> bool { - true - } -} - -struct GuardedData { - data: D, - _marker: PhantomData, -} - -trait Policy { - fn authenticate(&self, token: &[u8]) -> bool; -} - -struct Policies { - inner: HashMap>, -} - -impl Policies { - fn new() -> Self { - Self { inner: HashMap::new() } - } - - fn insert(&mut self, policy: S) { - self.inner.insert(TypeId::of::(), Box::new(policy)); - } - - fn get(&self) -> Option<&S> { - self.inner - .get(&TypeId::of::()) - .and_then(|p| p.downcast_ref::()) - } -} - -enum AuthConfig { - NoAuth, - Auth(Policies), -} - -impl Default for AuthConfig { - fn default() -> Self { - Self::NoAuth - } -} - -impl FromRequest for GuardedData { - type Config = AuthConfig; - - type Error = ResponseError; - - type Future = Ready>; - - fn from_request( - req: &actix_web::HttpRequest, - _payload: &mut actix_http::Payload, - ) -> Self::Future { - match req.app_data::() { - Some(config) => match config { - AuthConfig::NoAuth => match req.app_data::().cloned() { - Some(data) => ok(Self { - data, - _marker: PhantomData, - }), - None => todo!("Data not configured"), - }, - AuthConfig::Auth(policies) => match policies.get::

() { - Some(policy) => match req.headers().get("x-meili-api-key") { - Some(token) => { - if policy.authenticate(token.as_bytes()) { - match req.app_data::().cloned() { - Some(data) => ok(Self { - data, - _marker: PhantomData, - }), - None => todo!("Data not configured"), - } - } else { - err(AuthenticationError::InvalidToken(String::from("hello")).into()) - } - } - None => err(AuthenticationError::MissingAuthorizationHeader.into()), - }, - None => todo!("no policy found"), - }, - }, - None => todo!(), - } - } -} - -impl Deref for GuardedData { - type Target = D; - - fn deref(&self) -> &Self::Target { - &self.data - } -} +use crate::extractors::authentication::{Policies, AuthConfig, Public, GuardedData}; pub fn services(cfg: &mut web::ServiceConfig) { let mut policies = Policies::new();