diff --git a/meilisearch-auth/src/lib.rs b/meilisearch-auth/src/lib.rs index 17f1a3567..43183d4cf 100644 --- a/meilisearch-auth/src/lib.rs +++ b/meilisearch-auth/src/lib.rs @@ -110,10 +110,7 @@ impl AuthController { filters.search_rules = search_rules; } - filters.allow_index_creation = key - .actions - .iter() - .any(|&action| action == Action::IndexesAdd || action == Action::All); + filters.allow_index_creation = self.is_key_authorized(uid, Action::IndexesAdd, None)?; Ok(filters) } diff --git a/meilisearch-http/src/extractors/authentication/mod.rs b/meilisearch-http/src/extractors/authentication/mod.rs index 22f080a6f..f6feabbbd 100644 --- a/meilisearch-http/src/extractors/authentication/mod.rs +++ b/meilisearch-http/src/extractors/authentication/mod.rs @@ -5,7 +5,7 @@ use std::ops::Deref; use std::pin::Pin; use actix_web::FromRequest; -use error::AuthenticationError; +pub use error::AuthenticationError; use futures::future::err; use futures::Future; use meilisearch_auth::{AuthController, AuthFilter}; diff --git a/meilisearch-http/src/routes/indexes/mod.rs b/meilisearch-http/src/routes/indexes/mod.rs index 9fdd0854c..3fa0adba8 100644 --- a/meilisearch-http/src/routes/indexes/mod.rs +++ b/meilisearch-http/src/routes/indexes/mod.rs @@ -8,7 +8,7 @@ use serde_json::json; use time::OffsetDateTime; use crate::analytics::Analytics; -use crate::extractors::authentication::{policies::*, GuardedData}; +use crate::extractors::authentication::{policies::*, AuthenticationError, GuardedData}; use crate::extractors::sequential_extractor::SeqHandler; use crate::task::SummarizedTaskView; @@ -74,16 +74,21 @@ pub async fn create_index( primary_key, uid, .. } = body.into_inner(); - analytics.publish( - "Index Created".to_string(), - json!({ "primary_key": primary_key }), - Some(&req), - ); + let allow_index_creation = meilisearch.filters().search_rules.is_index_authorized(&uid); + if allow_index_creation { + analytics.publish( + "Index Created".to_string(), + json!({ "primary_key": primary_key }), + Some(&req), + ); - let update = Update::CreateIndex { primary_key }; - let task: SummarizedTaskView = meilisearch.register_update(uid, update).await?.into(); + let update = Update::CreateIndex { primary_key }; + let task: SummarizedTaskView = meilisearch.register_update(uid, update).await?.into(); - Ok(HttpResponse::Accepted().json(task)) + Ok(HttpResponse::Accepted().json(task)) + } else { + Err(AuthenticationError::InvalidToken.into()) + } } #[derive(Debug, Deserialize)] diff --git a/meilisearch-http/tests/auth/authorization.rs b/meilisearch-http/tests/auth/authorization.rs index b94070504..5b23749c5 100644 --- a/meilisearch-http/tests/auth/authorization.rs +++ b/meilisearch-http/tests/auth/authorization.rs @@ -597,11 +597,91 @@ async fn error_creating_index_without_action() { #[actix_rt::test] async fn lazy_create_index() { let mut server = Server::new_auth().await; + + // create key with access on all indexes. + let contents = vec![ + json!({ + "indexes": ["*"], + "actions": ["*"], + "expiresAt": "2050-11-13T00:00:00Z" + }), + json!({ + "indexes": ["*"], + "actions": ["indexes.*", "documents.*", "settings.*", "tasks.*"], + "expiresAt": "2050-11-13T00:00:00Z" + }), + json!({ + "indexes": ["*"], + "actions": ["indexes.create", "documents.add", "settings.update", "tasks.get"], + "expiresAt": "2050-11-13T00:00:00Z" + }), + ]; + + for content in contents { + server.use_api_key("MASTER_KEY"); + let (response, code) = server.add_api_key(content).await; + assert_eq!(201, code, "{:?}", &response); + assert!(response["key"].is_string()); + + // use created key. + let key = response["key"].as_str().unwrap(); + server.use_api_key(&key); + + // try to create a index via add documents route + let index = server.index("test"); + let documents = json!([ + { + "id": 1, + "content": "foo", + } + ]); + + let (response, code) = index.add_documents(documents, None).await; + assert_eq!(202, code, "{:?}", &response); + let task_id = response["taskUid"].as_u64().unwrap(); + + index.wait_task(task_id).await; + + let (response, code) = index.get_task(task_id).await; + assert_eq!(200, code, "{:?}", &response); + assert_eq!(response["status"], "succeeded"); + + // try to create a index via add settings route + let index = server.index("test1"); + let settings = json!({ "distinctAttribute": "test"}); + + let (response, code) = index.update_settings(settings).await; + assert_eq!(202, code, "{:?}", &response); + let task_id = response["taskUid"].as_u64().unwrap(); + + index.wait_task(task_id).await; + + let (response, code) = index.get_task(task_id).await; + assert_eq!(200, code, "{:?}", &response); + assert_eq!(response["status"], "succeeded"); + + // try to create a index via add specialized settings route + let index = server.index("test2"); + let (response, code) = index.update_distinct_attribute(json!("test")).await; + assert_eq!(202, code, "{:?}", &response); + let task_id = response["taskUid"].as_u64().unwrap(); + + index.wait_task(task_id).await; + + let (response, code) = index.get_task(task_id).await; + assert_eq!(200, code, "{:?}", &response); + assert_eq!(response["status"], "succeeded"); + } +} + +#[actix_rt::test] +async fn error_creating_index_without_index() { + let mut server = Server::new_auth().await; server.use_api_key("MASTER_KEY"); // create key with access on all indexes. let content = json!({ - "indexes": ["*"], + "indexes": ["unexpected"], "actions": ["*"], "expiresAt": "2050-11-13T00:00:00Z" }); @@ -624,38 +704,21 @@ async fn lazy_create_index() { ]); let (response, code) = index.add_documents(documents, None).await; - assert_eq!(202, code, "{:?}", &response); - let task_id = response["taskUid"].as_u64().unwrap(); - - index.wait_task(task_id).await; - - let (response, code) = index.get_task(task_id).await; - assert_eq!(200, code, "{:?}", &response); - assert_eq!(response["status"], "succeeded"); + assert_eq!(403, code, "{:?}", &response); // try to create a index via add settings route let index = server.index("test1"); let settings = json!({ "distinctAttribute": "test"}); - let (response, code) = index.update_settings(settings).await; - assert_eq!(202, code, "{:?}", &response); - let task_id = response["taskUid"].as_u64().unwrap(); - - index.wait_task(task_id).await; - - let (response, code) = index.get_task(task_id).await; - assert_eq!(200, code, "{:?}", &response); - assert_eq!(response["status"], "succeeded"); + assert_eq!(403, code, "{:?}", &response); // try to create a index via add specialized settings route let index = server.index("test2"); let (response, code) = index.update_distinct_attribute(json!("test")).await; - assert_eq!(202, code, "{:?}", &response); - let task_id = response["taskUid"].as_u64().unwrap(); + assert_eq!(403, code, "{:?}", &response); - index.wait_task(task_id).await; - - let (response, code) = index.get_task(task_id).await; - assert_eq!(200, code, "{:?}", &response); - assert_eq!(response["status"], "succeeded"); + // try to create a index via create index route + let index = server.index("test3"); + let (response, code) = index.create(None).await; + assert_eq!(403, code, "{:?}", &response); }