update authorization middleware with actix-web-macros

This commit is contained in:
Quentin de Quelen 2020-04-22 17:43:51 +02:00 committed by qdequele
parent e74d2c1872
commit bc8ff49de3
No known key found for this signature in database
GPG Key ID: B3F0A000EBF11745
13 changed files with 323 additions and 196 deletions

12
Cargo.lock generated
View File

@ -290,6 +290,17 @@ dependencies = [
"syn", "syn",
] ]
[[package]]
name = "actix-web-macros"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5ec7f5e4b361aeb648381a33cf81bd0e7a9d2cf9b49cf05fb4e161d8096bb25"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "adler32" name = "adler32"
version = "1.0.4" version = "1.0.4"
@ -1507,6 +1518,7 @@ dependencies = [
"actix-rt", "actix-rt",
"actix-service", "actix-service",
"actix-web", "actix-web",
"actix-web-macros",
"assert-json-diff", "assert-json-diff",
"chrono", "chrono",
"crossbeam-channel", "crossbeam-channel",

View File

@ -46,6 +46,7 @@ actix-http = "1"
actix-files = "0.2.1" actix-files = "0.2.1"
actix-cors = "0.2.0" actix-cors = "0.2.0"
actix-service = "1.0.5" actix-service = "1.0.5"
actix-web-macros = "0.1.0"
tokio = { version = "0.2.18", features = ["macros"] } tokio = { version = "0.2.18", features = ["macros"] }
[dev-dependencies] [dev-dependencies]

View File

@ -17,14 +17,12 @@ pub enum ResponseError {
InvalidToken(String), InvalidToken(String),
Maintenance, Maintenance,
MissingAuthorizationHeader, MissingAuthorizationHeader,
MissingFilterValue,
MissingHeader(String), MissingHeader(String),
NotFound(String), NotFound(String),
OpenIndex(String), OpenIndex(String),
FilterParsing(String), FilterParsing(String),
RetrieveDocument(u64, String), RetrieveDocument(u64, String),
SearchDocuments(String), SearchDocuments(String),
UnknownFilteredAttribute,
} }
impl ResponseError { impl ResponseError {
@ -103,13 +101,11 @@ impl fmt::Display for ResponseError {
Self::Maintenance => f.write_str("Server is in maintenance, please try again later"), Self::Maintenance => f.write_str("Server is in maintenance, please try again later"),
Self::FilterParsing(err) => write!(f, "parsing error: {}", err), Self::FilterParsing(err) => write!(f, "parsing error: {}", err),
Self::MissingAuthorizationHeader => f.write_str("You must have an authorization token"), Self::MissingAuthorizationHeader => f.write_str("You must have an authorization token"),
Self::MissingFilterValue => f.write_str("a filter doesn't have a value to compare it with"),
Self::MissingHeader(header) => write!(f, "Header {} is missing", header), Self::MissingHeader(header) => write!(f, "Header {} is missing", header),
Self::NotFound(err) => write!(f, "{} not found", err), Self::NotFound(err) => write!(f, "{} not found", err),
Self::OpenIndex(err) => write!(f, "Impossible to open index; {}", err), Self::OpenIndex(err) => write!(f, "Impossible to open index; {}", err),
Self::RetrieveDocument(id, err) => write!(f, "impossible to retrieve the document with id: {}; {}", id, err), Self::RetrieveDocument(id, err) => write!(f, "impossible to retrieve the document with id: {}; {}", id, err),
Self::SearchDocuments(err) => write!(f, "impossible to search documents; {}", err), Self::SearchDocuments(err) => write!(f, "impossible to search documents; {}", err),
Self::UnknownFilteredAttribute => f.write_str("a filter is specifying an unknown schema attribute"),
} }
} }
} }
@ -123,24 +119,22 @@ impl aweb::error::ResponseError for ResponseError {
fn status_code(&self) -> StatusCode { fn status_code(&self) -> StatusCode {
match *self { match *self {
Self::BadParameter(_, _) => StatusCode::BAD_REQUEST, Self::BadParameter(_, _)
Self::BadRequest(_) => StatusCode::BAD_REQUEST, | Self::BadRequest(_)
Self::CreateIndex(_) => StatusCode::BAD_REQUEST, | Self::CreateIndex(_)
Self::DocumentNotFound(_) => StatusCode::NOT_FOUND, | Self::InvalidIndexUid
Self::IndexNotFound(_) => StatusCode::NOT_FOUND, | Self::OpenIndex(_)
Self::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR, | Self::RetrieveDocument(_, _)
Self::InvalidIndexUid => StatusCode::BAD_REQUEST, | Self::SearchDocuments(_)
Self::InvalidToken(_) => StatusCode::UNAUTHORIZED, | Self::FilterParsing(_) => StatusCode::BAD_REQUEST,
Self::Maintenance => StatusCode::SERVICE_UNAVAILABLE, Self::DocumentNotFound(_)
Self::FilterParsing(_) => StatusCode::BAD_REQUEST, | Self::IndexNotFound(_)
| Self::NotFound(_) => StatusCode::NOT_FOUND,
Self::InvalidToken(_)
| Self::MissingHeader(_) => StatusCode::UNAUTHORIZED,
Self::MissingAuthorizationHeader => StatusCode::FORBIDDEN, Self::MissingAuthorizationHeader => StatusCode::FORBIDDEN,
Self::MissingFilterValue => StatusCode::BAD_REQUEST, Self::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
Self::MissingHeader(_) => StatusCode::UNAUTHORIZED, Self::Maintenance => StatusCode::SERVICE_UNAVAILABLE,
Self::NotFound(_) => StatusCode::NOT_FOUND,
Self::OpenIndex(_) => StatusCode::BAD_REQUEST,
Self::RetrieveDocument(_, _) => StatusCode::BAD_REQUEST,
Self::SearchDocuments(_) => StatusCode::BAD_REQUEST,
Self::UnknownFilteredAttribute => StatusCode::BAD_REQUEST,
} }
} }
} }

