diff --git a/meilisearch-auth/src/action.rs b/meilisearch-auth/src/action.rs index ef11c3a00..94a15eb9d 100644 --- a/meilisearch-auth/src/action.rs +++ b/meilisearch-auth/src/action.rs @@ -1,7 +1,8 @@ use enum_iterator::IntoEnumIterator; use serde::{Deserialize, Serialize}; +use std::hash::Hash; -#[derive(IntoEnumIterator, Copy, Clone, Serialize, Deserialize, Debug, Eq, PartialEq)] +#[derive(IntoEnumIterator, Copy, Clone, Serialize, Deserialize, Debug, Eq, PartialEq, Hash)] #[repr(u8)] pub enum Action { #[serde(rename = "*")] @@ -16,6 +17,8 @@ pub enum Action { DocumentsGet = actions::DOCUMENTS_GET, #[serde(rename = "documents.delete")] DocumentsDelete = actions::DOCUMENTS_DELETE, + #[serde(rename = "indexes.*")] + IndexesAll = actions::INDEXES_ALL, #[serde(rename = "indexes.create")] IndexesAdd = actions::INDEXES_CREATE, #[serde(rename = "indexes.get")] @@ -24,14 +27,22 @@ pub enum Action { IndexesUpdate = actions::INDEXES_UPDATE, #[serde(rename = "indexes.delete")] IndexesDelete = actions::INDEXES_DELETE, + #[serde(rename = "tasks.*")] + TasksAll = actions::TASKS_ALL, #[serde(rename = "tasks.get")] TasksGet = actions::TASKS_GET, + #[serde(rename = "settings.*")] + SettingsAll = actions::SETTINGS_ALL, #[serde(rename = "settings.get")] SettingsGet = actions::SETTINGS_GET, #[serde(rename = "settings.update")] SettingsUpdate = actions::SETTINGS_UPDATE, + #[serde(rename = "stats.*")] + StatsAll = actions::STATS_ALL, #[serde(rename = "stats.get")] StatsGet = actions::STATS_GET, + #[serde(rename = "dumps.*")] + DumpsAll = actions::DUMPS_ALL, #[serde(rename = "dumps.create")] DumpsCreate = actions::DUMPS_CREATE, #[serde(rename = "version")] @@ -56,14 +67,19 @@ impl Action { DOCUMENTS_ADD => Some(Self::DocumentsAdd), DOCUMENTS_GET => Some(Self::DocumentsGet), DOCUMENTS_DELETE => Some(Self::DocumentsDelete), + INDEXES_ALL => Some(Self::IndexesAll), INDEXES_CREATE => Some(Self::IndexesAdd), INDEXES_GET => Some(Self::IndexesGet), INDEXES_UPDATE => Some(Self::IndexesUpdate), INDEXES_DELETE => Some(Self::IndexesDelete), + TASKS_ALL => Some(Self::TasksAll), TASKS_GET => Some(Self::TasksGet), + SETTINGS_ALL => Some(Self::SettingsAll), SETTINGS_GET => Some(Self::SettingsGet), SETTINGS_UPDATE => Some(Self::SettingsUpdate), + STATS_ALL => Some(Self::StatsAll), STATS_GET => Some(Self::StatsGet), + DUMPS_ALL => Some(Self::DumpsAll), DUMPS_CREATE => Some(Self::DumpsCreate), VERSION => Some(Self::Version), KEYS_CREATE => Some(Self::KeysAdd), @@ -83,14 +99,19 @@ impl Action { Self::DocumentsAdd => DOCUMENTS_ADD, Self::DocumentsGet => DOCUMENTS_GET, Self::DocumentsDelete => DOCUMENTS_DELETE, + Self::IndexesAll => INDEXES_ALL, Self::IndexesAdd => INDEXES_CREATE, Self::IndexesGet => INDEXES_GET, Self::IndexesUpdate => INDEXES_UPDATE, Self::IndexesDelete => INDEXES_DELETE, + Self::TasksAll => TASKS_ALL, Self::TasksGet => TASKS_GET, + Self::SettingsAll => SETTINGS_ALL, Self::SettingsGet => SETTINGS_GET, Self::SettingsUpdate => SETTINGS_UPDATE, + Self::StatsAll => STATS_ALL, Self::StatsGet => STATS_GET, + Self::DumpsAll => DUMPS_ALL, Self::DumpsCreate => DUMPS_CREATE, Self::Version => VERSION, Self::KeysAdd => KEYS_CREATE, @@ -108,18 +129,23 @@ pub mod actions { pub const DOCUMENTS_ADD: u8 = 3; pub const DOCUMENTS_GET: u8 = 4; pub const DOCUMENTS_DELETE: u8 = 5; - pub const INDEXES_CREATE: u8 = 6; - pub const INDEXES_GET: u8 = 7; - pub const INDEXES_UPDATE: u8 = 8; - pub const INDEXES_DELETE: u8 = 9; - pub const TASKS_GET: u8 = 10; - pub const SETTINGS_GET: u8 = 11; - pub const SETTINGS_UPDATE: u8 = 12; - pub const STATS_GET: u8 = 13; - pub const DUMPS_CREATE: u8 = 14; - pub const VERSION: u8 = 15; - pub const KEYS_CREATE: u8 = 16; - pub const KEYS_GET: u8 = 17; - pub const KEYS_UPDATE: u8 = 18; - pub const KEYS_DELETE: u8 = 19; + pub const INDEXES_ALL: u8 = 6; + pub const INDEXES_CREATE: u8 = 7; + pub const INDEXES_GET: u8 = 8; + pub const INDEXES_UPDATE: u8 = 9; + pub const INDEXES_DELETE: u8 = 10; + pub const TASKS_ALL: u8 = 11; + pub const TASKS_GET: u8 = 12; + pub const SETTINGS_ALL: u8 = 13; + pub const SETTINGS_GET: u8 = 14; + pub const SETTINGS_UPDATE: u8 = 15; + pub const STATS_ALL: u8 = 16; + pub const STATS_GET: u8 = 17; + pub const DUMPS_ALL: u8 = 18; + pub const DUMPS_CREATE: u8 = 19; + pub const VERSION: u8 = 20; + pub const KEYS_CREATE: u8 = 21; + pub const KEYS_GET: u8 = 22; + pub const KEYS_UPDATE: u8 = 23; + pub const KEYS_DELETE: u8 = 24; } diff --git a/meilisearch-auth/src/store.rs b/meilisearch-auth/src/store.rs index f9d6e7728..f21382068 100644 --- a/meilisearch-auth/src/store.rs +++ b/meilisearch-auth/src/store.rs @@ -1,5 +1,6 @@ use std::borrow::Cow; use std::cmp::Reverse; +use std::collections::HashSet; use std::convert::TryFrom; use std::convert::TryInto; use std::fs::create_dir_all; @@ -87,21 +88,48 @@ impl HeedAuthStore { // create inverted database. let db = self.action_keyid_index_expiration; - let actions = if key.actions.contains(&Action::All) { - // if key.actions contains All, we iterate over all actions. - Action::into_enum_iter().collect() - } else if key.actions.contains(&Action::DocumentsAll) { - // if key.actions.contains.DocumentsAll add all actions related to documents. - let mut actions = key.actions.clone(); - actions.append(&mut vec![ - Action::DocumentsAdd, - Action::DocumentsGet, - Action::DocumentsDelete, - ]); - actions - } else { - key.actions.clone() - }; + let mut actions = HashSet::new(); + for action in &key.actions { + match action { + Action::All => actions.extend(Action::into_enum_iter()), + Action::DocumentsAll => { + actions.extend( + [ + Action::DocumentsGet, + Action::DocumentsDelete, + Action::DocumentsAdd, + ] + .iter(), + ); + } + Action::IndexesAll => { + actions.extend( + [ + Action::IndexesAdd, + Action::IndexesDelete, + Action::IndexesGet, + Action::IndexesUpdate, + ] + .iter(), + ); + } + Action::SettingsAll => { + actions.extend([Action::SettingsGet, Action::SettingsUpdate].iter()); + } + Action::DumpsAll => { + actions.insert(Action::DumpsCreate); + } + Action::TasksAll => { + actions.insert(Action::TasksGet); + } + Action::StatsAll => { + actions.insert(Action::StatsGet); + } + other => { + actions.insert(*other); + } + } + } let no_index_restriction = key.indexes.contains(&StarOr::Star); for action in actions { diff --git a/meilisearch-http/tests/auth/authorization.rs b/meilisearch-http/tests/auth/authorization.rs index e790d1e4a..27a22de38 100644 --- a/meilisearch-http/tests/auth/authorization.rs +++ b/meilisearch-http/tests/auth/authorization.rs @@ -15,37 +15,37 @@ pub static AUTHORIZATIONS: Lazy hashset!{"documents.get", "documents.*", "*"}, ("GET", "/indexes/products/documents/0") => hashset!{"documents.get", "documents.*", "*"}, ("DELETE", "/indexes/products/documents/0") => hashset!{"documents.delete", "documents.*", "*"}, - ("GET", "/tasks") => hashset!{"tasks.get", "*"}, - ("GET", "/tasks?indexUid=products") => hashset!{"tasks.get", "*"}, - ("GET", "/tasks/0") => hashset!{"tasks.get", "*"}, - ("PATCH", "/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", "*"}, - ("PATCH", "/indexes/products/settings") => hashset!{"settings.update", "*"}, - ("PATCH", "/indexes/products/settings/typo-tolerance") => hashset!{"settings.update", "*"}, - ("PUT", "/indexes/products/settings/displayed-attributes") => hashset!{"settings.update", "*"}, - ("PUT", "/indexes/products/settings/distinct-attribute") => hashset!{"settings.update", "*"}, - ("PUT", "/indexes/products/settings/filterable-attributes") => hashset!{"settings.update", "*"}, - ("PUT", "/indexes/products/settings/ranking-rules") => hashset!{"settings.update", "*"}, - ("PUT", "/indexes/products/settings/searchable-attributes") => hashset!{"settings.update", "*"}, - ("PUT", "/indexes/products/settings/sortable-attributes") => hashset!{"settings.update", "*"}, - ("PUT", "/indexes/products/settings/stop-words") => hashset!{"settings.update", "*"}, - ("PUT", "/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", "/tasks") => hashset!{"tasks.get", "tasks.*", "*"}, + ("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.*", "*"}, + ("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.*", "*"}, ("GET", "/version") => hashset!{"version", "*"}, ("PATCH", "/keys/mykey/") => hashset!{"keys.update", "*"}, ("GET", "/keys/mykey/") => hashset!{"keys.get", "*"},