mirror of
https://github.com/meilisearch/meilisearch.git
synced 2024-11-22 18:17:39 +08:00
Authentication: Directly pass the authfilter to the index scheduler
This commit is contained in:
parent
c8c5944094
commit
42577403d8
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -1904,6 +1904,7 @@ dependencies = [
|
|||||||
"insta",
|
"insta",
|
||||||
"log",
|
"log",
|
||||||
"meili-snap",
|
"meili-snap",
|
||||||
|
"meilisearch-auth",
|
||||||
"meilisearch-types",
|
"meilisearch-types",
|
||||||
"nelson",
|
"nelson",
|
||||||
"page_size 0.5.0",
|
"page_size 0.5.0",
|
||||||
|
@ -19,6 +19,7 @@ dump = { path = "../dump" }
|
|||||||
enum-iterator = "1.1.3"
|
enum-iterator = "1.1.3"
|
||||||
file-store = { path = "../file-store" }
|
file-store = { path = "../file-store" }
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
|
meilisearch-auth = { path = "../meilisearch-auth" }
|
||||||
meilisearch-types = { path = "../meilisearch-types" }
|
meilisearch-types = { path = "../meilisearch-types" }
|
||||||
page_size = "0.5.0"
|
page_size = "0.5.0"
|
||||||
roaring = { version = "0.10.0", features = ["serde"] }
|
roaring = { version = "0.10.0", features = ["serde"] }
|
||||||
|
@ -43,7 +43,6 @@ use file_store::FileStore;
|
|||||||
use meilisearch_types::error::ResponseError;
|
use meilisearch_types::error::ResponseError;
|
||||||
use meilisearch_types::heed::types::{OwnedType, SerdeBincode, SerdeJson, Str};
|
use meilisearch_types::heed::types::{OwnedType, SerdeBincode, SerdeJson, Str};
|
||||||
use meilisearch_types::heed::{self, Database, Env, RoTxn};
|
use meilisearch_types::heed::{self, Database, Env, RoTxn};
|
||||||
use meilisearch_types::index_uid_pattern::IndexUidPattern;
|
|
||||||
use meilisearch_types::milli;
|
use meilisearch_types::milli;
|
||||||
use meilisearch_types::milli::documents::DocumentsBatchBuilder;
|
use meilisearch_types::milli::documents::DocumentsBatchBuilder;
|
||||||
use meilisearch_types::milli::update::IndexerConfig;
|
use meilisearch_types::milli::update::IndexerConfig;
|
||||||
@ -630,13 +629,13 @@ impl IndexScheduler {
|
|||||||
&self,
|
&self,
|
||||||
rtxn: &RoTxn,
|
rtxn: &RoTxn,
|
||||||
query: &Query,
|
query: &Query,
|
||||||
authorized_indexes: &Option<Vec<IndexUidPattern>>,
|
filters: &meilisearch_auth::AuthFilter,
|
||||||
) -> Result<RoaringBitmap> {
|
) -> Result<RoaringBitmap> {
|
||||||
let mut tasks = self.get_task_ids(rtxn, query)?;
|
let mut tasks = self.get_task_ids(rtxn, query)?;
|
||||||
|
|
||||||
// If the query contains a list of index uid or there is a finite list of authorized indexes,
|
// If the query contains a list of index uid or there is a finite list of authorized indexes,
|
||||||
// then we must exclude all the kinds that aren't associated to one and only one index.
|
// then we must exclude all the kinds that aren't associated to one and only one index.
|
||||||
if query.index_uids.is_some() || authorized_indexes.is_some() {
|
if query.index_uids.is_some() || !filters.all_indexes_authorized() {
|
||||||
for kind in enum_iterator::all::<Kind>().filter(|kind| !kind.related_to_one_index()) {
|
for kind in enum_iterator::all::<Kind>().filter(|kind| !kind.related_to_one_index()) {
|
||||||
tasks -= self.get_kind(rtxn, kind)?;
|
tasks -= self.get_kind(rtxn, kind)?;
|
||||||
}
|
}
|
||||||
@ -644,11 +643,11 @@ impl IndexScheduler {
|
|||||||
|
|
||||||
// Any task that is internally associated with a non-authorized index
|
// Any task that is internally associated with a non-authorized index
|
||||||
// must be discarded.
|
// must be discarded.
|
||||||
if let Some(authorized_indexes) = authorized_indexes {
|
if !filters.all_indexes_authorized() {
|
||||||
let all_indexes_iter = self.index_tasks.iter(rtxn)?;
|
let all_indexes_iter = self.index_tasks.iter(rtxn)?;
|
||||||
for result in all_indexes_iter {
|
for result in all_indexes_iter {
|
||||||
let (index, index_tasks) = result?;
|
let (index, index_tasks) = result?;
|
||||||
if !authorized_indexes.iter().any(|p| p.matches_str(index)) {
|
if !filters.is_index_authorized(index) {
|
||||||
tasks -= index_tasks;
|
tasks -= index_tasks;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -668,12 +667,11 @@ impl IndexScheduler {
|
|||||||
pub fn get_tasks_from_authorized_indexes(
|
pub fn get_tasks_from_authorized_indexes(
|
||||||
&self,
|
&self,
|
||||||
query: Query,
|
query: Query,
|
||||||
authorized_indexes: Option<Vec<IndexUidPattern>>,
|
filters: &meilisearch_auth::AuthFilter,
|
||||||
) -> Result<Vec<Task>> {
|
) -> Result<Vec<Task>> {
|
||||||
let rtxn = self.env.read_txn()?;
|
let rtxn = self.env.read_txn()?;
|
||||||
|
|
||||||
let tasks =
|
let tasks = self.get_task_ids_from_authorized_indexes(&rtxn, &query, filters)?;
|
||||||
self.get_task_ids_from_authorized_indexes(&rtxn, &query, &authorized_indexes)?;
|
|
||||||
|
|
||||||
let tasks = self.get_existing_tasks(
|
let tasks = self.get_existing_tasks(
|
||||||
&rtxn,
|
&rtxn,
|
||||||
@ -1120,7 +1118,9 @@ mod tests {
|
|||||||
use crossbeam::channel::RecvTimeoutError;
|
use crossbeam::channel::RecvTimeoutError;
|
||||||
use file_store::File;
|
use file_store::File;
|
||||||
use meili_snap::snapshot;
|
use meili_snap::snapshot;
|
||||||
|
use meilisearch_auth::AuthFilter;
|
||||||
use meilisearch_types::document_formats::DocumentFormatError;
|
use meilisearch_types::document_formats::DocumentFormatError;
|
||||||
|
use meilisearch_types::index_uid_pattern::IndexUidPattern;
|
||||||
use meilisearch_types::milli::obkv_to_json;
|
use meilisearch_types::milli::obkv_to_json;
|
||||||
use meilisearch_types::milli::update::IndexDocumentsMethod::{
|
use meilisearch_types::milli::update::IndexDocumentsMethod::{
|
||||||
ReplaceDocuments, UpdateDocuments,
|
ReplaceDocuments, UpdateDocuments,
|
||||||
@ -2371,38 +2371,45 @@ mod tests {
|
|||||||
|
|
||||||
let rtxn = index_scheduler.env.read_txn().unwrap();
|
let rtxn = index_scheduler.env.read_txn().unwrap();
|
||||||
let query = Query { limit: Some(0), ..Default::default() };
|
let query = Query { limit: Some(0), ..Default::default() };
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[]");
|
snapshot!(snapshot_bitmap(&tasks), @"[]");
|
||||||
|
|
||||||
let query = Query { limit: Some(1), ..Default::default() };
|
let query = Query { limit: Some(1), ..Default::default() };
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[2,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[2,]");
|
||||||
|
|
||||||
let query = Query { limit: Some(2), ..Default::default() };
|
let query = Query { limit: Some(2), ..Default::default() };
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[1,2,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[1,2,]");
|
||||||
|
|
||||||
let query = Query { from: Some(1), ..Default::default() };
|
let query = Query { from: Some(1), ..Default::default() };
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[0,1,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[0,1,]");
|
||||||
|
|
||||||
let query = Query { from: Some(2), ..Default::default() };
|
let query = Query { from: Some(2), ..Default::default() };
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[0,1,2,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[0,1,2,]");
|
||||||
|
|
||||||
let query = Query { from: Some(1), limit: Some(1), ..Default::default() };
|
let query = Query { from: Some(1), limit: Some(1), ..Default::default() };
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[1,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[1,]");
|
||||||
|
|
||||||
let query = Query { from: Some(1), limit: Some(2), ..Default::default() };
|
let query = Query { from: Some(1), limit: Some(2), ..Default::default() };
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[0,1,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[0,1,]");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2427,21 +2434,24 @@ mod tests {
|
|||||||
let rtxn = index_scheduler.env.read_txn().unwrap();
|
let rtxn = index_scheduler.env.read_txn().unwrap();
|
||||||
|
|
||||||
let query = Query { statuses: Some(vec![Status::Processing]), ..Default::default() };
|
let query = Query { statuses: Some(vec![Status::Processing]), ..Default::default() };
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[0,]"); // only the processing tasks in the first tick
|
snapshot!(snapshot_bitmap(&tasks), @"[0,]"); // only the processing tasks in the first tick
|
||||||
|
|
||||||
let query = Query { statuses: Some(vec![Status::Enqueued]), ..Default::default() };
|
let query = Query { statuses: Some(vec![Status::Enqueued]), ..Default::default() };
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[1,2,]"); // only the enqueued tasks in the first tick
|
snapshot!(snapshot_bitmap(&tasks), @"[1,2,]"); // only the enqueued tasks in the first tick
|
||||||
|
|
||||||
let query = Query {
|
let query = Query {
|
||||||
statuses: Some(vec![Status::Enqueued, Status::Processing]),
|
statuses: Some(vec![Status::Enqueued, Status::Processing]),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[0,1,2,]"); // both enqueued and processing tasks in the first tick
|
snapshot!(snapshot_bitmap(&tasks), @"[0,1,2,]"); // both enqueued and processing tasks in the first tick
|
||||||
|
|
||||||
let query = Query {
|
let query = Query {
|
||||||
@ -2449,8 +2459,9 @@ mod tests {
|
|||||||
after_started_at: Some(start_time),
|
after_started_at: Some(start_time),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// both enqueued and processing tasks in the first tick, but limited to those with a started_at
|
// both enqueued and processing tasks in the first tick, but limited to those with a started_at
|
||||||
// that comes after the start of the test, which should excludes the enqueued tasks
|
// that comes after the start of the test, which should excludes the enqueued tasks
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[0,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[0,]");
|
||||||
@ -2460,8 +2471,9 @@ mod tests {
|
|||||||
before_started_at: Some(start_time),
|
before_started_at: Some(start_time),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// both enqueued and processing tasks in the first tick, but limited to those with a started_at
|
// both enqueued and processing tasks in the first tick, but limited to those with a started_at
|
||||||
// that comes before the start of the test, which should excludes all of them
|
// that comes before the start of the test, which should excludes all of them
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[]");
|
snapshot!(snapshot_bitmap(&tasks), @"[]");
|
||||||
@ -2472,8 +2484,9 @@ mod tests {
|
|||||||
before_started_at: Some(start_time + Duration::minutes(1)),
|
before_started_at: Some(start_time + Duration::minutes(1)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// both enqueued and processing tasks in the first tick, but limited to those with a started_at
|
// both enqueued and processing tasks in the first tick, but limited to those with a started_at
|
||||||
// that comes after the start of the test and before one minute after the start of the test,
|
// that comes after the start of the test and before one minute after the start of the test,
|
||||||
// which should exclude the enqueued tasks and include the only processing task
|
// which should exclude the enqueued tasks and include the only processing task
|
||||||
@ -2498,8 +2511,9 @@ mod tests {
|
|||||||
before_started_at: Some(start_time + Duration::minutes(1)),
|
before_started_at: Some(start_time + Duration::minutes(1)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// both succeeded and processing tasks in the first tick, but limited to those with a started_at
|
// both succeeded and processing tasks in the first tick, but limited to those with a started_at
|
||||||
// that comes after the start of the test and before one minute after the start of the test,
|
// that comes after the start of the test and before one minute after the start of the test,
|
||||||
// which should include all tasks
|
// which should include all tasks
|
||||||
@ -2510,8 +2524,9 @@ mod tests {
|
|||||||
before_started_at: Some(start_time),
|
before_started_at: Some(start_time),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// both succeeded and processing tasks in the first tick, but limited to those with a started_at
|
// both succeeded and processing tasks in the first tick, but limited to those with a started_at
|
||||||
// that comes before the start of the test, which should exclude all tasks
|
// that comes before the start of the test, which should exclude all tasks
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[]");
|
snapshot!(snapshot_bitmap(&tasks), @"[]");
|
||||||
@ -2522,8 +2537,9 @@ mod tests {
|
|||||||
before_started_at: Some(second_start_time + Duration::minutes(1)),
|
before_started_at: Some(second_start_time + Duration::minutes(1)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// both succeeded and processing tasks in the first tick, but limited to those with a started_at
|
// both succeeded and processing tasks in the first tick, but limited to those with a started_at
|
||||||
// that comes after the start of the second part of the test and before one minute after the
|
// that comes after the start of the second part of the test and before one minute after the
|
||||||
// second start of the test, which should exclude all tasks
|
// second start of the test, which should exclude all tasks
|
||||||
@ -2541,8 +2557,9 @@ mod tests {
|
|||||||
|
|
||||||
let rtxn = index_scheduler.env.read_txn().unwrap();
|
let rtxn = index_scheduler.env.read_txn().unwrap();
|
||||||
|
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// we run the same query to verify that, and indeed find that the last task is matched
|
// we run the same query to verify that, and indeed find that the last task is matched
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[2,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[2,]");
|
||||||
|
|
||||||
@ -2552,8 +2569,9 @@ mod tests {
|
|||||||
before_started_at: Some(second_start_time + Duration::minutes(1)),
|
before_started_at: Some(second_start_time + Duration::minutes(1)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// enqueued, succeeded, or processing tasks started after the second part of the test, should
|
// enqueued, succeeded, or processing tasks started after the second part of the test, should
|
||||||
// again only return the last task
|
// again only return the last task
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[2,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[2,]");
|
||||||
@ -2563,8 +2581,9 @@ mod tests {
|
|||||||
|
|
||||||
// now the last task should have failed
|
// now the last task should have failed
|
||||||
snapshot!(snapshot_index_scheduler(&index_scheduler), name: "end");
|
snapshot!(snapshot_index_scheduler(&index_scheduler), name: "end");
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// so running the last query should return nothing
|
// so running the last query should return nothing
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[]");
|
snapshot!(snapshot_bitmap(&tasks), @"[]");
|
||||||
|
|
||||||
@ -2574,8 +2593,9 @@ mod tests {
|
|||||||
before_started_at: Some(second_start_time + Duration::minutes(1)),
|
before_started_at: Some(second_start_time + Duration::minutes(1)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// but the same query on failed tasks should return the last task
|
// but the same query on failed tasks should return the last task
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[2,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[2,]");
|
||||||
|
|
||||||
@ -2585,8 +2605,9 @@ mod tests {
|
|||||||
before_started_at: Some(second_start_time + Duration::minutes(1)),
|
before_started_at: Some(second_start_time + Duration::minutes(1)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// but the same query on failed tasks should return the last task
|
// but the same query on failed tasks should return the last task
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[2,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[2,]");
|
||||||
|
|
||||||
@ -2597,8 +2618,9 @@ mod tests {
|
|||||||
before_started_at: Some(second_start_time + Duration::minutes(1)),
|
before_started_at: Some(second_start_time + Duration::minutes(1)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// same query but with an invalid uid
|
// same query but with an invalid uid
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[]");
|
snapshot!(snapshot_bitmap(&tasks), @"[]");
|
||||||
|
|
||||||
@ -2609,8 +2631,9 @@ mod tests {
|
|||||||
before_started_at: Some(second_start_time + Duration::minutes(1)),
|
before_started_at: Some(second_start_time + Duration::minutes(1)),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// same query but with a valid uid
|
// same query but with a valid uid
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[2,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[2,]");
|
||||||
}
|
}
|
||||||
@ -2640,8 +2663,9 @@ mod tests {
|
|||||||
let rtxn = index_scheduler.env.read_txn().unwrap();
|
let rtxn = index_scheduler.env.read_txn().unwrap();
|
||||||
|
|
||||||
let query = Query { index_uids: Some(vec!["catto".to_owned()]), ..Default::default() };
|
let query = Query { index_uids: Some(vec!["catto".to_owned()]), ..Default::default() };
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// only the first task associated with catto is returned, the indexSwap tasks are excluded!
|
// only the first task associated with catto is returned, the indexSwap tasks are excluded!
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[0,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[0,]");
|
||||||
|
|
||||||
@ -2650,7 +2674,9 @@ mod tests {
|
|||||||
.get_task_ids_from_authorized_indexes(
|
.get_task_ids_from_authorized_indexes(
|
||||||
&rtxn,
|
&rtxn,
|
||||||
&query,
|
&query,
|
||||||
&Some(vec![IndexUidPattern::new_unchecked("doggo")]),
|
&AuthFilter::with_allowed_indexes(
|
||||||
|
vec![IndexUidPattern::new_unchecked("doggo")].into_iter().collect(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// we have asked for only the tasks associated with catto, but are only authorized to retrieve the tasks
|
// we have asked for only the tasks associated with catto, but are only authorized to retrieve the tasks
|
||||||
@ -2662,7 +2688,9 @@ mod tests {
|
|||||||
.get_task_ids_from_authorized_indexes(
|
.get_task_ids_from_authorized_indexes(
|
||||||
&rtxn,
|
&rtxn,
|
||||||
&query,
|
&query,
|
||||||
&Some(vec![IndexUidPattern::new_unchecked("doggo")]),
|
&AuthFilter::with_allowed_indexes(
|
||||||
|
vec![IndexUidPattern::new_unchecked("doggo")].into_iter().collect(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// we asked for all the tasks, but we are only authorized to retrieve the doggo tasks
|
// we asked for all the tasks, but we are only authorized to retrieve the doggo tasks
|
||||||
@ -2674,10 +2702,14 @@ mod tests {
|
|||||||
.get_task_ids_from_authorized_indexes(
|
.get_task_ids_from_authorized_indexes(
|
||||||
&rtxn,
|
&rtxn,
|
||||||
&query,
|
&query,
|
||||||
&Some(vec![
|
&AuthFilter::with_allowed_indexes(
|
||||||
|
vec![
|
||||||
IndexUidPattern::new_unchecked("catto"),
|
IndexUidPattern::new_unchecked("catto"),
|
||||||
IndexUidPattern::new_unchecked("doggo"),
|
IndexUidPattern::new_unchecked("doggo"),
|
||||||
]),
|
]
|
||||||
|
.into_iter()
|
||||||
|
.collect(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// we asked for all the tasks, but we are only authorized to retrieve the doggo and catto tasks
|
// we asked for all the tasks, but we are only authorized to retrieve the doggo and catto tasks
|
||||||
@ -2685,8 +2717,9 @@ mod tests {
|
|||||||
snapshot!(snapshot_bitmap(&tasks), @"[0,1,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[0,1,]");
|
||||||
|
|
||||||
let query = Query::default();
|
let query = Query::default();
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// we asked for all the tasks with all index authorized -> all tasks returned
|
// we asked for all the tasks with all index authorized -> all tasks returned
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[0,1,2,3,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[0,1,2,3,]");
|
||||||
}
|
}
|
||||||
@ -2717,8 +2750,9 @@ mod tests {
|
|||||||
|
|
||||||
let rtxn = index_scheduler.read_txn().unwrap();
|
let rtxn = index_scheduler.read_txn().unwrap();
|
||||||
let query = Query { canceled_by: Some(vec![task_cancelation.uid]), ..Query::default() };
|
let query = Query { canceled_by: Some(vec![task_cancelation.uid]), ..Query::default() };
|
||||||
let tasks =
|
let tasks = index_scheduler
|
||||||
index_scheduler.get_task_ids_from_authorized_indexes(&rtxn, &query, &None).unwrap();
|
.get_task_ids_from_authorized_indexes(&rtxn, &query, &AuthFilter::default())
|
||||||
|
.unwrap();
|
||||||
// 0 is not returned because it was not canceled, 3 is not returned because it is the uid of the
|
// 0 is not returned because it was not canceled, 3 is not returned because it is the uid of the
|
||||||
// taskCancelation itself
|
// taskCancelation itself
|
||||||
snapshot!(snapshot_bitmap(&tasks), @"[1,2,]");
|
snapshot!(snapshot_bitmap(&tasks), @"[1,2,]");
|
||||||
@ -2728,7 +2762,9 @@ mod tests {
|
|||||||
.get_task_ids_from_authorized_indexes(
|
.get_task_ids_from_authorized_indexes(
|
||||||
&rtxn,
|
&rtxn,
|
||||||
&query,
|
&query,
|
||||||
&Some(vec![IndexUidPattern::new_unchecked("doggo")]),
|
&AuthFilter::with_allowed_indexes(
|
||||||
|
vec![IndexUidPattern::new_unchecked("doggo")].into_iter().collect(),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
// Return only 1 because the user is not authorized to see task 2
|
// Return only 1 because the user is not authorized to see task 2
|
||||||
|
@ -178,6 +178,19 @@ impl Default for AuthFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AuthFilter {
|
impl AuthFilter {
|
||||||
|
pub fn with_allowed_indexes(allowed_indexes: HashSet<IndexUidPattern>) -> Self {
|
||||||
|
Self {
|
||||||
|
search_rules: SearchRules::Set(allowed_indexes.clone()),
|
||||||
|
key_authorized_indexes: SearchRules::Set(allowed_indexes),
|
||||||
|
allow_index_creation: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn all_indexes_authorized(&self) -> bool {
|
||||||
|
self.key_authorized_indexes.all_indexes_authorized()
|
||||||
|
&& self.search_rules.all_indexes_authorized()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_index_authorized(&self, index: &str) -> bool {
|
pub fn is_index_authorized(&self, index: &str) -> bool {
|
||||||
self.key_authorized_indexes.is_index_authorized(index)
|
self.key_authorized_indexes.is_index_authorized(index)
|
||||||
&& self.search_rules.is_index_authorized(index)
|
&& self.search_rules.is_index_authorized(index)
|
||||||
@ -189,16 +202,6 @@ impl AuthFilter {
|
|||||||
}
|
}
|
||||||
self.search_rules.get_index_search_rules(index)
|
self.search_rules.get_index_search_rules(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the list of indexes such that `self.is_index_authorized(index) == true`,
|
|
||||||
/// or `None` if all indexes satisfy this condition.
|
|
||||||
///
|
|
||||||
/// FIXME: this works only when there are no tenant tokens, otherwise it ignores the rules of the API key.
|
|
||||||
///
|
|
||||||
/// It is better to use `is_index_authorized` when possible.
|
|
||||||
pub fn authorized_indexes(&self) -> Option<Vec<IndexUidPattern>> {
|
|
||||||
self.search_rules.authorized_indexes()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transparent wrapper around a list of allowed indexes with the search rules to apply for each.
|
/// Transparent wrapper around a list of allowed indexes with the search rules to apply for each.
|
||||||
@ -250,24 +253,10 @@ impl SearchRules {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the list of indexes such that `self.is_index_authorized(index) == true`,
|
fn all_indexes_authorized(&self) -> bool {
|
||||||
/// or `None` if all indexes satisfy this condition.
|
|
||||||
fn authorized_indexes(&self) -> Option<Vec<IndexUidPattern>> {
|
|
||||||
match self {
|
match self {
|
||||||
SearchRules::Set(set) => {
|
SearchRules::Set(set) => set.contains("*"),
|
||||||
if set.contains("*") {
|
SearchRules::Map(map) => map.contains_key("*"),
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(set.iter().cloned().collect())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
SearchRules::Map(map) => {
|
|
||||||
if map.contains_key("*") {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(map.keys().cloned().collect())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -255,7 +255,7 @@ pub fn create_all_stats(
|
|||||||
let mut database_size = 0;
|
let mut database_size = 0;
|
||||||
let processing_task = index_scheduler.get_tasks_from_authorized_indexes(
|
let processing_task = index_scheduler.get_tasks_from_authorized_indexes(
|
||||||
Query { statuses: Some(vec![Status::Processing]), limit: Some(1), ..Query::default() },
|
Query { statuses: Some(vec![Status::Processing]), limit: Some(1), ..Query::default() },
|
||||||
filters.authorized_indexes(),
|
filters,
|
||||||
)?;
|
)?;
|
||||||
// accumulate the size of each indexes
|
// accumulate the size of each indexes
|
||||||
let processing_index = processing_task.first().and_then(|task| task.index_uid());
|
let processing_index = processing_task.first().and_then(|task| task.index_uid());
|
||||||
|
@ -319,7 +319,7 @@ async fn cancel_tasks(
|
|||||||
let tasks = index_scheduler.get_task_ids_from_authorized_indexes(
|
let tasks = index_scheduler.get_task_ids_from_authorized_indexes(
|
||||||
&index_scheduler.read_txn()?,
|
&index_scheduler.read_txn()?,
|
||||||
&query,
|
&query,
|
||||||
&index_scheduler.filters().authorized_indexes(),
|
index_scheduler.filters(),
|
||||||
)?;
|
)?;
|
||||||
let task_cancelation =
|
let task_cancelation =
|
||||||
KindWithContent::TaskCancelation { query: format!("?{}", req.query_string()), tasks };
|
KindWithContent::TaskCancelation { query: format!("?{}", req.query_string()), tasks };
|
||||||
@ -364,7 +364,7 @@ async fn delete_tasks(
|
|||||||
let tasks = index_scheduler.get_task_ids_from_authorized_indexes(
|
let tasks = index_scheduler.get_task_ids_from_authorized_indexes(
|
||||||
&index_scheduler.read_txn()?,
|
&index_scheduler.read_txn()?,
|
||||||
&query,
|
&query,
|
||||||
&index_scheduler.filters().authorized_indexes(),
|
index_scheduler.filters(),
|
||||||
)?;
|
)?;
|
||||||
let task_deletion =
|
let task_deletion =
|
||||||
KindWithContent::TaskDeletion { query: format!("?{}", req.query_string()), tasks };
|
KindWithContent::TaskDeletion { query: format!("?{}", req.query_string()), tasks };
|
||||||
@ -398,7 +398,7 @@ async fn get_tasks(
|
|||||||
let query = params.into_query();
|
let query = params.into_query();
|
||||||
|
|
||||||
let mut tasks_results: Vec<TaskView> = index_scheduler
|
let mut tasks_results: Vec<TaskView> = index_scheduler
|
||||||
.get_tasks_from_authorized_indexes(query, index_scheduler.filters().authorized_indexes())?
|
.get_tasks_from_authorized_indexes(query, index_scheduler.filters())?
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|t| TaskView::from_task(&t))
|
.map(|t| TaskView::from_task(&t))
|
||||||
.collect();
|
.collect();
|
||||||
@ -436,9 +436,8 @@ async fn get_task(
|
|||||||
|
|
||||||
let query = index_scheduler::Query { uids: Some(vec![task_uid]), ..Query::default() };
|
let query = index_scheduler::Query { uids: Some(vec![task_uid]), ..Query::default() };
|
||||||
|
|
||||||
if let Some(task) = index_scheduler
|
if let Some(task) =
|
||||||
.get_tasks_from_authorized_indexes(query, index_scheduler.filters().authorized_indexes())?
|
index_scheduler.get_tasks_from_authorized_indexes(query, index_scheduler.filters())?.first()
|
||||||
.first()
|
|
||||||
{
|
{
|
||||||
let task_view = TaskView::from_task(task);
|
let task_view = TaskView::from_task(task);
|
||||||
Ok(HttpResponse::Ok().json(task_view))
|
Ok(HttpResponse::Ok().json(task_view))
|
||||||
|
Loading…
Reference in New Issue
Block a user