5231: Improve openapi r=dureuill a=irevoire

# Pull Request

## Related issue
Fixes https://github.com/meilisearch/open-api/issues/17
Fixes https://github.com/meilisearch/open-api/issues/13
Fixes https://github.com/meilisearch/open-api/issues/14
Fixes https://github.com/meilisearch/open-api/issues/16


Co-authored-by: Tamo <tamo@meilisearch.com>
This commit is contained in:
meili-bors[bot] 2025-01-13 13:04:09 +00:00 committed by GitHub
commit b0ef7701ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 36 additions and 28 deletions

View File

@ -54,7 +54,7 @@ pub fn configure(cfg: &mut web::ServiceConfig) {
/// Create an API Key. /// Create an API Key.
#[utoipa::path( #[utoipa::path(
post, post,
path = "/", path = "",
tag = "Keys", tag = "Keys",
security(("Bearer" = ["keys.create", "keys.*", "*"])), security(("Bearer" = ["keys.create", "keys.*", "*"])),
request_body = CreateApiKey, request_body = CreateApiKey,
@ -133,7 +133,7 @@ impl ListApiKeys {
/// List all API Keys /// List all API Keys
#[utoipa::path( #[utoipa::path(
get, get,
path = "/", path = "",
tag = "Keys", tag = "Keys",
security(("Bearer" = ["keys.get", "keys.*", "*"])), security(("Bearer" = ["keys.get", "keys.*", "*"])),
params(ListApiKeys), params(ListApiKeys),

View File

@ -121,7 +121,7 @@ pub struct AllBatches {
/// Batch results are paginated and can be filtered with query parameters. /// Batch results are paginated and can be filtered with query parameters.
#[utoipa::path( #[utoipa::path(
get, get,
path = "/", path = "",
tag = "Batches", tag = "Batches",
security(("Bearer" = ["tasks.get", "tasks.*", "*"])), security(("Bearer" = ["tasks.get", "tasks.*", "*"])),
params(TasksFilterQuery), params(TasksFilterQuery),

View File

@ -45,7 +45,7 @@ crate::empty_analytics!(DumpAnalytics, "Dump Created");
/// If the dump directory does not exist yet, it will be created. /// If the dump directory does not exist yet, it will be created.
#[utoipa::path( #[utoipa::path(
post, post,
path = "/", path = "",
tag = "Dumps", tag = "Dumps",
security(("Bearer" = ["dumps.create", "dumps.*", "*"])), security(("Bearer" = ["dumps.create", "dumps.*", "*"])),
responses( responses(

View File

@ -40,18 +40,18 @@ pub fn configure(cfg: &mut web::ServiceConfig) {
/// ///
/// Get a list of all experimental features that can be activated via the /experimental-features route and whether or not they are currently activated. /// Get a list of all experimental features that can be activated via the /experimental-features route and whether or not they are currently activated.
#[utoipa::path( #[utoipa::path(
post, get,
path = "/", path = "",
tag = "Experimental features", tag = "Experimental features",
security(("Bearer" = ["experimental_features.get", "experimental_features.*", "*"])), security(("Bearer" = ["experimental_features.get", "experimental_features.*", "*"])),
responses( responses(
(status = OK, description = "Experimental features are returned", body = RuntimeTogglableFeatures, content_type = "application/json", example = json!( (status = OK, description = "Experimental features are returned", body = RuntimeTogglableFeatures, content_type = "application/json", example = json!(RuntimeTogglableFeatures {
{ vector_store: Some(true),
"metrics": false, metrics: Some(true),
"logsRoute": true, logs_route: Some(false),
"vectorSearch": false, edit_documents_by_function: Some(false),
} contains_filter: Some(false),
)), })),
(status = 401, description = "The authorization header is missing", body = ResponseError, content_type = "application/json", example = json!( (status = 401, description = "The authorization header is missing", body = ResponseError, content_type = "application/json", example = json!(
{ {
"message": "The Authorization header is missing. It must use the bearer authorization method.", "message": "The Authorization header is missing. It must use the bearer authorization method.",
@ -75,8 +75,9 @@ async fn get_features(
HttpResponse::Ok().json(features) HttpResponse::Ok().json(features)
} }
#[derive(Debug, Deserr, ToSchema)] #[derive(Debug, Deserr, ToSchema, Serialize)]
#[deserr(error = DeserrJsonError, rename_all = camelCase, deny_unknown_fields)] #[deserr(error = DeserrJsonError, rename_all = camelCase, deny_unknown_fields)]
#[serde(rename_all = "camelCase")]
#[schema(rename_all = "camelCase")] #[schema(rename_all = "camelCase")]
pub struct RuntimeTogglableFeatures { pub struct RuntimeTogglableFeatures {
#[deserr(default)] #[deserr(default)]
@ -125,17 +126,17 @@ impl Aggregate for PatchExperimentalFeatureAnalytics {
/// Activate or deactivate experimental features. /// Activate or deactivate experimental features.
#[utoipa::path( #[utoipa::path(
patch, patch,
path = "/", path = "",
tag = "Experimental features", tag = "Experimental features",
security(("Bearer" = ["experimental_features.update", "experimental_features.*", "*"])), security(("Bearer" = ["experimental_features.update", "experimental_features.*", "*"])),
responses( responses(
(status = OK, description = "Experimental features are returned", body = RuntimeTogglableFeatures, content_type = "application/json", example = json!( (status = OK, description = "Experimental features are returned", body = RuntimeTogglableFeatures, content_type = "application/json", example = json!(RuntimeTogglableFeatures {
{ vector_store: Some(true),
"metrics": false, metrics: Some(true),
"logsRoute": true, logs_route: Some(false),
"vectorSearch": false, edit_documents_by_function: Some(false),
} contains_filter: Some(false),
)), })),
(status = 401, description = "The authorization header is missing", body = ResponseError, content_type = "application/json", example = json!( (status = 401, description = "The authorization header is missing", body = ResponseError, content_type = "application/json", example = json!(
{ {
"message": "The Authorization header is missing. It must use the bearer authorization method.", "message": "The Authorization header is missing. It must use the bearer authorization method.",

View File

@ -135,7 +135,7 @@ impl ListIndexes {
/// List all indexes. /// List all indexes.
#[utoipa::path( #[utoipa::path(
get, get,
path = "/", path = "",
tag = "Indexes", tag = "Indexes",
security(("Bearer" = ["indexes.get", "indexes.*", "*"])), security(("Bearer" = ["indexes.get", "indexes.*", "*"])),
params(ListIndexes), params(ListIndexes),
@ -226,7 +226,7 @@ impl Aggregate for IndexCreatedAggregate {
/// Create an index. /// Create an index.
#[utoipa::path( #[utoipa::path(
post, post,
path = "/", path = "",
tag = "Indexes", tag = "Indexes",
security(("Bearer" = ["indexes.create", "indexes.*", "*"])), security(("Bearer" = ["indexes.create", "indexes.*", "*"])),
request_body = IndexCreateRequest, request_body = IndexCreateRequest,

View File

@ -86,6 +86,7 @@ macro_rules! make_setting_route {
path = concat!("{indexUid}/settings", $route), path = concat!("{indexUid}/settings", $route),
tag = "Settings", tag = "Settings",
security(("Bearer" = ["settings.update", "settings.*", "*"])), security(("Bearer" = ["settings.update", "settings.*", "*"])),
operation_id = concat!("delete", $camelcase_attr),
summary = concat!("Reset ", $camelcase_attr), summary = concat!("Reset ", $camelcase_attr),
description = concat!("Reset an index's ", $camelcase_attr, " to its default value"), description = concat!("Reset an index's ", $camelcase_attr, " to its default value"),
params(("indexUid", example = "movies", description = "Index Unique Identifier", nullable = false)), params(("indexUid", example = "movies", description = "Index Unique Identifier", nullable = false)),
@ -149,6 +150,7 @@ macro_rules! make_setting_route {
path = concat!("{indexUid}/settings", $route), path = concat!("{indexUid}/settings", $route),
tag = "Settings", tag = "Settings",
security(("Bearer" = ["settings.update", "settings.*", "*"])), security(("Bearer" = ["settings.update", "settings.*", "*"])),
operation_id = concat!(stringify!($update_verb), $camelcase_attr),
summary = concat!("Update ", $camelcase_attr), summary = concat!("Update ", $camelcase_attr),
description = concat!("Update an index's user defined ", $camelcase_attr), description = concat!("Update an index's user defined ", $camelcase_attr),
params(("indexUid", example = "movies", description = "Index Unique Identifier", nullable = false)), params(("indexUid", example = "movies", description = "Index Unique Identifier", nullable = false)),
@ -236,6 +238,7 @@ macro_rules! make_setting_route {
summary = concat!("Get ", $camelcase_attr), summary = concat!("Get ", $camelcase_attr),
description = concat!("Get an user defined ", $camelcase_attr), description = concat!("Get an user defined ", $camelcase_attr),
security(("Bearer" = ["settings.get", "settings.*", "*"])), security(("Bearer" = ["settings.get", "settings.*", "*"])),
operation_id = concat!("get", $camelcase_attr),
params(("indexUid", example = "movies", description = "Index Unique Identifier", nullable = false)), params(("indexUid", example = "movies", description = "Index Unique Identifier", nullable = false)),
responses( responses(
(status = 200, description = concat!($camelcase_attr, " is returned"), body = $type, content_type = "application/json", example = json!( (status = 200, description = concat!($camelcase_attr, " is returned"), body = $type, content_type = "application/json", example = json!(

View File

@ -30,7 +30,7 @@ pub fn configure(config: &mut web::ServiceConfig) {
/// which means it must be enabled. /// which means it must be enabled.
#[utoipa::path( #[utoipa::path(
get, get,
path = "/", path = "",
tag = "Stats", tag = "Stats",
security(("Bearer" = ["metrics.get", "metrics.*", "*"])), security(("Bearer" = ["metrics.get", "metrics.*", "*"])),
responses( responses(

View File

@ -81,6 +81,10 @@ pub mod tasks;
(name = "Stats", description = "Stats gives extended information and metrics about indexes and the Meilisearch database."), (name = "Stats", description = "Stats gives extended information and metrics about indexes and the Meilisearch database."),
), ),
modifiers(&OpenApiAuth), modifiers(&OpenApiAuth),
servers((
url = "/",
description = "Local server",
)),
components(schemas(PaginationView<KeyView>, PaginationView<IndexView>, IndexView, DocumentDeletionByFilter, AllBatches, BatchStats, ProgressStepView, ProgressView, BatchView, RuntimeTogglableFeatures, SwapIndexesPayload, DocumentEditionByFunction, MergeFacets, FederationOptions, SearchQueryWithIndex, Federation, FederatedSearch, FederatedSearchResult, SearchResults, SearchResultWithIndex, SimilarQuery, SimilarResult, PaginationView<serde_json::Value>, BrowseQuery, UpdateIndexRequest, IndexUid, IndexCreateRequest, KeyView, Action, CreateApiKey, UpdateStderrLogs, LogMode, GetLogs, IndexStats, Stats, HealthStatus, HealthResponse, VersionResponse, Code, ErrorType, AllTasks, TaskView, Status, DetailsView, ResponseError, Settings<Unchecked>, Settings<Checked>, TypoSettings, MinWordSizeTyposSetting, FacetingSettings, PaginationSettings, SummarizedTaskView, Kind)) components(schemas(PaginationView<KeyView>, PaginationView<IndexView>, IndexView, DocumentDeletionByFilter, AllBatches, BatchStats, ProgressStepView, ProgressView, BatchView, RuntimeTogglableFeatures, SwapIndexesPayload, DocumentEditionByFunction, MergeFacets, FederationOptions, SearchQueryWithIndex, Federation, FederatedSearch, FederatedSearchResult, SearchResults, SearchResultWithIndex, SimilarQuery, SimilarResult, PaginationView<serde_json::Value>, BrowseQuery, UpdateIndexRequest, IndexUid, IndexCreateRequest, KeyView, Action, CreateApiKey, UpdateStderrLogs, LogMode, GetLogs, IndexStats, Stats, HealthStatus, HealthResponse, VersionResponse, Code, ErrorType, AllTasks, TaskView, Status, DetailsView, ResponseError, Settings<Unchecked>, Settings<Checked>, TypoSettings, MinWordSizeTyposSetting, FacetingSettings, PaginationSettings, SummarizedTaskView, Kind))
)] )]
pub struct MeilisearchApi; pub struct MeilisearchApi;

View File

@ -48,7 +48,7 @@ pub struct SearchResults {
/// Bundle multiple search queries in a single API request. Use this endpoint to search through multiple indexes at once. /// Bundle multiple search queries in a single API request. Use this endpoint to search through multiple indexes at once.
#[utoipa::path( #[utoipa::path(
post, post,
path = "/", path = "",
tag = "Multi-search", tag = "Multi-search",
security(("Bearer" = ["search", "*"])), security(("Bearer" = ["search", "*"])),
responses( responses(

View File

@ -39,7 +39,7 @@ crate::empty_analytics!(SnapshotAnalytics, "Snapshot Created");
/// Triggers a snapshot creation process. Once the process is complete, a snapshot is created in the snapshot directory. If the snapshot directory does not exist yet, it will be created. /// Triggers a snapshot creation process. Once the process is complete, a snapshot is created in the snapshot directory. If the snapshot directory does not exist yet, it will be created.
#[utoipa::path( #[utoipa::path(
post, post,
path = "/", path = "",
tag = "Snapshots", tag = "Snapshots",
security(("Bearer" = ["snapshots.create", "snapshots.*", "*"])), security(("Bearer" = ["snapshots.create", "snapshots.*", "*"])),
responses( responses(

View File

@ -63,7 +63,7 @@ impl Aggregate for IndexSwappedAnalytics {
/// Swapping indexA and indexB will also replace every mention of indexA by indexB and vice-versa in the task history. enqueued tasks are left unmodified. /// Swapping indexA and indexB will also replace every mention of indexA by indexB and vice-versa in the task history. enqueued tasks are left unmodified.
#[utoipa::path( #[utoipa::path(
post, post,
path = "/", path = "",
tag = "Indexes", tag = "Indexes",
security(("Bearer" = ["search", "*"])), security(("Bearer" = ["search", "*"])),
request_body = Vec<SwapIndexesPayload>, request_body = Vec<SwapIndexesPayload>,