mirror of
				https://github.com/meilisearch/meilisearch.git
				synced 2025-10-30 23:46:28 +00:00 
			
		
		
		
	meta(auth): Enhance tests on authorization
Enhance auth tests in order to be able to add new action without changing tests
This commit is contained in:
		| @@ -1,56 +1,61 @@ | ||||
| use crate::common::Server; | ||||
| use chrono::{Duration, Utc}; | ||||
| use maplit::hashmap; | ||||
| use maplit::{hashmap, hashset}; | ||||
| use once_cell::sync::Lazy; | ||||
| use serde_json::{json, Value}; | ||||
| use std::collections::{HashMap, HashSet}; | ||||
|  | ||||
| static AUTHORIZATIONS: Lazy<HashMap<(&'static str, &'static str), &'static str>> = | ||||
| static AUTHORIZATIONS: Lazy<HashMap<(&'static str, &'static str), HashSet<&'static str>>> = | ||||
|     Lazy::new(|| { | ||||
|         hashmap! { | ||||
|             ("POST",    "/indexes/products/search") =>                         "search", | ||||
|             ("GET",     "/indexes/products/search") =>                         "search", | ||||
|             ("POST",    "/indexes/products/documents") =>                      "documents.add", | ||||
|             ("GET",     "/indexes/products/documents") =>                      "documents.get", | ||||
|             ("GET",     "/indexes/products/documents/0") =>                    "documents.get", | ||||
|             ("DELETE",  "/indexes/products/documents/0") =>                    "documents.delete", | ||||
|             ("GET",     "/tasks") =>                                           "tasks.get", | ||||
|             ("GET",     "/indexes/products/tasks") =>                          "tasks.get", | ||||
|             ("GET",     "/indexes/products/tasks/0") =>                        "tasks.get", | ||||
|             ("PUT",     "/indexes/products/") =>                               "indexes.update", | ||||
|             ("GET",     "/indexes/products/") =>                               "indexes.get", | ||||
|             ("DELETE",  "/indexes/products/") =>                               "indexes.delete", | ||||
|             ("POST",    "/indexes") =>                                         "indexes.create", | ||||
|             ("GET",     "/indexes") =>                                         "indexes.get", | ||||
|             ("GET",     "/indexes/products/settings") =>                       "settings.get", | ||||
|             ("GET",     "/indexes/products/settings/displayed-attributes") =>  "settings.get", | ||||
|             ("GET",     "/indexes/products/settings/distinct-attribute") =>    "settings.get", | ||||
|             ("GET",     "/indexes/products/settings/filterable-attributes") => "settings.get", | ||||
|             ("GET",     "/indexes/products/settings/ranking-rules") =>         "settings.get", | ||||
|             ("GET",     "/indexes/products/settings/searchable-attributes") => "settings.get", | ||||
|             ("GET",     "/indexes/products/settings/sortable-attributes") =>   "settings.get", | ||||
|             ("GET",     "/indexes/products/settings/stop-words") =>            "settings.get", | ||||
|             ("GET",     "/indexes/products/settings/synonyms") =>              "settings.get", | ||||
|             ("DELETE",  "/indexes/products/settings") =>                       "settings.update", | ||||
|             ("POST",    "/indexes/products/settings") =>                       "settings.update", | ||||
|             ("POST",    "/indexes/products/settings/displayed-attributes") =>  "settings.update", | ||||
|             ("POST",    "/indexes/products/settings/distinct-attribute") =>    "settings.update", | ||||
|             ("POST",    "/indexes/products/settings/filterable-attributes") => "settings.update", | ||||
|             ("POST",    "/indexes/products/settings/ranking-rules") =>         "settings.update", | ||||
|             ("POST",    "/indexes/products/settings/searchable-attributes") => "settings.update", | ||||
|             ("POST",    "/indexes/products/settings/sortable-attributes") =>   "settings.update", | ||||
|             ("POST",    "/indexes/products/settings/stop-words") =>            "settings.update", | ||||
|             ("POST",    "/indexes/products/settings/synonyms") =>              "settings.update", | ||||
|             ("GET",     "/indexes/products/stats") =>                          "stats.get", | ||||
|             ("GET",     "/stats") =>                                           "stats.get", | ||||
|             ("POST",    "/dumps") =>                                           "dumps.create", | ||||
|             ("GET",     "/dumps/0/status") =>                                  "dumps.get", | ||||
|             ("GET",     "/version") =>                                         "version", | ||||
|             ("POST",    "/indexes/products/search") =>                         hashset!{"search", "*"}, | ||||
|             ("GET",     "/indexes/products/search") =>                         hashset!{"search", "*"}, | ||||
|             ("POST",    "/indexes/products/documents") =>                      hashset!{"documents.add", "*"}, | ||||
|             ("GET",     "/indexes/products/documents") =>                      hashset!{"documents.get", "*"}, | ||||
|             ("GET",     "/indexes/products/documents/0") =>                    hashset!{"documents.get", "*"}, | ||||
|             ("DELETE",  "/indexes/products/documents/0") =>                    hashset!{"documents.delete", "*"}, | ||||
|             ("GET",     "/tasks") =>                                           hashset!{"tasks.get", "*"}, | ||||
|             ("GET",     "/indexes/products/tasks") =>                          hashset!{"tasks.get", "*"}, | ||||
|             ("GET",     "/indexes/products/tasks/0") =>                        hashset!{"tasks.get", "*"}, | ||||
|             ("PUT",     "/indexes/products/") =>                               hashset!{"indexes.update", "*"}, | ||||
|             ("GET",     "/indexes/products/") =>                               hashset!{"indexes.get", "*"}, | ||||
|             ("DELETE",  "/indexes/products/") =>                               hashset!{"indexes.delete", "*"}, | ||||
|             ("POST",    "/indexes") =>                                         hashset!{"indexes.create", "*"}, | ||||
|             ("GET",     "/indexes") =>                                         hashset!{"indexes.get", "*"}, | ||||
|             ("GET",     "/indexes/products/settings") =>                       hashset!{"settings.get", "*"}, | ||||
|             ("GET",     "/indexes/products/settings/displayed-attributes") =>  hashset!{"settings.get", "*"}, | ||||
|             ("GET",     "/indexes/products/settings/distinct-attribute") =>    hashset!{"settings.get", "*"}, | ||||
|             ("GET",     "/indexes/products/settings/filterable-attributes") => hashset!{"settings.get", "*"}, | ||||
|             ("GET",     "/indexes/products/settings/ranking-rules") =>         hashset!{"settings.get", "*"}, | ||||
|             ("GET",     "/indexes/products/settings/searchable-attributes") => hashset!{"settings.get", "*"}, | ||||
|             ("GET",     "/indexes/products/settings/sortable-attributes") =>   hashset!{"settings.get", "*"}, | ||||
|             ("GET",     "/indexes/products/settings/stop-words") =>            hashset!{"settings.get", "*"}, | ||||
|             ("GET",     "/indexes/products/settings/synonyms") =>              hashset!{"settings.get", "*"}, | ||||
|             ("DELETE",  "/indexes/products/settings") =>                       hashset!{"settings.update", "*"}, | ||||
|             ("POST",    "/indexes/products/settings") =>                       hashset!{"settings.update", "*"}, | ||||
|             ("POST",    "/indexes/products/settings/displayed-attributes") =>  hashset!{"settings.update", "*"}, | ||||
|             ("POST",    "/indexes/products/settings/distinct-attribute") =>    hashset!{"settings.update", "*"}, | ||||
|             ("POST",    "/indexes/products/settings/filterable-attributes") => hashset!{"settings.update", "*"}, | ||||
|             ("POST",    "/indexes/products/settings/ranking-rules") =>         hashset!{"settings.update", "*"}, | ||||
|             ("POST",    "/indexes/products/settings/searchable-attributes") => hashset!{"settings.update", "*"}, | ||||
|             ("POST",    "/indexes/products/settings/sortable-attributes") =>   hashset!{"settings.update", "*"}, | ||||
|             ("POST",    "/indexes/products/settings/stop-words") =>            hashset!{"settings.update", "*"}, | ||||
|             ("POST",    "/indexes/products/settings/synonyms") =>              hashset!{"settings.update", "*"}, | ||||
|             ("GET",     "/indexes/products/stats") =>                          hashset!{"stats.get", "*"}, | ||||
|             ("GET",     "/stats") =>                                           hashset!{"stats.get", "*"}, | ||||
|             ("POST",    "/dumps") =>                                           hashset!{"dumps.create", "*"}, | ||||
|             ("GET",     "/dumps/0/status") =>                                  hashset!{"dumps.get", "*"}, | ||||
|             ("GET",     "/version") =>                                         hashset!{"version", "*"}, | ||||
|         } | ||||
|     }); | ||||
|  | ||||
| static ALL_ACTIONS: Lazy<HashSet<&'static str>> = | ||||
|     Lazy::new(|| AUTHORIZATIONS.values().cloned().collect()); | ||||
| static ALL_ACTIONS: Lazy<HashSet<&'static str>> = Lazy::new(|| { | ||||
|     AUTHORIZATIONS | ||||
|         .values() | ||||
|         .cloned() | ||||
|         .reduce(|l, r| l.union(&r).cloned().collect()) | ||||
|         .unwrap() | ||||
| }); | ||||
|  | ||||
| static INVALID_RESPONSE: Lazy<Value> = Lazy::new(|| { | ||||
|     json!({"message": "The provided API key is invalid.", | ||||
| @@ -147,7 +152,7 @@ async fn error_access_unauthorized_action() { | ||||
|  | ||||
|         // Patch API key letting all rights but the needed one. | ||||
|         let content = json!({ | ||||
|             "actions": ALL_ACTIONS.iter().cloned().filter(|a| a != action).collect::<Vec<_>>(), | ||||
|             "actions": ALL_ACTIONS.difference(action).collect::<Vec<_>>(), | ||||
|         }); | ||||
|         let (_, code) = server.patch_api_key(&key, content).await; | ||||
|         assert_eq!(code, 200); | ||||
| @@ -179,36 +184,23 @@ async fn access_authorized_restricted_index() { | ||||
|     let key = response["key"].as_str().unwrap(); | ||||
|     server.use_api_key(&key); | ||||
|  | ||||
|     for ((method, route), action) in AUTHORIZATIONS.iter() { | ||||
|         // Patch API key letting only the needed action. | ||||
|         let content = json!({ | ||||
|             "actions": [action], | ||||
|         }); | ||||
|     for ((method, route), actions) in AUTHORIZATIONS.iter() { | ||||
|         for action in actions { | ||||
|             // Patch API key letting only the needed action. | ||||
|             let content = json!({ | ||||
|                 "actions": [action], | ||||
|             }); | ||||
|  | ||||
|         server.use_api_key("MASTER_KEY"); | ||||
|         let (_, code) = server.patch_api_key(&key, content).await; | ||||
|         assert_eq!(code, 200); | ||||
|             server.use_api_key("MASTER_KEY"); | ||||
|             let (_, code) = server.patch_api_key(&key, content).await; | ||||
|             assert_eq!(code, 200); | ||||
|  | ||||
|         server.use_api_key(&key); | ||||
|         let (response, code) = server.dummy_request(method, route).await; | ||||
|             server.use_api_key(&key); | ||||
|             let (response, code) = server.dummy_request(method, route).await; | ||||
|  | ||||
|         assert_ne!(response, INVALID_RESPONSE.clone()); | ||||
|         assert_ne!(code, 403); | ||||
|  | ||||
|         // Patch API key using action all action. | ||||
|         let content = json!({ | ||||
|             "actions": ["*"], | ||||
|         }); | ||||
|  | ||||
|         server.use_api_key("MASTER_KEY"); | ||||
|         let (_, code) = server.patch_api_key(&key, content).await; | ||||
|         assert_eq!(code, 200); | ||||
|  | ||||
|         server.use_api_key(&key); | ||||
|         let (response, code) = server.dummy_request(method, route).await; | ||||
|  | ||||
|         assert_ne!(response, INVALID_RESPONSE.clone()); | ||||
|         assert_ne!(code, 403); | ||||
|             assert_ne!(response, INVALID_RESPONSE.clone()); | ||||
|             assert_ne!(code, 403); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -231,36 +223,23 @@ async fn access_authorized_no_index_restriction() { | ||||
|     let key = response["key"].as_str().unwrap(); | ||||
|     server.use_api_key(&key); | ||||
|  | ||||
|     for ((method, route), action) in AUTHORIZATIONS.iter() { | ||||
|         server.use_api_key("MASTER_KEY"); | ||||
|     for ((method, route), actions) in AUTHORIZATIONS.iter() { | ||||
|         for action in actions { | ||||
|             server.use_api_key("MASTER_KEY"); | ||||
|  | ||||
|         // Patch API key letting only the needed action. | ||||
|         let content = json!({ | ||||
|             "actions": [action], | ||||
|         }); | ||||
|         let (_, code) = server.patch_api_key(&key, content).await; | ||||
|         assert_eq!(code, 200); | ||||
|             // Patch API key letting only the needed action. | ||||
|             let content = json!({ | ||||
|                 "actions": [action], | ||||
|             }); | ||||
|             let (_, code) = server.patch_api_key(&key, content).await; | ||||
|             assert_eq!(code, 200); | ||||
|  | ||||
|         server.use_api_key(&key); | ||||
|         let (response, code) = server.dummy_request(method, route).await; | ||||
|             server.use_api_key(&key); | ||||
|             let (response, code) = server.dummy_request(method, route).await; | ||||
|  | ||||
|         assert_ne!(response, INVALID_RESPONSE.clone()); | ||||
|         assert_ne!(code, 403); | ||||
|  | ||||
|         // Patch API key using action all action. | ||||
|         let content = json!({ | ||||
|             "actions": ["*"], | ||||
|         }); | ||||
|  | ||||
|         server.use_api_key("MASTER_KEY"); | ||||
|         let (_, code) = server.patch_api_key(&key, content).await; | ||||
|         assert_eq!(code, 200); | ||||
|  | ||||
|         server.use_api_key(&key); | ||||
|         let (response, code) = server.dummy_request(method, route).await; | ||||
|  | ||||
|         assert_ne!(response, INVALID_RESPONSE.clone()); | ||||
|         assert_ne!(code, 403); | ||||
|             assert_ne!(response, INVALID_RESPONSE.clone()); | ||||
|             assert_ne!(code, 403); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| @@ -514,7 +493,8 @@ async fn error_creating_index_without_action() { | ||||
|     // create key with access on all indexes. | ||||
|     let content = json!({ | ||||
|         "indexes": ["*"], | ||||
|         "actions": ALL_ACTIONS.iter().cloned().filter(|a| *a != "indexes.create").collect::<Vec<_>>(), | ||||
|         // 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<_>>(), | ||||
|         "expiresAt": "2050-11-13T00:00:00Z" | ||||
|     }); | ||||
|     let (response, code) = server.add_api_key(content).await; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user