diff --git a/meilisearch-http/src/routes/dump.rs b/meilisearch-http/src/routes/dump.rs index 18b143fa3..72bc55986 100644 --- a/meilisearch-http/src/routes/dump.rs +++ b/meilisearch-http/src/routes/dump.rs @@ -11,7 +11,7 @@ pub fn configure(cfg: &mut web::ServiceConfig) { .service(web::resource("/{dump_uid}/status").route(web::get().to(get_dump_status))); } -async fn create_dump(data: GuardedData) -> Result { +pub async fn create_dump(data: GuardedData) -> Result { let res = data.create_dump().await?; debug!("returns: {:?}", res); diff --git a/meilisearch-http/src/routes/indexes/documents.rs b/meilisearch-http/src/routes/indexes/documents.rs index a62a85f1b..a4bf465b5 100644 --- a/meilisearch-http/src/routes/indexes/documents.rs +++ b/meilisearch-http/src/routes/indexes/documents.rs @@ -49,7 +49,7 @@ fn guard_json(head: &actix_web::dev::RequestHead) -> bool { } #[derive(Deserialize)] -struct DocumentParam { +pub struct DocumentParam { index_uid: String, document_id: String, } @@ -71,7 +71,7 @@ pub fn configure(cfg: &mut web::ServiceConfig) { ); } -async fn get_document( +pub async fn get_document( data: GuardedData, path: web::Path, ) -> Result { @@ -84,7 +84,7 @@ async fn get_document( Ok(HttpResponse::Ok().json(document)) } -async fn delete_document( +pub async fn delete_document( data: GuardedData, path: web::Path, ) -> Result { @@ -97,13 +97,13 @@ async fn delete_document( #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase", deny_unknown_fields)] -struct BrowseQuery { +pub struct BrowseQuery { offset: Option, limit: Option, attributes_to_retrieve: Option, } -async fn get_all_documents( +pub async fn get_all_documents( data: GuardedData, path: web::Path, params: web::Query, @@ -134,13 +134,13 @@ async fn get_all_documents( #[derive(Deserialize, Debug)] #[serde(rename_all = "camelCase", deny_unknown_fields)] -struct UpdateDocumentsQuery { +pub struct UpdateDocumentsQuery { primary_key: Option, } /// Route used when the payload type is "application/json" /// Used to add or replace documents -async fn add_documents( +pub async fn add_documents( data: GuardedData, path: web::Path, params: web::Query, @@ -163,7 +163,7 @@ async fn add_documents( /// Route used when the payload type is "application/json" /// Used to add or replace documents -async fn update_documents( +pub async fn update_documents( data: GuardedData, path: web::Path, params: web::Query, @@ -184,7 +184,7 @@ async fn update_documents( Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update.id() }))) } -async fn delete_documents( +pub async fn delete_documents( data: GuardedData, path: web::Path, body: web::Json>, @@ -204,7 +204,7 @@ async fn delete_documents( Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update_status.id() }))) } -async fn clear_all_documents( +pub async fn clear_all_documents( data: GuardedData, path: web::Path, ) -> Result { diff --git a/meilisearch-http/src/routes/indexes/mod.rs b/meilisearch-http/src/routes/indexes/mod.rs index 260d97ecd..8314bf032 100644 --- a/meilisearch-http/src/routes/indexes/mod.rs +++ b/meilisearch-http/src/routes/indexes/mod.rs @@ -8,10 +8,10 @@ use crate::extractors::authentication::{policies::*, GuardedData}; use crate::routes::IndexParam; use crate::Data; -mod documents; -mod search; -mod settings; -mod updates; +pub mod documents; +pub mod search; +pub mod settings; +pub mod updates; pub fn configure(cfg: &mut web::ServiceConfig) { cfg.service( @@ -35,7 +35,7 @@ pub fn configure(cfg: &mut web::ServiceConfig) { ); } -async fn list_indexes(data: GuardedData) -> Result { +pub async fn list_indexes(data: GuardedData) -> Result { let indexes = data.list_indexes().await?; debug!("returns: {:?}", indexes); Ok(HttpResponse::Ok().json(indexes)) @@ -43,12 +43,12 @@ async fn list_indexes(data: GuardedData) -> Result, } -async fn create_index( +pub async fn create_index( data: GuardedData, body: web::Json, ) -> Result { @@ -59,7 +59,7 @@ async fn create_index( #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] -struct UpdateIndexRequest { +pub struct UpdateIndexRequest { uid: Option, primary_key: Option, } @@ -74,7 +74,7 @@ pub struct UpdateIndexResponse { primary_key: Option, } -async fn get_index( +pub async fn get_index( data: GuardedData, path: web::Path, ) -> Result { @@ -83,7 +83,7 @@ async fn get_index( Ok(HttpResponse::Ok().json(meta)) } -async fn update_index( +pub async fn update_index( data: GuardedData, path: web::Path, body: web::Json, @@ -97,7 +97,7 @@ async fn update_index( Ok(HttpResponse::Ok().json(meta)) } -async fn delete_index( +pub async fn delete_index( data: GuardedData, path: web::Path, ) -> Result { @@ -105,7 +105,7 @@ async fn delete_index( Ok(HttpResponse::NoContent().finish()) } -async fn get_index_stats( +pub async fn get_index_stats( data: GuardedData, path: web::Path, ) -> Result { diff --git a/meilisearch-http/src/routes/indexes/search.rs b/meilisearch-http/src/routes/indexes/search.rs index c296b2f6a..8a2f4ae1d 100644 --- a/meilisearch-http/src/routes/indexes/search.rs +++ b/meilisearch-http/src/routes/indexes/search.rs @@ -77,7 +77,7 @@ impl From for SearchQuery { } } -async fn search_with_url_query( +pub async fn search_with_url_query( data: GuardedData, path: web::Path, params: web::Query, @@ -94,7 +94,7 @@ async fn search_with_url_query( Ok(HttpResponse::Ok().json(search_result)) } -async fn search_with_post( +pub async fn search_with_post( data: GuardedData, path: web::Path, params: web::Json, diff --git a/meilisearch-http/src/routes/indexes/settings.rs b/meilisearch-http/src/routes/indexes/settings.rs index 272060bf5..47f18a68a 100644 --- a/meilisearch-http/src/routes/indexes/settings.rs +++ b/meilisearch-http/src/routes/indexes/settings.rs @@ -9,7 +9,7 @@ use crate::{error::ResponseError, index::Unchecked}; #[macro_export] macro_rules! make_setting_route { ($route:literal, $type:ty, $attr:ident, $camelcase_attr:literal) => { - mod $attr { + pub mod $attr { use log::debug; use actix_web::{web, HttpResponse, Resource}; @@ -18,7 +18,7 @@ macro_rules! make_setting_route { use crate::index::Settings; use crate::extractors::authentication::{GuardedData, policies::*}; - async fn delete( + pub async fn delete( data: GuardedData, index_uid: web::Path, ) -> Result { @@ -32,7 +32,7 @@ macro_rules! make_setting_route { Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update_status.id() }))) } - async fn update( + pub async fn update( data: GuardedData, index_uid: actix_web::web::Path, body: actix_web::web::Json>, @@ -47,7 +47,7 @@ macro_rules! make_setting_route { Ok(HttpResponse::Accepted().json(serde_json::json!({ "updateId": update_status.id() }))) } - async fn get( + pub async fn get( data: GuardedData, index_uid: actix_web::web::Path, ) -> std::result::Result { @@ -135,7 +135,7 @@ generate_configure!( ranking_rules ); -async fn update_all( +pub async fn update_all( data: GuardedData, index_uid: web::Path, body: web::Json>, @@ -149,7 +149,7 @@ async fn update_all( Ok(HttpResponse::Accepted().json(json)) } -async fn get_all( +pub async fn get_all( data: GuardedData, index_uid: web::Path, ) -> Result { @@ -158,7 +158,7 @@ async fn get_all( Ok(HttpResponse::Ok().json(settings)) } -async fn delete_all( +pub async fn delete_all( data: GuardedData, index_uid: web::Path, ) -> Result { diff --git a/meilisearch-http/src/routes/indexes/updates.rs b/meilisearch-http/src/routes/indexes/updates.rs index 735736e97..471636abf 100644 --- a/meilisearch-http/src/routes/indexes/updates.rs +++ b/meilisearch-http/src/routes/indexes/updates.rs @@ -31,12 +31,12 @@ pub struct UpdateIndexResponse { } #[derive(Deserialize)] -struct UpdateParam { +pub struct UpdateParam { index_uid: String, update_id: u64, } -async fn get_update_status( +pub async fn get_update_status( data: GuardedData, path: web::Path, ) -> Result { @@ -49,7 +49,7 @@ async fn get_update_status( Ok(HttpResponse::Ok().json(meta)) } -async fn get_all_updates_status( +pub async fn get_all_updates_status( data: GuardedData, path: web::Path, ) -> Result { diff --git a/meilisearch-http/src/routes/mod.rs b/meilisearch-http/src/routes/mod.rs index 981d27e02..fd30cd519 100644 --- a/meilisearch-http/src/routes/mod.rs +++ b/meilisearch-http/src/routes/mod.rs @@ -278,3 +278,97 @@ pub async fn list_keys(data: GuardedData) -> HttpResponse { pub async fn get_health() -> Result { Ok(HttpResponse::Ok().json(serde_json::json!({ "status": "available" }))) } + +#[cfg(test)] +mod test { + use super::*; + use crate::data::Data; + use crate::extractors::authentication::GuardedData; + + /// A type implemented for a route that uses a authentication policy `Policy`. + /// + /// This trait is used for regression testing of route authenticaton policies. + trait Is {} + + macro_rules! impl_is_policy { + ($($param:ident)*) => { + impl Is for Func + where Func: Fn(GuardedData, $($param,)*) -> Res {} + + }; + } + + impl_is_policy! {} + impl_is_policy! {A} + impl_is_policy! {A B} + impl_is_policy! {A B C} + impl_is_policy! {A B C D} + + /// Emits a compile error if a route doesn't have the correct authentication policy. + /// + /// This works by trying to cast the route function into a Is type, where Policy it + /// the authentication policy defined for the route. + macro_rules! test_auth_routes { + ($($policy:ident => { $($route:expr,)*})*) => { + #[test] + fn test_auth() { + $($(let _: &dyn Is<$policy, _> = &$route;)*)* + } + }; + } + + test_auth_routes! { + Public => { + indexes::search::search_with_url_query, + indexes::search::search_with_post, + + indexes::documents::get_document, + indexes::documents::get_all_documents, + } + Private => { + get_stats, + get_version, + + indexes::create_index, + indexes::list_indexes, + indexes::get_index_stats, + indexes::delete_index, + indexes::update_index, + indexes::get_index, + + dump::create_dump, + + indexes::settings::filterable_attributes::get, + indexes::settings::displayed_attributes::get, + indexes::settings::searchable_attributes::get, + indexes::settings::stop_words::get, + indexes::settings::synonyms::get, + indexes::settings::distinct_attribute::get, + indexes::settings::filterable_attributes::update, + indexes::settings::displayed_attributes::update, + indexes::settings::searchable_attributes::update, + indexes::settings::stop_words::update, + indexes::settings::synonyms::update, + indexes::settings::distinct_attribute::update, + indexes::settings::filterable_attributes::delete, + indexes::settings::displayed_attributes::delete, + indexes::settings::searchable_attributes::delete, + indexes::settings::stop_words::delete, + indexes::settings::synonyms::delete, + indexes::settings::distinct_attribute::delete, + indexes::settings::delete_all, + indexes::settings::get_all, + indexes::settings::update_all, + + indexes::documents::clear_all_documents, + indexes::documents::delete_documents, + indexes::documents::update_documents, + indexes::documents::add_documents, + indexes::documents::delete_document, + + indexes::updates::get_all_updates_status, + indexes::updates::get_update_status, + } + Admin => { list_keys, } + } +}