View File

@ -29,57 +29,17 @@ pub fn create_app(
App::new() App::new()
.app_data(web::Data::new(data.clone())) .app_data(web::Data::new(data.clone()))
.app_data(web::JsonConfig::default().limit(1024 * 1024 * 10)) // Json Limit of 10Mb .app_data(web::JsonConfig::default().limit(1024 * 1024 * 10)) // Json Limit of 10Mb
.wrap(helpers::Authentication::Public)
.service(routes::load_html) .service(routes::load_html)
.service(routes::load_css) .service(routes::load_css)
.service(routes::search::search_with_url_query) .configure(routes::document::services)
.service(routes::document::get_document) .configure(routes::index::services)
.service(routes::document::get_all_documents) .configure(routes::search::services)
.wrap(helpers::Authentication::Private) .configure(routes::setting::services)
.service(routes::index::list_indexes) .configure(routes::stop_words::services)
.service(routes::index::get_index) .configure(routes::synonym::services)
.service(routes::index::create_index) .configure(routes::health::services)
.service(routes::index::update_index) .configure(routes::stats::services)
.service(routes::index::delete_index) .configure(routes::key::services)
.service(routes::index::get_update_status)
.service(routes::index::get_all_updates_status)
.service(routes::document::delete_document)
.service(routes::document::add_documents)
.service(routes::document::update_documents)
.service(routes::document::delete_documents)
.service(routes::document::clear_all_documents)
.service(routes::setting::update_all)
.service(routes::setting::get_all)
.service(routes::setting::delete_all)
.service(routes::setting::get_rules)
.service(routes::setting::update_rules)
.service(routes::setting::delete_rules)
.service(routes::setting::get_distinct)
.service(routes::setting::update_distinct)
.service(routes::setting::delete_distinct)
.service(routes::setting::get_searchable)
.service(routes::setting::update_searchable)
.service(routes::setting::delete_searchable)
.service(routes::setting::get_displayed)
.service(routes::setting::update_displayed)
.service(routes::setting::delete_displayed)
.service(routes::setting::get_accept_new_fields)
.service(routes::setting::update_accept_new_fields)
.service(routes::stop_words::get)
.service(routes::stop_words::update)
.service(routes::stop_words::delete)
.service(routes::synonym::get)
.service(routes::synonym::update)
.service(routes::synonym::delete)
.service(routes::stats::index_stats)
.service(routes::stats::get_stats)
.service(routes::stats::get_version)
.service(routes::stats::get_sys_info)
.service(routes::stats::get_sys_info_pretty)
.service(routes::health::get_health)
.service(routes::health::change_healthyness)
.wrap(helpers::Authentication::Admin)
.service(routes::key::list)
} }
pub fn index_update_callback(index_uid: &str, data: &Data, status: ProcessedUpdateResult) { pub fn index_update_callback(index_uid: &str, data: &Data, status: ProcessedUpdateResult) {

View File

@ -1,24 +1,39 @@
use std::collections::{BTreeSet, HashSet}; use std::collections::{BTreeSet, HashSet};
use actix_web::{delete, get, post, put, web, HttpResponse}; use actix_web::{web, HttpResponse};
use actix_web_macros::{delete, get, post, put};
use indexmap::IndexMap; use indexmap::IndexMap;
use serde::Deserialize; use serde::Deserialize;
use serde_json::Value; use serde_json::Value;
use crate::error::ResponseError; use crate::error::ResponseError;
use crate::helpers::Authentication;
use crate::routes::{IndexParam, IndexUpdateResponse}; use crate::routes::{IndexParam, IndexUpdateResponse};
use crate::Data; use crate::Data;
type Document = IndexMap<String, Value>; type Document = IndexMap<String, Value>;
#[derive(Default, Deserialize)] #[derive(Default, Deserialize)]
pub struct DocumentParam { struct DocumentParam {
index_uid: String, index_uid: String,
document_id: String, document_id: String,
} }
#[get("/indexes/{index_uid}/documents/{document_id}")] pub fn services(cfg: &mut web::ServiceConfig) {
pub async fn get_document( cfg.service(get_document)
.service(delete_document)
.service(get_all_documents)
.service(add_documents)
.service(update_documents)
.service(delete_documents)
.service(clear_all_documents);
}
#[get(
"/indexes/{index_uid}/documents/{document_id}",
wrap = "Authentication::Public"
)]
async fn get_document(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<DocumentParam>, path: web::Path<DocumentParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -37,8 +52,11 @@ pub async fn get_document(
Ok(HttpResponse::Ok().json(response)) Ok(HttpResponse::Ok().json(response))
} }
#[delete("/indexes/{index_uid}/documents/{document_id}")] #[delete(
pub async fn delete_document( "/indexes/{index_uid}/documents/{document_id}",
wrap = "Authentication::Private"
)]
async fn delete_document(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<DocumentParam>, path: web::Path<DocumentParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -62,14 +80,14 @@ pub async fn delete_document(
#[derive(Default, Deserialize)] #[derive(Default, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)] #[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct BrowseQuery { struct BrowseQuery {
offset: Option<usize>, offset: Option<usize>,
limit: Option<usize>, limit: Option<usize>,
attributes_to_retrieve: Option<String>, attributes_to_retrieve: Option<String>,
} }
#[get("/indexes/{index_uid}/documents")] #[get("/indexes/{index_uid}/documents", wrap = "Authentication::Public")]
pub async fn get_all_documents( async fn get_all_documents(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
params: web::Query<BrowseQuery>, params: web::Query<BrowseQuery>,
@ -119,7 +137,7 @@ fn find_primary_key(document: &IndexMap<String, Value>) -> Option<String> {
#[derive(Default, Deserialize)] #[derive(Default, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)] #[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct UpdateDocumentsQuery { struct UpdateDocumentsQuery {
primary_key: Option<String>, primary_key: Option<String>,
} }
@ -175,8 +193,8 @@ async fn update_multiple_documents(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[post("/indexes/{index_uid}/documents")] #[post("/indexes/{index_uid}/documents", wrap = "Authentication::Private")]
pub async fn add_documents( async fn add_documents(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
params: web::Query<UpdateDocumentsQuery>, params: web::Query<UpdateDocumentsQuery>,
@ -185,8 +203,8 @@ pub async fn add_documents(
update_multiple_documents(data, path, params, body, false).await update_multiple_documents(data, path, params, body, false).await
} }
#[put("/indexes/{index_uid}/documents")] #[put("/indexes/{index_uid}/documents", wrap = "Authentication::Private")]
pub async fn update_documents( async fn update_documents(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
params: web::Query<UpdateDocumentsQuery>, params: web::Query<UpdateDocumentsQuery>,
@ -195,8 +213,11 @@ pub async fn update_documents(
update_multiple_documents(data, path, params, body, true).await update_multiple_documents(data, path, params, body, true).await
} }
#[post("/indexes/{index_uid}/documents/delete-batch")] #[post(
pub async fn delete_documents( "/indexes/{index_uid}/documents/delete-batch",
wrap = "Authentication::Private"
)]
async fn delete_documents(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<Vec<Value>>, body: web::Json<Vec<Value>>,
@ -224,8 +245,8 @@ pub async fn delete_documents(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[delete("/indexes/{index_uid}/documents")] #[delete("/indexes/{index_uid}/documents", wrap = "Authentication::Private")]
pub async fn clear_all_documents( async fn clear_all_documents(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {

View File

@ -1,13 +1,20 @@
use crate::error::ResponseError; use actix_web::{web, HttpResponse};
use crate::Data; use actix_web_macros::{get, put};
use actix_web::{get, put, web, HttpResponse};
use heed::types::{Str, Unit}; use heed::types::{Str, Unit};
use serde::Deserialize; use serde::Deserialize;
use crate::error::ResponseError;
use crate::helpers::Authentication;
use crate::Data;
const UNHEALTHY_KEY: &str = "_is_unhealthy"; const UNHEALTHY_KEY: &str = "_is_unhealthy";
#[get("/health")] pub fn services(cfg: &mut web::ServiceConfig) {
pub async fn get_health(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> { cfg.service(get_health).service(change_healthyness);
}
#[get("/health", wrap = "Authentication::Private")]
async fn get_health(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
let reader = data.db.main_read_txn()?; let reader = data.db.main_read_txn()?;
let common_store = data.db.common_store(); let common_store = data.db.common_store();
@ -19,7 +26,7 @@ pub async fn get_health(data: web::Data<Data>) -> Result<HttpResponse, ResponseE
Ok(HttpResponse::Ok().finish()) Ok(HttpResponse::Ok().finish())
} }
pub async fn set_healthy(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> { async fn set_healthy(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
let mut writer = data.db.main_write_txn()?; let mut writer = data.db.main_write_txn()?;
let common_store = data.db.common_store(); let common_store = data.db.common_store();
common_store.delete::<_, Str>(&mut writer, UNHEALTHY_KEY)?; common_store.delete::<_, Str>(&mut writer, UNHEALTHY_KEY)?;
@ -28,7 +35,7 @@ pub async fn set_healthy(data: web::Data<Data>) -> Result<HttpResponse, Response
Ok(HttpResponse::Ok().finish()) Ok(HttpResponse::Ok().finish())
} }
pub async fn set_unhealthy(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> { async fn set_unhealthy(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
let mut writer = data.db.main_write_txn()?; let mut writer = data.db.main_write_txn()?;
let common_store = data.db.common_store(); let common_store = data.db.common_store();
common_store.put::<_, Str, Unit>(&mut writer, UNHEALTHY_KEY, &())?; common_store.put::<_, Str, Unit>(&mut writer, UNHEALTHY_KEY, &())?;
@ -38,12 +45,12 @@ pub async fn set_unhealthy(data: web::Data<Data>) -> Result<HttpResponse, Respon
} }
#[derive(Deserialize, Clone)] #[derive(Deserialize, Clone)]
pub struct HealtBody { struct HealtBody {
health: bool, health: bool,
} }
#[put("/health")] #[put("/health", wrap = "Authentication::Private")]
pub async fn change_healthyness( async fn change_healthyness(
data: web::Data<Data>, data: web::Data<Data>,
body: web::Json<HealtBody>, body: web::Json<HealtBody>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {

View File

@ -1,13 +1,25 @@
use actix_web::{delete, get, post, put, web, HttpResponse}; use actix_web::{web, HttpResponse};
use actix_web_macros::{delete, get, post, put};
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use log::error; use log::error;
use rand::seq::SliceRandom; use rand::seq::SliceRandom;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::error::ResponseError; use crate::error::ResponseError;
use crate::helpers::Authentication;
use crate::routes::IndexParam; use crate::routes::IndexParam;
use crate::Data; use crate::Data;
pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(list_indexes)
.service(get_index)
.service(create_index)
.service(update_index)
.service(delete_index)
.service(get_update_status)
.service(get_all_updates_status);
}
fn generate_uid() -> String { fn generate_uid() -> String {
let mut rng = rand::thread_rng(); let mut rng = rand::thread_rng();
let sample = b"abcdefghijklmnopqrstuvwxyz0123456789"; let sample = b"abcdefghijklmnopqrstuvwxyz0123456789";
@ -19,7 +31,7 @@ fn generate_uid() -> String {
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct IndexResponse { struct IndexResponse {
name: String, name: String,
uid: String, uid: String,
created_at: DateTime<Utc>, created_at: DateTime<Utc>,
@ -27,8 +39,8 @@ pub struct IndexResponse {
primary_key: Option<String>, primary_key: Option<String>,
} }
#[get("/indexes")] #[get("/indexes", wrap = "Authentication::Private")]
pub async fn list_indexes(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> { async fn list_indexes(data: web::Data<Data>) -> Result<HttpResponse, ResponseError> {
let reader = data.db.main_read_txn()?; let reader = data.db.main_read_txn()?;
let mut response = Vec::new(); let mut response = Vec::new();
@ -81,8 +93,8 @@ pub async fn list_indexes(data: web::Data<Data>) -> Result<HttpResponse, Respons
Ok(HttpResponse::Ok().json(response)) Ok(HttpResponse::Ok().json(response))
} }
#[get("/indexes/{index_uid}")] #[get("/indexes/{index_uid}", wrap = "Authentication::Private")]
pub async fn get_index( async fn get_index(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -128,14 +140,14 @@ pub async fn get_index(
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)] #[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct IndexCreateRequest { struct IndexCreateRequest {
name: Option<String>, name: Option<String>,
uid: Option<String>, uid: Option<String>,
primary_key: Option<String>, primary_key: Option<String>,
} }
#[post("/indexes")] #[post("/indexes", wrap = "Authentication::Private")]
pub async fn create_index( async fn create_index(
data: web::Data<Data>, data: web::Data<Data>,
body: web::Json<IndexCreateRequest>, body: web::Json<IndexCreateRequest>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -206,14 +218,14 @@ pub async fn create_index(
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)] #[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct UpdateIndexRequest { struct UpdateIndexRequest {
name: Option<String>, name: Option<String>,
primary_key: Option<String>, primary_key: Option<String>,
} }
#[derive(Debug, Serialize)] #[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct UpdateIndexResponse { struct UpdateIndexResponse {
name: String, name: String,
uid: String, uid: String,
created_at: DateTime<Utc>, created_at: DateTime<Utc>,
@ -221,8 +233,8 @@ pub struct UpdateIndexResponse {
primary_key: Option<String>, primary_key: Option<String>,
} }
#[put("/indexes/{index_uid}")] #[put("/indexes/{index_uid}", wrap = "Authentication::Private")]
pub async fn update_index( async fn update_index(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<IndexCreateRequest>, body: web::Json<IndexCreateRequest>,
@ -292,8 +304,8 @@ pub async fn update_index(
})) }))
} }
#[delete("/indexes/{index_uid}")] #[delete("/indexes/{index_uid}", wrap = "Authentication::Private")]
pub async fn delete_index( async fn delete_index(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -303,13 +315,16 @@ pub async fn delete_index(
} }
#[derive(Default, Deserialize)] #[derive(Default, Deserialize)]
pub struct UpdateParam { struct UpdateParam {
index_uid: String, index_uid: String,
update_id: u64, update_id: u64,
} }
#[get("/indexes/{index_uid}/updates/{update_id}")] #[get(
pub async fn get_update_status( "/indexes/{index_uid}/updates/{update_id}",
wrap = "Authentication::Private"
)]
async fn get_update_status(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<UpdateParam>, path: web::Path<UpdateParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -331,8 +346,8 @@ pub async fn get_update_status(
} }
} }
#[get("/indexes/{index_uid}/updates")] #[get("/indexes/{index_uid}/updates", wrap = "Authentication::Private")]
pub async fn get_all_updates_status( async fn get_all_updates_status(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {

View File

@ -1,15 +1,22 @@
use crate::Data; use actix_web::web;
use actix_web::{get, web}; use actix_web_macros::get;
use serde::Serialize; use serde::Serialize;
use crate::helpers::Authentication;
use crate::Data;
pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(list);
}
#[derive(Default, Serialize)] #[derive(Default, Serialize)]
pub struct KeysResponse { struct KeysResponse {
private: Option<String>, private: Option<String>,
public: Option<String>, public: Option<String>,
} }
#[get("/keys")] #[get("/keys", wrap = "Authentication::Admin")]
pub async fn list(data: web::Data<Data>) -> web::Json<KeysResponse> { async fn list(data: web::Data<Data>) -> web::Json<KeysResponse> {
let api_keys = data.api_keys.clone(); let api_keys = data.api_keys.clone();
web::Json(KeysResponse { web::Json(KeysResponse {
private: api_keys.private, private: api_keys.private,

View File

@ -2,17 +2,23 @@ use std::collections::{HashSet, HashMap};
use std::time::Duration; use std::time::Duration;
use log::warn; use log::warn;
use actix_web::{get, web}; use actix_web::web;
use actix_web_macros::get;
use serde::Deserialize; use serde::Deserialize;
use crate::error::ResponseError; use crate::error::ResponseError;
use crate::helpers::meilisearch::{IndexSearchExt, SearchResult}; use crate::helpers::meilisearch::{IndexSearchExt, SearchResult};
use crate::helpers::Authentication;
use crate::routes::IndexParam; use crate::routes::IndexParam;
use crate::Data; use crate::Data;
pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(search_with_url_query);
}
#[derive(Deserialize)] #[derive(Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)] #[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct SearchQuery { struct SearchQuery {
q: String, q: String,
offset: Option<usize>, offset: Option<usize>,
limit: Option<usize>, limit: Option<usize>,
@ -25,8 +31,8 @@ pub struct SearchQuery {
matches: Option<bool>, matches: Option<bool>,
} }
#[get("/indexes/{index_uid}/search")] #[get("/indexes/{index_uid}/search", wrap = "Authentication::Public")]
pub async fn search_with_url_query( async fn search_with_url_query(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
params: web::Query<SearchQuery>, params: web::Query<SearchQuery>,

View File

@ -1,13 +1,35 @@
use actix_web::{delete, get, post, web, HttpResponse}; use actix_web::{web, HttpResponse};
use actix_web_macros::{delete, get, post};
use meilisearch_core::settings::{Settings, SettingsUpdate, UpdateState, DEFAULT_RANKING_RULES}; use meilisearch_core::settings::{Settings, SettingsUpdate, UpdateState, DEFAULT_RANKING_RULES};
use std::collections::{BTreeMap, BTreeSet, HashSet}; use std::collections::{BTreeMap, BTreeSet, HashSet};
use crate::error::ResponseError; use crate::error::ResponseError;
use crate::helpers::Authentication;
use crate::routes::{IndexParam, IndexUpdateResponse}; use crate::routes::{IndexParam, IndexUpdateResponse};
use crate::Data; use crate::Data;
#[post("/indexes/{index_uid}/settings")] pub fn services(cfg: &mut web::ServiceConfig) {
pub async fn update_all( cfg.service(update_all)
.service(get_all)
.service(delete_all)
.service(get_rules)
.service(update_rules)
.service(delete_rules)
.service(get_distinct)
.service(update_distinct)
.service(delete_distinct)
.service(get_searchable)
.service(update_searchable)
.service(delete_searchable)
.service(get_displayed)
.service(update_displayed)
.service(delete_displayed)
.service(get_accept_new_fields)
.service(update_accept_new_fields);
}
#[post("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
async fn update_all(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<Settings>, body: web::Json<Settings>,
@ -28,8 +50,8 @@ pub async fn update_all(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[get("/indexes/{index_uid}/settings")] #[get("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
pub async fn get_all( async fn get_all(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -98,8 +120,8 @@ pub async fn get_all(
Ok(HttpResponse::Ok().json(settings)) Ok(HttpResponse::Ok().json(settings))
} }
#[delete("/indexes/{index_uid}/settings")] #[delete("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
pub async fn delete_all( async fn delete_all(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -126,8 +148,11 @@ pub async fn delete_all(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[get("/indexes/{index_uid}/settings/ranking-rules")] #[get(
pub async fn get_rules( "/indexes/{index_uid}/settings/ranking-rules",
wrap = "Authentication::Private"
)]
async fn get_rules(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -148,8 +173,11 @@ pub async fn get_rules(
Ok(HttpResponse::Ok().json(ranking_rules)) Ok(HttpResponse::Ok().json(ranking_rules))
} }
#[post("/indexes/{index_uid}/settings/ranking-rules")] #[post(
pub async fn update_rules( "/indexes/{index_uid}/settings/ranking-rules",
wrap = "Authentication::Private"
)]
async fn update_rules(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<Option<Vec<String>>>, body: web::Json<Option<Vec<String>>>,
@ -172,8 +200,11 @@ pub async fn update_rules(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[delete("/indexes/{index_uid}/settings/ranking-rules")] #[delete(
pub async fn delete_rules( "/indexes/{index_uid}/settings/ranking-rules",
wrap = "Authentication::Private"
)]
async fn delete_rules(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -195,8 +226,11 @@ pub async fn delete_rules(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[get("/indexes/{index_uid}/settings/distinct-attribute")] #[get(
pub async fn get_distinct( "/indexes/{index_uid}/settings/distinct-attribute",
wrap = "Authentication::Private"
)]
async fn get_distinct(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -210,8 +244,11 @@ pub async fn get_distinct(
Ok(HttpResponse::Ok().json(distinct_attribute)) Ok(HttpResponse::Ok().json(distinct_attribute))
} }
#[post("/indexes/{index_uid}/settings/distinct-attribute")] #[post(
pub async fn update_distinct( "/indexes/{index_uid}/settings/distinct-attribute",
wrap = "Authentication::Private"
)]
async fn update_distinct(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<Option<String>>, body: web::Json<Option<String>>,
@ -234,8 +271,11 @@ pub async fn update_distinct(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[delete("/indexes/{index_uid}/settings/distinct-attribute")] #[delete(
pub async fn delete_distinct( "/indexes/{index_uid}/settings/distinct-attribute",
wrap = "Authentication::Private"
)]
async fn delete_distinct(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -257,8 +297,11 @@ pub async fn delete_distinct(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[get("/indexes/{index_uid}/settings/searchable-attributes")] #[get(
pub async fn get_searchable( "/indexes/{index_uid}/settings/searchable-attributes",
wrap = "Authentication::Private"
)]
async fn get_searchable(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -274,8 +317,11 @@ pub async fn get_searchable(
Ok(HttpResponse::Ok().json(searchable_attributes)) Ok(HttpResponse::Ok().json(searchable_attributes))
} }
#[post("/indexes/{index_uid}/settings/searchable-attributes")] #[post(
pub async fn update_searchable( "/indexes/{index_uid}/settings/searchable-attributes",
wrap = "Authentication::Private"
)]
async fn update_searchable(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<Option<Vec<String>>>, body: web::Json<Option<Vec<String>>>,
@ -298,8 +344,11 @@ pub async fn update_searchable(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[delete("/indexes/{index_uid}/settings/searchable-attributes")] #[delete(
pub async fn delete_searchable( "/indexes/{index_uid}/settings/searchable-attributes",
wrap = "Authentication::Private"
)]
async fn delete_searchable(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -320,8 +369,11 @@ pub async fn delete_searchable(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[get("/indexes/{index_uid}/settings/displayed-attributes")] #[get(
pub async fn get_displayed( "/indexes/{index_uid}/settings/displayed-attributes",
wrap = "Authentication::Private"
)]
async fn get_displayed(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -343,8 +395,11 @@ pub async fn get_displayed(
Ok(HttpResponse::Ok().json(displayed_attributes)) Ok(HttpResponse::Ok().json(displayed_attributes))
} }
#[post("/indexes/{index_uid}/settings/displayed-attributes")] #[post(
pub async fn update_displayed( "/indexes/{index_uid}/settings/displayed-attributes",
wrap = "Authentication::Private"
)]
async fn update_displayed(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<Option<HashSet<String>>>, body: web::Json<Option<HashSet<String>>>,
@ -367,8 +422,11 @@ pub async fn update_displayed(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[delete("/indexes/{index_uid}/settings/displayed-attributes")] #[delete(
pub async fn delete_displayed( "/indexes/{index_uid}/settings/displayed-attributes",
wrap = "Authentication::Private"
)]
async fn delete_displayed(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -389,8 +447,11 @@ pub async fn delete_displayed(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[get("/indexes/{index_uid}/settings/accept-new-fields")] #[get(
pub async fn get_accept_new_fields( "/indexes/{index_uid}/settings/accept-new-fields",
wrap = "Authentication::Private"
)]
async fn get_accept_new_fields(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -407,8 +468,11 @@ pub async fn get_accept_new_fields(
Ok(HttpResponse::Ok().json(accept_new_fields)) Ok(HttpResponse::Ok().json(accept_new_fields))
} }
#[post("/indexes/{index_uid}/settings/accept-new-fields")] #[post(
pub async fn update_accept_new_fields( "/indexes/{index_uid}/settings/accept-new-fields",
wrap = "Authentication::Private"
)]
async fn update_accept_new_fields(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<Option<bool>>, body: web::Json<Option<bool>>,

View File

@ -1,6 +1,7 @@
use std::collections::HashMap; use std::collections::HashMap;
use actix_web::{get, web}; use actix_web::web;
use actix_web_macros::get;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use log::error; use log::error;
use pretty_bytes::converter::convert; use pretty_bytes::converter::convert;
@ -9,19 +10,28 @@ use sysinfo::{NetworkExt, ProcessExt, ProcessorExt, System, SystemExt};
use walkdir::WalkDir; use walkdir::WalkDir;
use crate::error::ResponseError; use crate::error::ResponseError;
use crate::helpers::Authentication;
use crate::routes::IndexParam; use crate::routes::IndexParam;
use crate::Data; use crate::Data;
pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(index_stats)
.service(get_stats)
.service(get_version)
.service(get_sys_info)
.service(get_sys_info_pretty);
}
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct IndexStatsResponse { struct IndexStatsResponse {
number_of_documents: u64, number_of_documents: u64,
is_indexing: bool, is_indexing: bool,
fields_frequency: HashMap<String, usize>, fields_frequency: HashMap<String, usize>,
} }
#[get("/indexes/{index_uid}/stats")] #[get("/indexes/{index_uid}/stats", wrap = "Authentication::Private")]
pub async fn index_stats( async fn index_stats(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<web::Json<IndexStatsResponse>, ResponseError> { ) -> Result<web::Json<IndexStatsResponse>, ResponseError> {
@ -51,14 +61,14 @@ pub async fn index_stats(
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct StatsResult { struct StatsResult {
database_size: u64, database_size: u64,
last_update: Option<DateTime<Utc>>, last_update: Option<DateTime<Utc>>,
indexes: HashMap<String, IndexStatsResponse>, indexes: HashMap<String, IndexStatsResponse>,
} }
#[get("/stats")] #[get("/stats", wrap = "Authentication::Private")]
pub async fn get_stats(data: web::Data<Data>) -> Result<web::Json<StatsResult>, ResponseError> { async fn get_stats(data: web::Data<Data>) -> Result<web::Json<StatsResult>, ResponseError> {
let mut index_list = HashMap::new(); let mut index_list = HashMap::new();
let reader = data.db.main_read_txn()?; let reader = data.db.main_read_txn()?;
@ -109,14 +119,14 @@ pub async fn get_stats(data: web::Data<Data>) -> Result<web::Json<StatsResult>,
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct VersionResponse { struct VersionResponse {
commit_sha: String, commit_sha: String,
build_date: String, build_date: String,
pkg_version: String, pkg_version: String,
} }
#[get("/version")] #[get("/version", wrap = "Authentication::Private")]
pub async fn get_version() -> web::Json<VersionResponse> { async fn get_version() -> web::Json<VersionResponse> {
web::Json(VersionResponse { web::Json(VersionResponse {
commit_sha: env!("VERGEN_SHA").to_string(), commit_sha: env!("VERGEN_SHA").to_string(),
build_date: env!("VERGEN_BUILD_TIMESTAMP").to_string(), build_date: env!("VERGEN_BUILD_TIMESTAMP").to_string(),
@ -126,7 +136,7 @@ pub async fn get_version() -> web::Json<VersionResponse> {
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct SysGlobal { struct SysGlobal {
total_memory: u64, total_memory: u64,
used_memory: u64, used_memory: u64,
total_swap: u64, total_swap: u64,
@ -150,7 +160,7 @@ impl SysGlobal {
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct SysProcess { struct SysProcess {
memory: u64, memory: u64,
cpu: f32, cpu: f32,
} }
@ -166,7 +176,7 @@ impl SysProcess {
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct SysInfo { struct SysInfo {
memory_usage: f64, memory_usage: f64,
processor_usage: Vec<f32>, processor_usage: Vec<f32>,
global: SysGlobal, global: SysGlobal,
@ -184,8 +194,8 @@ impl SysInfo {
} }
} }
#[get("/sys-info")] #[get("/sys-info", wrap = "Authentication::Private")]
pub async fn get_sys_info(data: web::Data<Data>) -> web::Json<SysInfo> { async fn get_sys_info(data: web::Data<Data>) -> web::Json<SysInfo> {
let mut sys = System::new(); let mut sys = System::new();
let mut info = SysInfo::new(); let mut info = SysInfo::new();
@ -221,7 +231,7 @@ pub async fn get_sys_info(data: web::Data<Data>) -> web::Json<SysInfo> {
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct SysGlobalPretty { struct SysGlobalPretty {
total_memory: String, total_memory: String,
used_memory: String, used_memory: String,
total_swap: String, total_swap: String,
@ -245,7 +255,7 @@ impl SysGlobalPretty {
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct SysProcessPretty { struct SysProcessPretty {
memory: String, memory: String,
cpu: String, cpu: String,
} }
@ -261,7 +271,7 @@ impl SysProcessPretty {
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct SysInfoPretty { struct SysInfoPretty {
memory_usage: String, memory_usage: String,
processor_usage: Vec<String>, processor_usage: Vec<String>,
global: SysGlobalPretty, global: SysGlobalPretty,
@ -279,8 +289,8 @@ impl SysInfoPretty {
} }
} }
#[get("/sys-info/pretty")] #[get("/sys-info/pretty", wrap = "Authentication::Private")]
pub async fn get_sys_info_pretty(data: web::Data<Data>) -> web::Json<SysInfoPretty> { async fn get_sys_info_pretty(data: web::Data<Data>) -> web::Json<SysInfoPretty> {
let mut sys = System::new(); let mut sys = System::new();
let mut info = SysInfoPretty::new(); let mut info = SysInfoPretty::new();

View File

@ -1,13 +1,22 @@
use actix_web::{delete, get, post, web, HttpResponse}; use actix_web::{web, HttpResponse};
use actix_web_macros::{delete, get, post};
use meilisearch_core::settings::{SettingsUpdate, UpdateState}; use meilisearch_core::settings::{SettingsUpdate, UpdateState};
use std::collections::BTreeSet; use std::collections::BTreeSet;
use crate::error::ResponseError; use crate::error::ResponseError;
use crate::helpers::Authentication;
use crate::routes::{IndexParam, IndexUpdateResponse}; use crate::routes::{IndexParam, IndexUpdateResponse};
use crate::Data; use crate::Data;
#[get("/indexes/{index_uid}/settings/stop-words")] pub fn services(cfg: &mut web::ServiceConfig) {
pub async fn get( cfg.service(get).service(update).service(delete);
}
#[get(
"/indexes/{index_uid}/settings/stop-words",
wrap = "Authentication::Private"
)]
async fn get(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -22,8 +31,11 @@ pub async fn get(
Ok(HttpResponse::Ok().json(stop_words)) Ok(HttpResponse::Ok().json(stop_words))
} }
#[post("/indexes/{index_uid}/settings/stop-words")] #[post(
pub async fn update( "/indexes/{index_uid}/settings/stop-words",
wrap = "Authentication::Private"
)]
async fn update(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<BTreeSet<String>>, body: web::Json<BTreeSet<String>>,
@ -45,8 +57,11 @@ pub async fn update(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[delete("/indexes/{index_uid}/settings/stop-words")] #[delete(
pub async fn delete( "/indexes/{index_uid}/settings/stop-words",
wrap = "Authentication::Private"
)]
async fn delete(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {

View File

@ -1,15 +1,24 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use actix_web::{delete, get, post, web, HttpResponse}; use actix_web::{web, HttpResponse};
use actix_web_macros::{delete, get, post};
use indexmap::IndexMap; use indexmap::IndexMap;
use meilisearch_core::settings::{SettingsUpdate, UpdateState}; use meilisearch_core::settings::{SettingsUpdate, UpdateState};
use crate::error::ResponseError; use crate::error::ResponseError;
use crate::helpers::Authentication;
use crate::routes::{IndexParam, IndexUpdateResponse}; use crate::routes::{IndexParam, IndexUpdateResponse};
use crate::Data; use crate::Data;
#[get("/indexes/{index_uid}/settings/synonyms")] pub fn services(cfg: &mut web::ServiceConfig) {
pub async fn get( cfg.service(get).service(update).service(delete);
}
#[get(
"/indexes/{index_uid}/settings/synonyms",
wrap = "Authentication::Private"
)]
async fn get(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {
@ -37,8 +46,11 @@ pub async fn get(
Ok(HttpResponse::Ok().json(synonyms)) Ok(HttpResponse::Ok().json(synonyms))
} }
#[post("/indexes/{index_uid}/settings/synonyms")] #[post(
pub async fn update( "/indexes/{index_uid}/settings/synonyms",
wrap = "Authentication::Private"
)]
async fn update(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
body: web::Json<BTreeMap<String, Vec<String>>>, body: web::Json<BTreeMap<String, Vec<String>>>,
@ -60,8 +72,11 @@ pub async fn update(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id))) Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
} }
#[delete("/indexes/{index_uid}/settings/synonyms")] #[delete(
pub async fn delete( "/indexes/{index_uid}/settings/synonyms",
wrap = "Authentication::Private"
)]
async fn delete(
data: web::Data<Data>, data: web::Data<Data>,
path: web::Path<IndexParam>, path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> { ) -> Result<HttpResponse, ResponseError> {