2022-10-20 18:00:07 +02:00
|
|
|
use std::collections::{HashMap, HashSet};
|
|
|
|
|
2022-02-14 15:32:41 +01:00
|
|
|
use ::time::format_description::well_known::Rfc3339;
|
2022-01-24 15:06:31 +01:00
|
|
|
use maplit::{hashmap, hashset};
|
2021-11-08 18:31:27 +01:00
|
|
|
use once_cell::sync::Lazy;
|
|
|
|
use serde_json::{json, Value};
|
2022-02-14 15:32:41 +01:00
|
|
|
use time::{Duration, OffsetDateTime};
|
2021-11-08 18:31:27 +01:00
|
|
|
|
2022-10-20 18:00:07 +02:00
|
|
|
use crate::common::Server;
|
|
|
|
|
2022-01-12 15:35:33 +01:00
|
|
|
pub static AUTHORIZATIONS: Lazy<HashMap<(&'static str, &'static str), HashSet<&'static str>>> =
|
2021-11-08 18:31:27 +01:00
|
|
|
Lazy::new(|| {
|
2022-08-29 12:36:54 +02:00
|
|
|
let mut authorizations = hashmap! {
|
2022-01-24 15:06:31 +01:00
|
|
|
("POST", "/indexes/products/search") => hashset!{"search", "*"},
|
|
|
|
("GET", "/indexes/products/search") => hashset!{"search", "*"},
|
2022-06-15 17:10:20 +02:00
|
|
|
("POST", "/indexes/products/documents") => hashset!{"documents.add", "documents.*", "*"},
|
|
|
|
("GET", "/indexes/products/documents") => hashset!{"documents.get", "documents.*", "*"},
|
|
|
|
("GET", "/indexes/products/documents/0") => hashset!{"documents.get", "documents.*", "*"},
|
|
|
|
("DELETE", "/indexes/products/documents/0") => hashset!{"documents.delete", "documents.*", "*"},
|
2022-07-05 03:30:24 +02:00
|
|
|
("GET", "/tasks") => hashset!{"tasks.get", "tasks.*", "*"},
|
2022-10-13 12:48:23 +02:00
|
|
|
("DELETE", "/tasks") => hashset!{"tasks.delete", "tasks.*", "*"},
|
2022-07-05 03:30:24 +02:00
|
|
|
("GET", "/tasks?indexUid=products") => hashset!{"tasks.get", "tasks.*", "*"},
|
|
|
|
("GET", "/tasks/0") => hashset!{"tasks.get", "tasks.*", "*"},
|
|
|
|
("PATCH", "/indexes/products/") => hashset!{"indexes.update", "indexes.*", "*"},
|
|
|
|
("GET", "/indexes/products/") => hashset!{"indexes.get", "indexes.*", "*"},
|
|
|
|
("DELETE", "/indexes/products/") => hashset!{"indexes.delete", "indexes.*", "*"},
|
|
|
|
("POST", "/indexes") => hashset!{"indexes.create", "indexes.*", "*"},
|
|
|
|
("GET", "/indexes") => hashset!{"indexes.get", "indexes.*", "*"},
|
2022-10-22 13:26:25 +02:00
|
|
|
// ("POST", "/indexes-swap") => hashset!{"indexes.swap", "indexes.*", "*"}, // TODO: uncomment and fix this test
|
2022-07-05 03:30:24 +02:00
|
|
|
("GET", "/indexes/products/settings") => hashset!{"settings.get", "settings.*", "*"},
|
|
|
|
("GET", "/indexes/products/settings/displayed-attributes") => hashset!{"settings.get", "settings.*", "*"},
|
|
|
|
("GET", "/indexes/products/settings/distinct-attribute") => hashset!{"settings.get", "settings.*", "*"},
|
|
|
|
("GET", "/indexes/products/settings/filterable-attributes") => hashset!{"settings.get", "settings.*", "*"},
|
|
|
|
("GET", "/indexes/products/settings/ranking-rules") => hashset!{"settings.get", "settings.*", "*"},
|
|
|
|
("GET", "/indexes/products/settings/searchable-attributes") => hashset!{"settings.get", "settings.*", "*"},
|
|
|
|
("GET", "/indexes/products/settings/sortable-attributes") => hashset!{"settings.get", "settings.*", "*"},
|
|
|
|
("GET", "/indexes/products/settings/stop-words") => hashset!{"settings.get", "settings.*", "*"},
|
|
|
|
("GET", "/indexes/products/settings/synonyms") => hashset!{"settings.get", "settings.*", "*"},
|
|
|
|
("DELETE", "/indexes/products/settings") => hashset!{"settings.update", "settings.*", "*"},
|
|
|
|
("PATCH", "/indexes/products/settings") => hashset!{"settings.update", "settings.*", "*"},
|
|
|
|
("PATCH", "/indexes/products/settings/typo-tolerance") => hashset!{"settings.update", "settings.*", "*"},
|
|
|
|
("PUT", "/indexes/products/settings/displayed-attributes") => hashset!{"settings.update", "settings.*", "*"},
|
|
|
|
("PUT", "/indexes/products/settings/distinct-attribute") => hashset!{"settings.update", "settings.*", "*"},
|
|
|
|
("PUT", "/indexes/products/settings/filterable-attributes") => hashset!{"settings.update", "settings.*", "*"},
|
|
|
|
("PUT", "/indexes/products/settings/ranking-rules") => hashset!{"settings.update", "settings.*", "*"},
|
|
|
|
("PUT", "/indexes/products/settings/searchable-attributes") => hashset!{"settings.update", "settings.*", "*"},
|
|
|
|
("PUT", "/indexes/products/settings/sortable-attributes") => hashset!{"settings.update", "settings.*", "*"},
|
|
|
|
("PUT", "/indexes/products/settings/stop-words") => hashset!{"settings.update", "settings.*", "*"},
|
|
|
|
("PUT", "/indexes/products/settings/synonyms") => hashset!{"settings.update", "settings.*", "*"},
|
|
|
|
("GET", "/indexes/products/stats") => hashset!{"stats.get", "stats.*", "*"},
|
|
|
|
("GET", "/stats") => hashset!{"stats.get", "stats.*", "*"},
|
|
|
|
("POST", "/dumps") => hashset!{"dumps.create", "dumps.*", "*"},
|
2022-01-24 15:06:31 +01:00
|
|
|
("GET", "/version") => hashset!{"version", "*"},
|
2022-05-23 17:03:28 +02:00
|
|
|
("PATCH", "/keys/mykey/") => hashset!{"keys.update", "*"},
|
|
|
|
("GET", "/keys/mykey/") => hashset!{"keys.get", "*"},
|
|
|
|
("DELETE", "/keys/mykey/") => hashset!{"keys.delete", "*"},
|
|
|
|
("POST", "/keys") => hashset!{"keys.create", "*"},
|
|
|
|
("GET", "/keys") => hashset!{"keys.get", "*"},
|
2022-08-29 12:36:54 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
if cfg!(feature = "metrics") {
|
2022-10-20 18:00:07 +02:00
|
|
|
authorizations.insert(("GET", "/metrics"), hashset! {"metrics.get", "metrics.*", "*"});
|
2021-11-08 18:31:27 +01:00
|
|
|
}
|
2022-08-29 12:36:54 +02:00
|
|
|
|
|
|
|
authorizations
|
2021-11-08 18:31:27 +01:00
|
|
|
});
|
|
|
|
|
2022-01-12 15:35:33 +01:00
|
|
|
pub static ALL_ACTIONS: Lazy<HashSet<&'static str>> = Lazy::new(|| {
|
2022-10-20 18:00:07 +02:00
|
|
|
AUTHORIZATIONS.values().cloned().reduce(|l, r| l.union(&r).cloned().collect()).unwrap()
|
2022-01-24 15:06:31 +01:00
|
|
|
});
|
2021-11-08 18:31:27 +01:00
|
|
|
|
|
|
|
static INVALID_RESPONSE: Lazy<Value> = Lazy::new(|| {
|
|
|
|
json!({"message": "The provided API key is invalid.",
|
|
|
|
"code": "invalid_api_key",
|
|
|
|
"type": "auth",
|
|
|
|
"link": "https://docs.meilisearch.com/errors#invalid_api_key"
|
|
|
|
})
|
|
|
|
});
|
|
|
|
|
|
|
|
#[actix_rt::test]
|
2021-12-22 12:39:48 +01:00
|
|
|
#[cfg_attr(target_os = "windows", ignore)]
|
2021-11-08 18:31:27 +01:00
|
|
|
async fn error_access_expired_key() {
|
2021-12-06 15:45:41 +01:00
|
|
|
use std::{thread, time};
|
|
|
|
|
2021-11-08 18:31:27 +01:00
|
|
|
let mut server = Server::new_auth().await;
|
|
|
|
server.use_api_key("MASTER_KEY");
|
|
|
|
|
|
|
|
let content = json!({
|
|
|
|
"indexes": ["products"],
|
|
|
|
"actions": ALL_ACTIONS.clone(),
|
2022-02-14 15:32:41 +01:00
|
|
|
"expiresAt": (OffsetDateTime::now_utc() + Duration::seconds(1)).format(&Rfc3339).unwrap(),
|
2021-11-08 18:31:27 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
let (response, code) = server.add_api_key(content).await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(201, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
assert!(response["key"].is_string());
|
|
|
|
|
|
|
|
let key = response["key"].as_str().unwrap();
|
|
|
|
server.use_api_key(&key);
|
|
|
|
|
2021-12-06 15:45:41 +01:00
|
|
|
// wait until the key is expired.
|
|
|
|
thread::sleep(time::Duration::new(1, 0));
|
|
|
|
|
2021-11-08 18:31:27 +01:00
|
|
|
for (method, route) in AUTHORIZATIONS.keys() {
|
|
|
|
let (response, code) = server.dummy_request(method, route).await;
|
|
|
|
|
2022-10-20 18:00:07 +02:00
|
|
|
assert_eq!(response, INVALID_RESPONSE.clone(), "on route: {:?} - {:?}", method, route);
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(403, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[actix_rt::test]
|
2021-12-22 12:39:48 +01:00
|
|
|
#[cfg_attr(target_os = "windows", ignore)]
|
2021-11-08 18:31:27 +01:00
|
|
|
async fn error_access_unauthorized_index() {
|
|
|
|
let mut server = Server::new_auth().await;
|
|
|
|
server.use_api_key("MASTER_KEY");
|
|
|
|
|
|
|
|
let content = json!({
|
|
|
|
"indexes": ["sales"],
|
|
|
|
"actions": ALL_ACTIONS.clone(),
|
2022-02-14 15:32:41 +01:00
|
|
|
"expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(),
|
2021-11-08 18:31:27 +01:00
|
|
|
});
|
|
|
|
|
|
|
|
let (response, code) = server.add_api_key(content).await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(201, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
assert!(response["key"].is_string());
|
|
|
|
|
|
|
|
let key = response["key"].as_str().unwrap();
|
|
|
|
server.use_api_key(&key);
|
|
|
|
|
|
|
|
for (method, route) in AUTHORIZATIONS
|
|
|
|
.keys()
|
|
|
|
// filter `products` index routes
|
|
|
|
.filter(|(_, route)| route.starts_with("/indexes/products"))
|
|
|
|
{
|
|
|
|
let (response, code) = server.dummy_request(method, route).await;
|
|
|
|
|
2022-10-20 18:00:07 +02:00
|
|
|
assert_eq!(response, INVALID_RESPONSE.clone(), "on route: {:?} - {:?}", method, route);
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(403, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[actix_rt::test]
|
2021-12-22 12:39:48 +01:00
|
|
|
#[cfg_attr(target_os = "windows", ignore)]
|
2021-11-08 18:31:27 +01:00
|
|
|
async fn error_access_unauthorized_action() {
|
|
|
|
let mut server = Server::new_auth().await;
|
|
|
|
|
|
|
|
for ((method, route), action) in AUTHORIZATIONS.iter() {
|
2022-06-01 14:11:56 +02:00
|
|
|
// create a new API key letting only the needed action.
|
2021-11-08 18:31:27 +01:00
|
|
|
server.use_api_key("MASTER_KEY");
|
|
|
|
|
|
|
|
let content = json!({
|
2022-06-01 14:11:56 +02:00
|
|
|
"indexes": ["products"],
|
2022-01-24 15:06:31 +01:00
|
|
|
"actions": ALL_ACTIONS.difference(action).collect::<Vec<_>>(),
|
2022-06-01 14:11:56 +02:00
|
|
|
"expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(),
|
2021-11-08 18:31:27 +01:00
|
|
|
});
|
|
|
|
|
2022-06-01 14:11:56 +02:00
|
|
|
let (response, code) = server.add_api_key(content).await;
|
|
|
|
assert_eq!(201, code, "{:?}", &response);
|
|
|
|
assert!(response["key"].is_string());
|
|
|
|
|
|
|
|
let key = response["key"].as_str().unwrap();
|
2021-11-08 18:31:27 +01:00
|
|
|
server.use_api_key(&key);
|
|
|
|
let (response, code) = server.dummy_request(method, route).await;
|
|
|
|
|
2022-10-20 18:00:07 +02:00
|
|
|
assert_eq!(response, INVALID_RESPONSE.clone(), "on route: {:?} - {:?}", method, route);
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(403, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-05-23 17:03:28 +02:00
|
|
|
#[actix_rt::test]
|
|
|
|
#[cfg_attr(target_os = "windows", ignore)]
|
|
|
|
async fn access_authorized_master_key() {
|
|
|
|
let mut server = Server::new_auth().await;
|
|
|
|
server.use_api_key("MASTER_KEY");
|
|
|
|
|
2022-06-01 11:47:44 +02:00
|
|
|
// master key must have access to all routes.
|
|
|
|
for ((method, route), _) in AUTHORIZATIONS.iter() {
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = server.dummy_request(method, route).await;
|
2021-11-08 18:31:27 +01:00
|
|
|
|
2022-10-20 18:00:07 +02:00
|
|
|
assert_ne!(response, INVALID_RESPONSE.clone(), "on route: {:?} - {:?}", method, route);
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_ne!(code, 403);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[actix_rt::test]
|
|
|
|
#[cfg_attr(target_os = "windows", ignore)]
|
|
|
|
async fn access_authorized_restricted_index() {
|
|
|
|
let mut server = Server::new_auth().await;
|
2022-01-24 15:06:31 +01:00
|
|
|
for ((method, route), actions) in AUTHORIZATIONS.iter() {
|
|
|
|
for action in actions {
|
2022-05-23 17:03:28 +02:00
|
|
|
// create a new API key letting only the needed action.
|
|
|
|
server.use_api_key("MASTER_KEY");
|
|
|
|
|
2022-01-24 15:06:31 +01:00
|
|
|
let content = json!({
|
2022-05-23 17:03:28 +02:00
|
|
|
"indexes": ["products"],
|
2022-01-24 15:06:31 +01:00
|
|
|
"actions": [action],
|
2022-05-23 17:03:28 +02:00
|
|
|
"expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(),
|
2022-01-24 15:06:31 +01:00
|
|
|
});
|
2021-11-08 18:31:27 +01:00
|
|
|
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = server.add_api_key(content).await;
|
|
|
|
assert_eq!(201, code, "{:?}", &response);
|
|
|
|
assert!(response["key"].is_string());
|
2021-11-08 18:31:27 +01:00
|
|
|
|
2022-05-23 17:03:28 +02:00
|
|
|
let key = response["key"].as_str().unwrap();
|
2022-01-24 15:06:31 +01:00
|
|
|
server.use_api_key(&key);
|
2022-05-23 17:03:28 +02:00
|
|
|
|
2022-01-24 15:06:31 +01:00
|
|
|
let (response, code) = server.dummy_request(method, route).await;
|
2021-11-08 18:31:27 +01:00
|
|
|
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_ne!(
|
|
|
|
response,
|
|
|
|
INVALID_RESPONSE.clone(),
|
|
|
|
"on route: {:?} - {:?} with action: {:?}",
|
|
|
|
method,
|
|
|
|
route,
|
|
|
|
action
|
|
|
|
);
|
2022-01-24 15:06:31 +01:00
|
|
|
assert_ne!(code, 403);
|
|
|
|
}
|
2021-11-08 18:31:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[actix_rt::test]
|
2021-12-22 12:39:48 +01:00
|
|
|
#[cfg_attr(target_os = "windows", ignore)]
|
2021-11-08 18:31:27 +01:00
|
|
|
async fn access_authorized_no_index_restriction() {
|
|
|
|
let mut server = Server::new_auth().await;
|
|
|
|
|
2022-01-24 15:06:31 +01:00
|
|
|
for ((method, route), actions) in AUTHORIZATIONS.iter() {
|
|
|
|
for action in actions {
|
2022-05-23 17:03:28 +02:00
|
|
|
// create a new API key letting only the needed action.
|
2022-01-24 15:06:31 +01:00
|
|
|
server.use_api_key("MASTER_KEY");
|
2021-11-08 18:31:27 +01:00
|
|
|
|
2022-01-24 15:06:31 +01:00
|
|
|
let content = json!({
|
2022-06-08 14:52:32 +02:00
|
|
|
"indexes": ["*"],
|
2022-01-24 15:06:31 +01:00
|
|
|
"actions": [action],
|
2022-05-23 17:03:28 +02:00
|
|
|
"expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(),
|
2022-01-24 15:06:31 +01:00
|
|
|
});
|
2021-11-08 18:31:27 +01:00
|
|
|
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = server.add_api_key(content).await;
|
|
|
|
assert_eq!(201, code, "{:?}", &response);
|
|
|
|
assert!(response["key"].is_string());
|
|
|
|
|
|
|
|
let key = response["key"].as_str().unwrap();
|
2022-01-24 15:06:31 +01:00
|
|
|
server.use_api_key(&key);
|
2022-05-23 17:03:28 +02:00
|
|
|
|
2022-01-24 15:06:31 +01:00
|
|
|
let (response, code) = server.dummy_request(method, route).await;
|
2021-11-08 18:31:27 +01:00
|
|
|
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_ne!(
|
|
|
|
response,
|
|
|
|
INVALID_RESPONSE.clone(),
|
|
|
|
"on route: {:?} - {:?} with action: {:?}",
|
|
|
|
method,
|
|
|
|
route,
|
|
|
|
action
|
|
|
|
);
|
2022-01-24 15:06:31 +01:00
|
|
|
assert_ne!(code, 403);
|
|
|
|
}
|
2021-11-08 18:31:27 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[actix_rt::test]
|
2021-12-22 12:39:48 +01:00
|
|
|
#[cfg_attr(target_os = "windows", ignore)]
|
2021-11-08 18:31:27 +01:00
|
|
|
async fn access_authorized_stats_restricted_index() {
|
|
|
|
let mut server = Server::new_auth().await;
|
2022-05-23 17:03:28 +02:00
|
|
|
server.use_admin_key("MASTER_KEY").await;
|
2021-11-08 18:31:27 +01:00
|
|
|
|
|
|
|
// create index `test`
|
|
|
|
let index = server.index("test");
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = index.create(Some("id")).await;
|
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
// create index `products`
|
|
|
|
let index = server.index("products");
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = index.create(Some("product_id")).await;
|
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
index.wait_task(0).await;
|
|
|
|
|
|
|
|
// create key with access on `products` index only.
|
|
|
|
let content = json!({
|
|
|
|
"indexes": ["products"],
|
|
|
|
"actions": ["stats.get"],
|
2022-02-14 15:32:41 +01:00
|
|
|
"expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(),
|
2021-11-08 18:31:27 +01:00
|
|
|
});
|
|
|
|
let (response, code) = server.add_api_key(content).await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(201, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
assert!(response["key"].is_string());
|
|
|
|
|
|
|
|
// use created key.
|
|
|
|
let key = response["key"].as_str().unwrap();
|
|
|
|
server.use_api_key(&key);
|
|
|
|
|
|
|
|
let (response, code) = server.stats().await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(200, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
|
|
|
|
// key should have access on `products` index.
|
|
|
|
assert!(response["indexes"].get("products").is_some());
|
|
|
|
|
|
|
|
// key should not have access on `test` index.
|
|
|
|
assert!(response["indexes"].get("test").is_none());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[actix_rt::test]
|
2021-12-22 12:39:48 +01:00
|
|
|
#[cfg_attr(target_os = "windows", ignore)]
|
2021-11-08 18:31:27 +01:00
|
|
|
async fn access_authorized_stats_no_index_restriction() {
|
|
|
|
let mut server = Server::new_auth().await;
|
2022-05-23 17:03:28 +02:00
|
|
|
server.use_admin_key("MASTER_KEY").await;
|
2021-11-08 18:31:27 +01:00
|
|
|
|
|
|
|
// create index `test`
|
|
|
|
let index = server.index("test");
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = index.create(Some("id")).await;
|
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
// create index `products`
|
|
|
|
let index = server.index("products");
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = index.create(Some("product_id")).await;
|
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
index.wait_task(0).await;
|
|
|
|
|
|
|
|
// create key with access on all indexes.
|
|
|
|
let content = json!({
|
|
|
|
"indexes": ["*"],
|
|
|
|
"actions": ["stats.get"],
|
2022-02-14 15:32:41 +01:00
|
|
|
"expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(),
|
2021-11-08 18:31:27 +01:00
|
|
|
});
|
|
|
|
let (response, code) = server.add_api_key(content).await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(201, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
assert!(response["key"].is_string());
|
|
|
|
|
|
|
|
// use created key.
|
|
|
|
let key = response["key"].as_str().unwrap();
|
|
|
|
server.use_api_key(&key);
|
|
|
|
|
|
|
|
let (response, code) = server.stats().await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(200, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
|
|
|
|
// key should have access on `products` index.
|
|
|
|
assert!(response["indexes"].get("products").is_some());
|
|
|
|
|
|
|
|
// key should have access on `test` index.
|
|
|
|
assert!(response["indexes"].get("test").is_some());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[actix_rt::test]
|
2021-12-22 12:39:48 +01:00
|
|
|
#[cfg_attr(target_os = "windows", ignore)]
|
2021-11-08 18:31:27 +01:00
|
|
|
async fn list_authorized_indexes_restricted_index() {
|
|
|
|
let mut server = Server::new_auth().await;
|
2022-05-23 17:03:28 +02:00
|
|
|
server.use_admin_key("MASTER_KEY").await;
|
2021-11-08 18:31:27 +01:00
|
|
|
|
|
|
|
// create index `test`
|
|
|
|
let index = server.index("test");
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = index.create(Some("id")).await;
|
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
// create index `products`
|
|
|
|
let index = server.index("products");
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = index.create(Some("product_id")).await;
|
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
index.wait_task(0).await;
|
|
|
|
|
|
|
|
// create key with access on `products` index only.
|
|
|
|
let content = json!({
|
|
|
|
"indexes": ["products"],
|
|
|
|
"actions": ["indexes.get"],
|
2022-02-14 15:32:41 +01:00
|
|
|
"expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(),
|
2021-11-08 18:31:27 +01:00
|
|
|
});
|
|
|
|
let (response, code) = server.add_api_key(content).await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(201, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
assert!(response["key"].is_string());
|
|
|
|
|
|
|
|
// use created key.
|
|
|
|
let key = response["key"].as_str().unwrap();
|
|
|
|
server.use_api_key(&key);
|
|
|
|
|
2022-05-24 11:29:03 +02:00
|
|
|
let (response, code) = server.list_indexes(None, None).await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(200, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
|
2022-05-24 11:29:03 +02:00
|
|
|
let response = response["results"].as_array().unwrap();
|
2021-11-08 18:31:27 +01:00
|
|
|
// key should have access on `products` index.
|
|
|
|
assert!(response.iter().any(|index| index["uid"] == "products"));
|
|
|
|
|
|
|
|
// key should not have access on `test` index.
|
|
|
|
assert!(!response.iter().any(|index| index["uid"] == "test"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[actix_rt::test]
|
2021-12-22 12:39:48 +01:00
|
|
|
#[cfg_attr(target_os = "windows", ignore)]
|
2021-11-08 18:31:27 +01:00
|
|
|
async fn list_authorized_indexes_no_index_restriction() {
|
|
|
|
let mut server = Server::new_auth().await;
|
2022-05-23 17:03:28 +02:00
|
|
|
server.use_admin_key("MASTER_KEY").await;
|
2021-11-08 18:31:27 +01:00
|
|
|
|
|
|
|
// create index `test`
|
|
|
|
let index = server.index("test");
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = index.create(Some("id")).await;
|
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
// create index `products`
|
|
|
|
let index = server.index("products");
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = index.create(Some("product_id")).await;
|
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
index.wait_task(0).await;
|
|
|
|
|
|
|
|
// create key with access on all indexes.
|
|
|
|
let content = json!({
|
|
|
|
"indexes": ["*"],
|
|
|
|
"actions": ["indexes.get"],
|
2022-02-14 15:32:41 +01:00
|
|
|
"expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(),
|
2021-11-08 18:31:27 +01:00
|
|
|
});
|
|
|
|
let (response, code) = server.add_api_key(content).await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(201, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
assert!(response["key"].is_string());
|
|
|
|
|
|
|
|
// use created key.
|
|
|
|
let key = response["key"].as_str().unwrap();
|
|
|
|
server.use_api_key(&key);
|
|
|
|
|
2022-05-24 11:29:03 +02:00
|
|
|
let (response, code) = server.list_indexes(None, None).await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(200, code, "{:?}", &response);
|
2021-11-08 18:31:27 +01:00
|
|
|
|
2022-05-24 11:29:03 +02:00
|
|
|
let response = response["results"].as_array().unwrap();
|
2021-11-08 18:31:27 +01:00
|
|
|
// key should have access on `products` index.
|
|
|
|
assert!(response.iter().any(|index| index["uid"] == "products"));
|
|
|
|
|
|
|
|
// key should have access on `test` index.
|
|
|
|
assert!(response.iter().any(|index| index["uid"] == "test"));
|
|
|
|
}
|
2021-12-06 15:45:41 +01:00
|
|
|
|
|
|
|
#[actix_rt::test]
|
|
|
|
async fn list_authorized_tasks_restricted_index() {
|
|
|
|
let mut server = Server::new_auth().await;
|
2022-05-23 17:03:28 +02:00
|
|
|
server.use_admin_key("MASTER_KEY").await;
|
2021-12-06 15:45:41 +01:00
|
|
|
|
|
|
|
// create index `test`
|
|
|
|
let index = server.index("test");
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = index.create(Some("id")).await;
|
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2021-12-06 15:45:41 +01:00
|
|
|
// create index `products`
|
|
|
|
let index = server.index("products");
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = index.create(Some("product_id")).await;
|
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2021-12-06 15:45:41 +01:00
|
|
|
index.wait_task(0).await;
|
|
|
|
|
|
|
|
// create key with access on `products` index only.
|
|
|
|
let content = json!({
|
|
|
|
"indexes": ["products"],
|
|
|
|
"actions": ["tasks.get"],
|
2022-02-14 15:32:41 +01:00
|
|
|
"expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(),
|
2021-12-06 15:45:41 +01:00
|
|
|
});
|
|
|
|
let (response, code) = server.add_api_key(content).await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(201, code, "{:?}", &response);
|
2021-12-06 15:45:41 +01:00
|
|
|
assert!(response["key"].is_string());
|
|
|
|
|
|
|
|
// use created key.
|
|
|
|
let key = response["key"].as_str().unwrap();
|
|
|
|
server.use_api_key(&key);
|
|
|
|
|
|
|
|
let (response, code) = server.service.get("/tasks").await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(200, code, "{:?}", &response);
|
2021-12-06 15:45:41 +01:00
|
|
|
println!("{}", response);
|
|
|
|
let response = response["results"].as_array().unwrap();
|
|
|
|
// key should have access on `products` index.
|
|
|
|
assert!(response.iter().any(|task| task["indexUid"] == "products"));
|
|
|
|
|
|
|
|
// key should not have access on `test` index.
|
|
|
|
assert!(!response.iter().any(|task| task["indexUid"] == "test"));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[actix_rt::test]
|
|
|
|
async fn list_authorized_tasks_no_index_restriction() {
|
|
|
|
let mut server = Server::new_auth().await;
|
2022-05-23 17:03:28 +02:00
|
|
|
server.use_admin_key("MASTER_KEY").await;
|
2021-12-06 15:45:41 +01:00
|
|
|
|
|
|
|
// create index `test`
|
|
|
|
let index = server.index("test");
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = index.create(Some("id")).await;
|
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2021-12-06 15:45:41 +01:00
|
|
|
// create index `products`
|
|
|
|
let index = server.index("products");
|
2022-05-23 17:03:28 +02:00
|
|
|
let (response, code) = index.create(Some("product_id")).await;
|
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2021-12-06 15:45:41 +01:00
|
|
|
index.wait_task(0).await;
|
|
|
|
|
|
|
|
// create key with access on all indexes.
|
|
|
|
let content = json!({
|
|
|
|
"indexes": ["*"],
|
|
|
|
"actions": ["tasks.get"],
|
2022-02-14 15:32:41 +01:00
|
|
|
"expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(),
|
2021-12-06 15:45:41 +01:00
|
|
|
});
|
|
|
|
let (response, code) = server.add_api_key(content).await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(201, code, "{:?}", &response);
|
2021-12-06 15:45:41 +01:00
|
|
|
assert!(response["key"].is_string());
|
|
|
|
|
|
|
|
// use created key.
|
|
|
|
let key = response["key"].as_str().unwrap();
|
|
|
|
server.use_api_key(&key);
|
|
|
|
|
|
|
|
let (response, code) = server.service.get("/tasks").await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(200, code, "{:?}", &response);
|
2021-12-06 15:45:41 +01:00
|
|
|
|
|
|
|
let response = response["results"].as_array().unwrap();
|
|
|
|
// key should have access on `products` index.
|
|
|
|
assert!(response.iter().any(|task| task["indexUid"] == "products"));
|
|
|
|
|
|
|
|
// key should have access on `test` index.
|
|
|
|
assert!(response.iter().any(|task| task["indexUid"] == "test"));
|
|
|
|
}
|
2021-12-15 14:52:33 +01:00
|
|
|
|
|
|
|
#[actix_rt::test]
|
|
|
|
async fn error_creating_index_without_action() {
|
|
|
|
let mut server = Server::new_auth().await;
|
|
|
|
server.use_api_key("MASTER_KEY");
|
|
|
|
|
|
|
|
// create key with access on all indexes.
|
|
|
|
let content = json!({
|
|
|
|
"indexes": ["*"],
|
2022-01-24 15:06:31 +01:00
|
|
|
// Give all action but the ones allowing to create an index.
|
|
|
|
"actions": ALL_ACTIONS.iter().cloned().filter(|a| !AUTHORIZATIONS.get(&("POST","/indexes")).unwrap().contains(a)).collect::<Vec<_>>(),
|
2021-12-15 14:52:33 +01:00
|
|
|
"expiresAt": "2050-11-13T00:00:00Z"
|
|
|
|
});
|
|
|
|
let (response, code) = server.add_api_key(content).await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(201, code, "{:?}", &response);
|
2021-12-15 14:52:33 +01:00
|
|
|
assert!(response["key"].is_string());
|
|
|
|
|
|
|
|
// use created key.
|
|
|
|
let key = response["key"].as_str().unwrap();
|
|
|
|
server.use_api_key(&key);
|
|
|
|
|
|
|
|
let expected_error = json!({
|
|
|
|
"message": "Index `test` not found.",
|
|
|
|
"code": "index_not_found",
|
|
|
|
"type": "invalid_request",
|
|
|
|
"link": "https://docs.meilisearch.com/errors#index_not_found"
|
|
|
|
});
|
|
|
|
|
|
|
|
// 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;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2022-05-17 11:17:32 +02:00
|
|
|
let task_id = response["taskUid"].as_u64().unwrap();
|
2021-12-15 14:52:33 +01:00
|
|
|
|
|
|
|
let response = index.wait_task(task_id).await;
|
|
|
|
assert_eq!(response["status"], "failed");
|
|
|
|
assert_eq!(response["error"], expected_error.clone());
|
|
|
|
|
|
|
|
// try to create a index via add settings route
|
|
|
|
let settings = json!({ "distinctAttribute": "test"});
|
|
|
|
|
|
|
|
let (response, code) = index.update_settings(settings).await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2022-05-17 11:17:32 +02:00
|
|
|
let task_id = response["taskUid"].as_u64().unwrap();
|
2021-12-15 14:52:33 +01:00
|
|
|
|
|
|
|
let response = index.wait_task(task_id).await;
|
|
|
|
|
|
|
|
assert_eq!(response["status"], "failed");
|
|
|
|
assert_eq!(response["error"], expected_error.clone());
|
|
|
|
|
|
|
|
// try to create a index via add specialized settings route
|
|
|
|
let (response, code) = index.update_distinct_attribute(json!("test")).await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(202, code, "{:?}", &response);
|
2022-05-17 11:17:32 +02:00
|
|
|
let task_id = response["taskUid"].as_u64().unwrap();
|
2021-12-15 14:52:33 +01:00
|
|
|
|
|
|
|
let response = index.wait_task(task_id).await;
|
|
|
|
|
|
|
|
assert_eq!(response["status"], "failed");
|
|
|
|
assert_eq!(response["error"], expected_error.clone());
|
|
|
|
}
|
|
|
|
|
|
|
|
#[actix_rt::test]
|
|
|
|
async fn lazy_create_index() {
|
|
|
|
let mut server = Server::new_auth().await;
|
2022-09-06 15:13:09 +02:00
|
|
|
|
|
|
|
// 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;
|
2021-12-15 14:52:33 +01:00
|
|
|
server.use_api_key("MASTER_KEY");
|
|
|
|
|
|
|
|
// create key with access on all indexes.
|
|
|
|
let content = json!({
|
2022-09-06 15:13:09 +02:00
|
|
|
"indexes": ["unexpected"],
|
2021-12-15 14:52:33 +01:00
|
|
|
"actions": ["*"],
|
|
|
|
"expiresAt": "2050-11-13T00:00:00Z"
|
|
|
|
});
|
|
|
|
|
|
|
|
let (response, code) = server.add_api_key(content).await;
|
2022-05-23 17:03:28 +02:00
|
|
|
assert_eq!(201, code, "{:?}", &response);
|
2021-12-15 14:52:33 +01:00
|
|
|
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;
|
2022-09-06 15:13:09 +02:00
|
|
|
assert_eq!(403, code, "{:?}", &response);
|
2021-12-15 14:52:33 +01:00
|
|
|
|
|
|
|
// 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;
|
2022-09-06 15:13:09 +02:00
|
|
|
assert_eq!(403, code, "{:?}", &response);
|
2021-12-15 14:52:33 +01:00
|
|
|
|
|
|
|
// 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;
|
2022-09-06 15:13:09 +02:00
|
|
|
assert_eq!(403, code, "{:?}", &response);
|
2021-12-15 14:52:33 +01:00
|
|
|
|
2022-09-06 15:13:09 +02:00
|
|
|
// 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);
|
2021-12-15 14:52:33 +01:00
|
|
|
}
|