add authentication middleware

This commit is contained in:
Quentin de Quelen 2020-04-14 18:00:35 +02:00 committed by qdequele
parent 5fed155f15
commit 38d41252e6
No known key found for this signature in database
GPG key ID: B3F0A000EBF11745
5 changed files with 105 additions and 106 deletions

View file

@ -1,8 +1,17 @@
use std::cell::RefCell;
use std::pin::Pin;
use std::rc::Rc;
use std::task::{Context, Poll};
use actix_service::{Service, Transform};
use actix_web::{dev::ServiceRequest, dev::ServiceResponse, Error};
use actix_web::{get, HttpResponse};
use futures::future::{err, ok, Future, Ready};
use log::error;
use meilisearch_core::ProcessedUpdateResult;
use serde::{Deserialize, Serialize};
use crate::error::ResponseError;
use crate::Data;
pub mod document;
@ -79,109 +88,91 @@ pub fn index_update_callback(index_uid: &str, data: &Data, status: ProcessedUpda
}
}
// pub fn load_routes(app: &mut tide::Server<Data>) {
// app.at("/").get(|_| async {
// tide::Response::new(200)
// .body_string()
// .set_mime(mime::TEXT_HTML_UTF_8)
// });
// app.at("/bulma.min.css").get(|_| async {
// tide::Response::new(200)
// .body_string(include_str!("../../public/bulma.min.css").to_string())
// .set_mime(mime::TEXT_CSS_UTF_8)
// });
#[derive(Clone)]
pub enum Authentication {
Public,
Private,
Admin,
}
// app.at("/indexes")
// .get(|ctx| into_response(index::list_indexes(ctx)))
// .post(|ctx| into_response(index::create_index(ctx)));
impl<S: 'static, B> Transform<S> for Authentication
where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
S::Future: 'static,
B: 'static,
{
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = Error;
type InitError = ();
type Transform = LoggingMiddleware<S>;
type Future = Ready<Result<Self::Transform, Self::InitError>>;
// app.at("/indexes/search")
// .post(|ctx| into_response(search::search_multi_index(ctx)));
fn new_transform(&self, service: S) -> Self::Future {
ok(LoggingMiddleware {
acl: (*self).clone(),
service: Rc::new(RefCell::new(service)),
})
}
}
// app.at("/indexes/:index")
// .get(|ctx| into_response(index::get_index(ctx)))
// .put(|ctx| into_response(index::update_index(ctx)))
// .delete(|ctx| into_response(index::delete_index(ctx)));
pub struct LoggingMiddleware<S> {
acl: Authentication,
service: Rc<RefCell<S>>,
}
// app.at("/indexes/:index/search")
// .get(|ctx| into_response(search::search_with_url_query(ctx)));
impl<S, B> Service for LoggingMiddleware<S>
where
S: Service<Request = ServiceRequest, Response = ServiceResponse<B>, Error = Error> + 'static,
S::Future: 'static,
B: 'static,
{
type Request = ServiceRequest;
type Response = ServiceResponse<B>;
type Error = Error;
type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>;
// app.at("/indexes/:index/updates")
// .get(|ctx| into_response(index::get_all_updates_status(ctx)));
fn poll_ready(&mut self, cx: &mut Context) -> Poll<Result<(), Self::Error>> {
self.service.poll_ready(cx)
}
// app.at("/indexes/:index/updates/:update_id")
// .get(|ctx| into_response(index::get_update_status(ctx)));
fn call(&mut self, req: ServiceRequest) -> Self::Future {
let mut svc = self.service.clone();
let data = req.app_data::<Data>().unwrap();
// app.at("/indexes/:index/documents")
// .get(|ctx| into_response(document::get_all_documents(ctx)))
// .post(|ctx| into_response(document::add_or_replace_multiple_documents(ctx)))
// .put(|ctx| into_response(document::add_or_update_multiple_documents(ctx)))
// .delete(|ctx| into_response(document::clear_all_documents(ctx)));
if data.api_keys.master.is_none() {
return Box::pin(svc.call(req));
}
// app.at("/indexes/:index/documents/:document_id")
// .get(|ctx| into_response(document::get_document(ctx)))
// .delete(|ctx| into_response(document::delete_document(ctx)));
let auth_header = match req.headers().get("X-Meili-API-Key") {
Some(auth) => match auth.to_str() {
Ok(auth) => auth,
Err(_) => return Box::pin(err(ResponseError::MissingAuthorizationHeader.into())),
},
None => {
return Box::pin(err(ResponseError::MissingAuthorizationHeader.into()));
}
};
// app.at("/indexes/:index/documents/delete-batch")
// .post(|ctx| into_response(document::delete_multiple_documents(ctx)));
let authenticated = match self.acl {
Authentication::Admin => data.api_keys.master.as_deref() == Some(auth_header),
Authentication::Private => {
data.api_keys.master.as_deref() == Some(auth_header)
|| data.api_keys.private.as_deref() == Some(auth_header)
}
Authentication::Public => {
data.api_keys.master.as_deref() == Some(auth_header)
|| data.api_keys.private.as_deref() == Some(auth_header)
|| data.api_keys.public.as_deref() == Some(auth_header)
}
};
// app.at("/indexes/:index/settings")
// .get(|ctx| into_response(setting::get_all(ctx)))
// .post(|ctx| into_response(setting::update_all(ctx)))
// .delete(|ctx| into_response(setting::delete_all(ctx)));
// app.at("/indexes/:index/settings/ranking-rules")
// .get(|ctx| into_response(setting::get_rules(ctx)))
// .post(|ctx| into_response(setting::update_rules(ctx)))
// .delete(|ctx| into_response(setting::delete_rules(ctx)));
// app.at("/indexes/:index/settings/distinct-attribute")
// .get(|ctx| into_response(setting::get_distinct(ctx)))
// .post(|ctx| into_response(setting::update_distinct(ctx)))
// .delete(|ctx| into_response(setting::delete_distinct(ctx)));
// app.at("/indexes/:index/settings/searchable-attributes")
// .get(|ctx| into_response(setting::get_searchable(ctx)))
// .post(|ctx| into_response(setting::update_searchable(ctx)))
// .delete(|ctx| into_response(setting::delete_searchable(ctx)));
// app.at("/indexes/:index/settings/displayed-attributes")
// .get(|ctx| into_response(setting::displayed(ctx)))
// .post(|ctx| into_response(setting::update_displayed(ctx)))
// .delete(|ctx| into_response(setting::delete_displayed(ctx)));
// app.at("/indexes/:index/settings/accept-new-fields")
// .get(|ctx| into_response(setting::get_accept_new_fields(ctx)))
// .post(|ctx| into_response(setting::update_accept_new_fields(ctx)));
// app.at("/indexes/:index/settings/synonyms")
// .get(|ctx| into_response(synonym::get(ctx)))
// .post(|ctx| into_response(synonym::update(ctx)))
// .delete(|ctx| into_response(synonym::delete(ctx)));
// app.at("/indexes/:index/settings/stop-words")
// .get(|ctx| into_response(stop_words::get(ctx)))
// .post(|ctx| into_response(stop_words::update(ctx)))
// .delete(|ctx| into_response(stop_words::delete(ctx)));
// app.at("/indexes/:index/stats")
// .get(|ctx| into_response(stats::index_stats(ctx)));
// app.at("/keys").get(|ctx| into_response(key::list(ctx)));
// app.at("/health")
// .get(|ctx| into_response(health::get_health(ctx)))
// .put(|ctx| into_response(health::change_healthyness(ctx)));
// app.at("/stats")
// .get(|ctx| into_response(stats::get_stats(ctx)));
// app.at("/version")
// .get(|ctx| into_response(stats::get_version(ctx)));
// app.at("/sys-info")
// .get(|ctx| into_response(stats::get_sys_info(ctx)));
// app.at("/sys-info/pretty")
// .get(|ctx| into_response(stats::get_sys_info_pretty(ctx)));
// }
if authenticated {
Box::pin(svc.call(req))
} else {
Box::pin(err(
ResponseError::InvalidToken(auth_header.to_string()).into()
))
}
}
}