From 0c1c7a3dd9085fb2d7a4708b19a582fa59f82d3b Mon Sep 17 00:00:00 2001 From: marin postma Date: Thu, 24 Jun 2021 14:22:12 +0200 Subject: [PATCH] implement authentication policies --- .../src/extractors/authentication/mod.rs | 58 +++++++++++-------- meilisearch-http/src/lib.rs | 30 ++++++++-- 2 files changed, 60 insertions(+), 28 deletions(-) diff --git a/meilisearch-http/src/extractors/authentication/mod.rs b/meilisearch-http/src/extractors/authentication/mod.rs index 315461578..2cce6911d 100644 --- a/meilisearch-http/src/extractors/authentication/mod.rs +++ b/meilisearch-http/src/extractors/authentication/mod.rs @@ -1,37 +1,43 @@ -use std::collections::{HashMap, HashSet}; +use std::any::{Any, TypeId}; +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 futures::future::{ok, Ready}; use crate::error::{AuthenticationError, ResponseError}; macro_rules! create_policies { ($($name:ident), *) => { - $( - pub struct $name { - inner: HashSet> - } + pub mod policies { + use std::collections::HashSet; + use crate::extractors::authentication::Policy; - impl $name { - pub fn new() -> Self { - Self { inner: HashSet::new() } + $( + #[derive(Debug)] + pub struct $name { + inner: HashSet> } - pub fn add(&mut self, token: Vec) { - self.inner.insert(token); - } - } + impl $name { + pub fn new() -> Self { + Self { inner: HashSet::new() } + } - impl Policy for $name { - fn authenticate(&self, token: &[u8]) -> bool { - self.inner.contains(token) + pub fn add(&mut self, token: Vec) { + &mut self.inner.insert(token); + } } - } - )* + + impl Policy for $name { + fn authenticate(&self, token: &[u8]) -> bool { + self.inner.contains(token) + } + } + )* + } }; } @@ -41,7 +47,7 @@ create_policies!(Public, Private, Admin); macro_rules! init_policies { ($($name:ident), *) => { { - let mut policies = Policies::new(); + let mut policies = crate::extractors::authentication::Policies::new(); $( let policy = $name::new(); policies.insert(policy); @@ -53,11 +59,11 @@ macro_rules! init_policies { /// Adds user to all specified policies. macro_rules! create_users { - ($policies:ident, $($user:literal => { $($policy:ty), * }), *) => { + ($policies:ident, $($user:expr => { $($policy:ty), * }), *) => { { $( $( - $policies.get_mut::<$policy>().map(|p| p.add($user.to_owned())) + $policies.get_mut::<$policy>().map(|p| p.add($user.to_owned())); )* )* } @@ -81,13 +87,16 @@ pub trait Policy { fn authenticate(&self, token: &[u8]) -> bool; } +#[derive(Debug)] pub struct Policies { inner: HashMap>, } impl Policies { pub fn new() -> Self { - Self { inner: HashMap::new() } + Self { + inner: HashMap::new(), + } } pub fn insert(&mut self, policy: S) { @@ -101,7 +110,8 @@ impl Policies { } pub fn get_mut(&mut self) -> Option<&mut S> { - self.inner.get_mut(&TypeId::of::()) + self.inner + .get_mut(&TypeId::of::()) .and_then(|p| p.downcast_mut::()) } } diff --git a/meilisearch-http/src/lib.rs b/meilisearch-http/src/lib.rs index 0ee1fb4c2..7b9dbdc21 100644 --- a/meilisearch-http/src/lib.rs +++ b/meilisearch-http/src/lib.rs @@ -1,6 +1,7 @@ pub mod data; #[macro_use] pub mod error; +#[macro_use] pub mod extractors; pub mod helpers; mod index; @@ -11,17 +12,21 @@ pub mod routes; #[cfg(all(not(debug_assertions), feature = "analytics"))] pub mod analytics; +use crate::extractors::authentication::AuthConfig; + pub use self::data::Data; pub use option::Opt; use actix_web::web; use extractors::payload::PayloadConfig; +use extractors::authentication::policies::*; pub fn configure_data(config: &mut web::ServiceConfig, data: Data) { let http_payload_size_limit = data.http_payload_size_limit(); config - .data(data) + .data(data.clone()) + .app_data(data) .app_data( web::JsonConfig::default() .limit(http_payload_size_limit) @@ -35,8 +40,24 @@ pub fn configure_data(config: &mut web::ServiceConfig, data: Data) { ); } -pub fn configure_auth(config: &mut web::ServiceConfig, opt: &Options) { - todo!() +pub fn configure_auth(config: &mut web::ServiceConfig, data: &Data) { + let keys = data.api_keys(); + let auth_config = if let Some(ref master_key) = keys.master { + let private_key = keys.private.as_ref().unwrap(); + let public_key = keys.public.as_ref().unwrap(); + let mut policies = init_policies!(Public, Private, Admin); + create_users!( + policies, + master_key.as_bytes() => { Admin, Private, Public }, + private_key.as_bytes() => { Private, Public }, + public_key.as_bytes() => { Public } + ); + AuthConfig::Auth(policies) + } else { + AuthConfig::NoAuth + }; + + config.app_data(auth_config); } #[cfg(feature = "mini-dashboard")] @@ -84,10 +105,11 @@ macro_rules! create_app { use actix_web::App; use actix_web::{middleware, web}; use meilisearch_http::routes::*; - use meilisearch_http::{configure_data, dashboard}; + use meilisearch_http::{configure_data, dashboard, configure_auth}; App::new() .configure(|s| configure_data(s, $data.clone())) + .configure(|s| configure_auth(s, &$data)) .configure(document::services) .configure(index::services) .configure(search::services)