mirror of
https://github.com/meilisearch/MeiliSearch
synced 2025-07-04 04:17:10 +02:00
Making it work with index uid patterns
This commit is contained in:
parent
ec7de4bae7
commit
d563ed8a39
6 changed files with 53 additions and 48 deletions
|
@ -7,6 +7,7 @@ edition = "2021"
|
|||
base64 = "0.13.1"
|
||||
enum-iterator = "1.1.3"
|
||||
hmac = "0.12.1"
|
||||
maplit = "1.0.2"
|
||||
meilisearch-types = { path = "../meilisearch-types" }
|
||||
rand = "0.8.5"
|
||||
roaring = { version = "0.10.0", features = ["serde"] }
|
||||
|
|
|
@ -8,6 +8,7 @@ use std::path::Path;
|
|||
use std::sync::Arc;
|
||||
|
||||
use error::{AuthControllerError, Result};
|
||||
use maplit::hashset;
|
||||
use meilisearch_types::index_uid_pattern::IndexUidPattern;
|
||||
use meilisearch_types::keys::{Action, CreateApiKey, Key, PatchApiKey};
|
||||
use meilisearch_types::star_or::StarOr;
|
||||
|
@ -75,31 +76,12 @@ impl AuthController {
|
|||
search_rules: Option<SearchRules>,
|
||||
) -> Result<AuthFilter> {
|
||||
let mut filters = AuthFilter::default();
|
||||
let key = self
|
||||
.store
|
||||
.get_api_key(uid)?
|
||||
.ok_or_else(|| AuthControllerError::ApiKeyNotFound(uid.to_string()))?;
|
||||
let key = self.get_key(uid)?;
|
||||
|
||||
if !key.indexes.iter().any(|i| i == &StarOr::Star) {
|
||||
filters.search_rules = match search_rules {
|
||||
// Intersect search_rules with parent key authorized indexes.
|
||||
Some(search_rules) => SearchRules::Map(
|
||||
key.indexes
|
||||
.into_iter()
|
||||
.filter_map(|index| {
|
||||
search_rules.get_index_search_rules(index.deref()).map(
|
||||
|index_search_rules| {
|
||||
(String::from(index), Some(index_search_rules))
|
||||
},
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
None => SearchRules::Set(key.indexes.into_iter().map(String::from).collect()),
|
||||
};
|
||||
} else if let Some(search_rules) = search_rules {
|
||||
filters.search_rules = search_rules;
|
||||
}
|
||||
filters.search_rules = match search_rules {
|
||||
Some(search_rules) => search_rules,
|
||||
None => SearchRules::Set(key.indexes.into_iter().collect()),
|
||||
};
|
||||
|
||||
filters.allow_index_creation = self.is_key_authorized(uid, Action::IndexesAdd, None)?;
|
||||
|
||||
|
@ -182,13 +164,13 @@ impl Default for AuthFilter {
|
|||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
#[serde(untagged)]
|
||||
pub enum SearchRules {
|
||||
Set(HashSet<String>),
|
||||
Map(HashMap<String, Option<IndexSearchRules>>),
|
||||
Set(HashSet<IndexUidPattern>),
|
||||
Map(HashMap<IndexUidPattern, Option<IndexSearchRules>>),
|
||||
}
|
||||
|
||||
impl Default for SearchRules {
|
||||
fn default() -> Self {
|
||||
Self::Set(Some("*".to_string()).into_iter().collect())
|
||||
Self::Set(hashset! { IndexUidPattern::all() })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,16 +180,12 @@ impl SearchRules {
|
|||
Self::Set(set) => {
|
||||
set.contains("*")
|
||||
|| set.contains(index)
|
||||
|| set
|
||||
.iter() // We must store the IndexUidPattern in the Set
|
||||
.any(|pattern| IndexUidPattern::new_unchecked(pattern).matches_str(index))
|
||||
|| set.iter().any(|pattern| pattern.matches_str(index))
|
||||
}
|
||||
Self::Map(map) => {
|
||||
map.contains_key("*")
|
||||
|| map.contains_key(index)
|
||||
|| map
|
||||
.keys() // We must store the IndexUidPattern in the Map
|
||||
.any(|pattern| IndexUidPattern::new_unchecked(pattern).matches_str(index))
|
||||
|| map.keys().any(|pattern| pattern.matches_str(index))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -215,21 +193,26 @@ impl SearchRules {
|
|||
pub fn get_index_search_rules(&self, index: &str) -> Option<IndexSearchRules> {
|
||||
match self {
|
||||
Self::Set(set) => {
|
||||
if set.contains("*") || set.contains(index) {
|
||||
if self.is_index_authorized(index) {
|
||||
Some(IndexSearchRules::default())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
Self::Map(map) => {
|
||||
map.get(index).or_else(|| map.get("*")).map(|isr| isr.clone().unwrap_or_default())
|
||||
// We must take the most retrictive rule of this index uid patterns set of rules.
|
||||
map.iter()
|
||||
.filter(|(pattern, _)| pattern.matches_str(index))
|
||||
.max_by_key(|(pattern, _)| (pattern.is_exact(), pattern.len()))
|
||||
.map(|(_, rule)| rule.clone())
|
||||
.flatten()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the list of indexes such that `self.is_index_authorized(index) == true`,
|
||||
/// or `None` if all indexes satisfy this condition.
|
||||
pub fn authorized_indexes(&self) -> Option<Vec<String>> {
|
||||
pub fn authorized_indexes(&self) -> Option<Vec<IndexUidPattern>> {
|
||||
match self {
|
||||
SearchRules::Set(set) => {
|
||||
if set.contains("*") {
|
||||
|
@ -250,7 +233,7 @@ impl SearchRules {
|
|||
}
|
||||
|
||||
impl IntoIterator for SearchRules {
|
||||
type Item = (String, IndexSearchRules);
|
||||
type Item = (IndexUidPattern, IndexSearchRules);
|
||||
type IntoIter = Box<dyn Iterator<Item = Self::Item>>;
|
||||
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue