2579: API keys: adds action * for actions r=irevoire a=phdavis1027

# Pull Request
This is PR builds on `@janithpet's` addition to DocumentsAll; it's basically a copy-and-paste job, except I used ```iter.filter()``` to avoid the possibility for duplication that they mentioned. I'm not sure how much that matters.

Also, hi! This is my first open-source contribution and my first attempt to write Rust for anyone other than myself, so any feedback whatsoever is appreciated. 

## What does this PR do?
Fixes #2560

## PR checklist
Please check if your PR fulfills the following requirements:
- [x] Does this PR fix an existing issue?
- [x] Have you read the contributing guidelines?
- [x] Have you made sure that the title is accurate and descriptive of the changes?

Thank you so much for contributing to Meilisearch!


Co-authored-by: Phillip Davis <phdavis1027@gmail.com>
This commit is contained in:
bors[bot] 2022-07-07 08:54:23 +00:00 committed by GitHub
commit 0353537fef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 115 additions and 61 deletions

View File

@ -1,7 +1,8 @@
use enum_iterator::IntoEnumIterator; use enum_iterator::IntoEnumIterator;
use serde::{Deserialize, Serialize}; 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)] #[repr(u8)]
pub enum Action { pub enum Action {
#[serde(rename = "*")] #[serde(rename = "*")]
@ -16,6 +17,8 @@ pub enum Action {
DocumentsGet = actions::DOCUMENTS_GET, DocumentsGet = actions::DOCUMENTS_GET,
#[serde(rename = "documents.delete")] #[serde(rename = "documents.delete")]
DocumentsDelete = actions::DOCUMENTS_DELETE, DocumentsDelete = actions::DOCUMENTS_DELETE,
#[serde(rename = "indexes.*")]
IndexesAll = actions::INDEXES_ALL,
#[serde(rename = "indexes.create")] #[serde(rename = "indexes.create")]
IndexesAdd = actions::INDEXES_CREATE, IndexesAdd = actions::INDEXES_CREATE,
#[serde(rename = "indexes.get")] #[serde(rename = "indexes.get")]
@ -24,14 +27,22 @@ pub enum Action {
IndexesUpdate = actions::INDEXES_UPDATE, IndexesUpdate = actions::INDEXES_UPDATE,
#[serde(rename = "indexes.delete")] #[serde(rename = "indexes.delete")]
IndexesDelete = actions::INDEXES_DELETE, IndexesDelete = actions::INDEXES_DELETE,
#[serde(rename = "tasks.*")]
TasksAll = actions::TASKS_ALL,
#[serde(rename = "tasks.get")] #[serde(rename = "tasks.get")]
TasksGet = actions::TASKS_GET, TasksGet = actions::TASKS_GET,
#[serde(rename = "settings.*")]
SettingsAll = actions::SETTINGS_ALL,
#[serde(rename = "settings.get")] #[serde(rename = "settings.get")]
SettingsGet = actions::SETTINGS_GET, SettingsGet = actions::SETTINGS_GET,
#[serde(rename = "settings.update")] #[serde(rename = "settings.update")]
SettingsUpdate = actions::SETTINGS_UPDATE, SettingsUpdate = actions::SETTINGS_UPDATE,
#[serde(rename = "stats.*")]
StatsAll = actions::STATS_ALL,
#[serde(rename = "stats.get")] #[serde(rename = "stats.get")]
StatsGet = actions::STATS_GET, StatsGet = actions::STATS_GET,
#[serde(rename = "dumps.*")]
DumpsAll = actions::DUMPS_ALL,
#[serde(rename = "dumps.create")] #[serde(rename = "dumps.create")]
DumpsCreate = actions::DUMPS_CREATE, DumpsCreate = actions::DUMPS_CREATE,
#[serde(rename = "version")] #[serde(rename = "version")]
@ -56,14 +67,19 @@ impl Action {
DOCUMENTS_ADD => Some(Self::DocumentsAdd), DOCUMENTS_ADD => Some(Self::DocumentsAdd),
DOCUMENTS_GET => Some(Self::DocumentsGet), DOCUMENTS_GET => Some(Self::DocumentsGet),
DOCUMENTS_DELETE => Some(Self::DocumentsDelete), DOCUMENTS_DELETE => Some(Self::DocumentsDelete),
INDEXES_ALL => Some(Self::IndexesAll),
INDEXES_CREATE => Some(Self::IndexesAdd), INDEXES_CREATE => Some(Self::IndexesAdd),
INDEXES_GET => Some(Self::IndexesGet), INDEXES_GET => Some(Self::IndexesGet),
INDEXES_UPDATE => Some(Self::IndexesUpdate), INDEXES_UPDATE => Some(Self::IndexesUpdate),
INDEXES_DELETE => Some(Self::IndexesDelete), INDEXES_DELETE => Some(Self::IndexesDelete),
TASKS_ALL => Some(Self::TasksAll),
TASKS_GET => Some(Self::TasksGet), TASKS_GET => Some(Self::TasksGet),
SETTINGS_ALL => Some(Self::SettingsAll),
SETTINGS_GET => Some(Self::SettingsGet), SETTINGS_GET => Some(Self::SettingsGet),
SETTINGS_UPDATE => Some(Self::SettingsUpdate), SETTINGS_UPDATE => Some(Self::SettingsUpdate),
STATS_ALL => Some(Self::StatsAll),
STATS_GET => Some(Self::StatsGet), STATS_GET => Some(Self::StatsGet),
DUMPS_ALL => Some(Self::DumpsAll),
DUMPS_CREATE => Some(Self::DumpsCreate), DUMPS_CREATE => Some(Self::DumpsCreate),
VERSION => Some(Self::Version), VERSION => Some(Self::Version),
KEYS_CREATE => Some(Self::KeysAdd), KEYS_CREATE => Some(Self::KeysAdd),
@ -83,14 +99,19 @@ impl Action {
Self::DocumentsAdd => DOCUMENTS_ADD, Self::DocumentsAdd => DOCUMENTS_ADD,
Self::DocumentsGet => DOCUMENTS_GET, Self::DocumentsGet => DOCUMENTS_GET,
Self::DocumentsDelete => DOCUMENTS_DELETE, Self::DocumentsDelete => DOCUMENTS_DELETE,
Self::IndexesAll => INDEXES_ALL,
Self::IndexesAdd => INDEXES_CREATE, Self::IndexesAdd => INDEXES_CREATE,
Self::IndexesGet => INDEXES_GET, Self::IndexesGet => INDEXES_GET,
Self::IndexesUpdate => INDEXES_UPDATE, Self::IndexesUpdate => INDEXES_UPDATE,
Self::IndexesDelete => INDEXES_DELETE, Self::IndexesDelete => INDEXES_DELETE,
Self::TasksAll => TASKS_ALL,
Self::TasksGet => TASKS_GET, Self::TasksGet => TASKS_GET,
Self::SettingsAll => SETTINGS_ALL,
Self::SettingsGet => SETTINGS_GET, Self::SettingsGet => SETTINGS_GET,
Self::SettingsUpdate => SETTINGS_UPDATE, Self::SettingsUpdate => SETTINGS_UPDATE,
Self::StatsAll => STATS_ALL,
Self::StatsGet => STATS_GET, Self::StatsGet => STATS_GET,
Self::DumpsAll => DUMPS_ALL,
Self::DumpsCreate => DUMPS_CREATE, Self::DumpsCreate => DUMPS_CREATE,
Self::Version => VERSION, Self::Version => VERSION,
Self::KeysAdd => KEYS_CREATE, Self::KeysAdd => KEYS_CREATE,
@ -108,18 +129,23 @@ pub mod actions {
pub const DOCUMENTS_ADD: u8 = 3; pub const DOCUMENTS_ADD: u8 = 3;
pub const DOCUMENTS_GET: u8 = 4; pub const DOCUMENTS_GET: u8 = 4;
pub const DOCUMENTS_DELETE: u8 = 5; pub const DOCUMENTS_DELETE: u8 = 5;
pub const INDEXES_CREATE: u8 = 6; pub const INDEXES_ALL: u8 = 6;
pub const INDEXES_GET: u8 = 7; pub const INDEXES_CREATE: u8 = 7;
pub const INDEXES_UPDATE: u8 = 8; pub const INDEXES_GET: u8 = 8;
pub const INDEXES_DELETE: u8 = 9; pub const INDEXES_UPDATE: u8 = 9;
pub const TASKS_GET: u8 = 10; pub const INDEXES_DELETE: u8 = 10;
pub const SETTINGS_GET: u8 = 11; pub const TASKS_ALL: u8 = 11;
pub const SETTINGS_UPDATE: u8 = 12; pub const TASKS_GET: u8 = 12;
pub const STATS_GET: u8 = 13; pub const SETTINGS_ALL: u8 = 13;
pub const DUMPS_CREATE: u8 = 14; pub const SETTINGS_GET: u8 = 14;
pub const VERSION: u8 = 15; pub const SETTINGS_UPDATE: u8 = 15;
pub const KEYS_CREATE: u8 = 16; pub const STATS_ALL: u8 = 16;
pub const KEYS_GET: u8 = 17; pub const STATS_GET: u8 = 17;
pub const KEYS_UPDATE: u8 = 18; pub const DUMPS_ALL: u8 = 18;
pub const KEYS_DELETE: u8 = 19; 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;
} }

View File

@ -1,5 +1,6 @@
use std::borrow::Cow; use std::borrow::Cow;
use std::cmp::Reverse; use std::cmp::Reverse;
use std::collections::HashSet;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::convert::TryInto; use std::convert::TryInto;
use std::fs::create_dir_all; use std::fs::create_dir_all;
@ -87,21 +88,48 @@ impl HeedAuthStore {
// create inverted database. // create inverted database.
let db = self.action_keyid_index_expiration; let db = self.action_keyid_index_expiration;
let actions = if key.actions.contains(&Action::All) { let mut actions = HashSet::new();
// if key.actions contains All, we iterate over all actions. for action in &key.actions {
Action::into_enum_iter().collect() match action {
} else if key.actions.contains(&Action::DocumentsAll) { Action::All => actions.extend(Action::into_enum_iter()),
// if key.actions.contains.DocumentsAll add all actions related to documents. Action::DocumentsAll => {
let mut actions = key.actions.clone(); actions.extend(
actions.append(&mut vec![ [
Action::DocumentsAdd, Action::DocumentsGet,
Action::DocumentsGet, Action::DocumentsDelete,
Action::DocumentsDelete, Action::DocumentsAdd,
]); ]
actions .iter(),
} else { );
key.actions.clone() }
}; 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); let no_index_restriction = key.indexes.contains(&StarOr::Star);
for action in actions { for action in actions {

View File

@ -15,37 +15,37 @@ pub static AUTHORIZATIONS: Lazy<HashMap<(&'static str, &'static str), HashSet<&'
("GET", "/indexes/products/documents") => hashset!{"documents.get", "documents.*", "*"}, ("GET", "/indexes/products/documents") => hashset!{"documents.get", "documents.*", "*"},
("GET", "/indexes/products/documents/0") => hashset!{"documents.get", "documents.*", "*"}, ("GET", "/indexes/products/documents/0") => hashset!{"documents.get", "documents.*", "*"},
("DELETE", "/indexes/products/documents/0") => hashset!{"documents.delete", "documents.*", "*"}, ("DELETE", "/indexes/products/documents/0") => hashset!{"documents.delete", "documents.*", "*"},
("GET", "/tasks") => hashset!{"tasks.get", "*"}, ("GET", "/tasks") => hashset!{"tasks.get", "tasks.*", "*"},
("GET", "/tasks?indexUid=products") => hashset!{"tasks.get", "*"}, ("GET", "/tasks?indexUid=products") => hashset!{"tasks.get", "tasks.*", "*"},
("GET", "/tasks/0") => hashset!{"tasks.get", "*"}, ("GET", "/tasks/0") => hashset!{"tasks.get", "tasks.*", "*"},
("PATCH", "/indexes/products/") => hashset!{"indexes.update", "*"}, ("PATCH", "/indexes/products/") => hashset!{"indexes.update", "indexes.*", "*"},
("GET", "/indexes/products/") => hashset!{"indexes.get", "*"}, ("GET", "/indexes/products/") => hashset!{"indexes.get", "indexes.*", "*"},
("DELETE", "/indexes/products/") => hashset!{"indexes.delete", "*"}, ("DELETE", "/indexes/products/") => hashset!{"indexes.delete", "indexes.*", "*"},
("POST", "/indexes") => hashset!{"indexes.create", "*"}, ("POST", "/indexes") => hashset!{"indexes.create", "indexes.*", "*"},
("GET", "/indexes") => hashset!{"indexes.get", "*"}, ("GET", "/indexes") => hashset!{"indexes.get", "indexes.*", "*"},
("GET", "/indexes/products/settings") => hashset!{"settings.get", "*"}, ("GET", "/indexes/products/settings") => hashset!{"settings.get", "settings.*", "*"},
("GET", "/indexes/products/settings/displayed-attributes") => hashset!{"settings.get", "*"}, ("GET", "/indexes/products/settings/displayed-attributes") => hashset!{"settings.get", "settings.*", "*"},
("GET", "/indexes/products/settings/distinct-attribute") => hashset!{"settings.get", "*"}, ("GET", "/indexes/products/settings/distinct-attribute") => hashset!{"settings.get", "settings.*", "*"},
("GET", "/indexes/products/settings/filterable-attributes") => hashset!{"settings.get", "*"}, ("GET", "/indexes/products/settings/filterable-attributes") => hashset!{"settings.get", "settings.*", "*"},
("GET", "/indexes/products/settings/ranking-rules") => hashset!{"settings.get", "*"}, ("GET", "/indexes/products/settings/ranking-rules") => hashset!{"settings.get", "settings.*", "*"},
("GET", "/indexes/products/settings/searchable-attributes") => hashset!{"settings.get", "*"}, ("GET", "/indexes/products/settings/searchable-attributes") => hashset!{"settings.get", "settings.*", "*"},
("GET", "/indexes/products/settings/sortable-attributes") => hashset!{"settings.get", "*"}, ("GET", "/indexes/products/settings/sortable-attributes") => hashset!{"settings.get", "settings.*", "*"},
("GET", "/indexes/products/settings/stop-words") => hashset!{"settings.get", "*"}, ("GET", "/indexes/products/settings/stop-words") => hashset!{"settings.get", "settings.*", "*"},
("GET", "/indexes/products/settings/synonyms") => hashset!{"settings.get", "*"}, ("GET", "/indexes/products/settings/synonyms") => hashset!{"settings.get", "settings.*", "*"},
("DELETE", "/indexes/products/settings") => hashset!{"settings.update", "*"}, ("DELETE", "/indexes/products/settings") => hashset!{"settings.update", "settings.*", "*"},
("PATCH", "/indexes/products/settings") => hashset!{"settings.update", "*"}, ("PATCH", "/indexes/products/settings") => hashset!{"settings.update", "settings.*", "*"},
("PATCH", "/indexes/products/settings/typo-tolerance") => hashset!{"settings.update", "*"}, ("PATCH", "/indexes/products/settings/typo-tolerance") => hashset!{"settings.update", "settings.*", "*"},
("PUT", "/indexes/products/settings/displayed-attributes") => hashset!{"settings.update", "*"}, ("PUT", "/indexes/products/settings/displayed-attributes") => hashset!{"settings.update", "settings.*", "*"},
("PUT", "/indexes/products/settings/distinct-attribute") => hashset!{"settings.update", "*"}, ("PUT", "/indexes/products/settings/distinct-attribute") => hashset!{"settings.update", "settings.*", "*"},
("PUT", "/indexes/products/settings/filterable-attributes") => hashset!{"settings.update", "*"}, ("PUT", "/indexes/products/settings/filterable-attributes") => hashset!{"settings.update", "settings.*", "*"},
("PUT", "/indexes/products/settings/ranking-rules") => hashset!{"settings.update", "*"}, ("PUT", "/indexes/products/settings/ranking-rules") => hashset!{"settings.update", "settings.*", "*"},
("PUT", "/indexes/products/settings/searchable-attributes") => hashset!{"settings.update", "*"}, ("PUT", "/indexes/products/settings/searchable-attributes") => hashset!{"settings.update", "settings.*", "*"},
("PUT", "/indexes/products/settings/sortable-attributes") => hashset!{"settings.update", "*"}, ("PUT", "/indexes/products/settings/sortable-attributes") => hashset!{"settings.update", "settings.*", "*"},
("PUT", "/indexes/products/settings/stop-words") => hashset!{"settings.update", "*"}, ("PUT", "/indexes/products/settings/stop-words") => hashset!{"settings.update", "settings.*", "*"},
("PUT", "/indexes/products/settings/synonyms") => hashset!{"settings.update", "*"}, ("PUT", "/indexes/products/settings/synonyms") => hashset!{"settings.update", "settings.*", "*"},
("GET", "/indexes/products/stats") => hashset!{"stats.get", "*"}, ("GET", "/indexes/products/stats") => hashset!{"stats.get", "stats.*", "*"},
("GET", "/stats") => hashset!{"stats.get", "*"}, ("GET", "/stats") => hashset!{"stats.get", "stats.*", "*"},
("POST", "/dumps") => hashset!{"dumps.create", "*"}, ("POST", "/dumps") => hashset!{"dumps.create", "dumps.*", "*"},
("GET", "/version") => hashset!{"version", "*"}, ("GET", "/version") => hashset!{"version", "*"},
("PATCH", "/keys/mykey/") => hashset!{"keys.update", "*"}, ("PATCH", "/keys/mykey/") => hashset!{"keys.update", "*"},
("GET", "/keys/mykey/") => hashset!{"keys.get", "*"}, ("GET", "/keys/mykey/") => hashset!{"keys.get", "*"},