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",
]
[[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]]
name = "adler32"
version = "1.0.4"
@ -1507,6 +1518,7 @@ dependencies = [
"actix-rt",
"actix-service",
"actix-web",
"actix-web-macros",
"assert-json-diff",
"chrono",
"crossbeam-channel",

View File

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

View File

@ -17,14 +17,12 @@ pub enum ResponseError {
InvalidToken(String),
Maintenance,
MissingAuthorizationHeader,
MissingFilterValue,
MissingHeader(String),
NotFound(String),
OpenIndex(String),
FilterParsing(String),
RetrieveDocument(u64, String),
SearchDocuments(String),
UnknownFilteredAttribute,
}
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::FilterParsing(err) => write!(f, "parsing error: {}", err),
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::NotFound(err) => write!(f, "{} not found", 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::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 {
match *self {
Self::BadParameter(_, _) => StatusCode::BAD_REQUEST,
Self::BadRequest(_) => StatusCode::BAD_REQUEST,
Self::CreateIndex(_) => StatusCode::BAD_REQUEST,
Self::DocumentNotFound(_) => StatusCode::NOT_FOUND,
Self::IndexNotFound(_) => StatusCode::NOT_FOUND,
Self::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
Self::InvalidIndexUid => StatusCode::BAD_REQUEST,
Self::InvalidToken(_) => StatusCode::UNAUTHORIZED,
Self::Maintenance => StatusCode::SERVICE_UNAVAILABLE,
Self::FilterParsing(_) => StatusCode::BAD_REQUEST,
Self::BadParameter(_, _)
| Self::BadRequest(_)
| Self::CreateIndex(_)
| Self::InvalidIndexUid
| Self::OpenIndex(_)
| Self::RetrieveDocument(_, _)
| Self::SearchDocuments(_)
| Self::FilterParsing(_) => StatusCode::BAD_REQUEST,
Self::DocumentNotFound(_)
| Self::IndexNotFound(_)
| Self::NotFound(_) => StatusCode::NOT_FOUND,
Self::InvalidToken(_)
| Self::MissingHeader(_) => StatusCode::UNAUTHORIZED,
Self::MissingAuthorizationHeader => StatusCode::FORBIDDEN,
Self::MissingFilterValue => StatusCode::BAD_REQUEST,
Self::MissingHeader(_) => StatusCode::UNAUTHORIZED,
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,
Self::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
Self::Maintenance => StatusCode::SERVICE_UNAVAILABLE,
}
}
}

View File

@ -29,57 +29,17 @@ pub fn create_app(
App::new()
.app_data(web::Data::new(data.clone()))
.app_data(web::JsonConfig::default().limit(1024 * 1024 * 10)) // Json Limit of 10Mb
.wrap(helpers::Authentication::Public)
.service(routes::load_html)
.service(routes::load_css)
.service(routes::search::search_with_url_query)
.service(routes::document::get_document)
.service(routes::document::get_all_documents)
.wrap(helpers::Authentication::Private)
.service(routes::index::list_indexes)
.service(routes::index::get_index)
.service(routes::index::create_index)
.service(routes::index::update_index)
.service(routes::index::delete_index)
.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)
.configure(routes::document::services)
.configure(routes::index::services)
.configure(routes::search::services)
.configure(routes::setting::services)
.configure(routes::stop_words::services)
.configure(routes::synonym::services)
.configure(routes::health::services)
.configure(routes::stats::services)
.configure(routes::key::services)
}
pub fn index_update_callback(index_uid: &str, data: &Data, status: ProcessedUpdateResult) {

View File

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

View File

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

View File

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

View File

@ -2,17 +2,23 @@ use std::collections::{HashSet, HashMap};
use std::time::Duration;
use log::warn;
use actix_web::{get, web};
use actix_web::web;
use actix_web_macros::get;
use serde::Deserialize;
use crate::error::ResponseError;
use crate::helpers::meilisearch::{IndexSearchExt, SearchResult};
use crate::helpers::Authentication;
use crate::routes::IndexParam;
use crate::Data;
pub fn services(cfg: &mut web::ServiceConfig) {
cfg.service(search_with_url_query);
}
#[derive(Deserialize)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
pub struct SearchQuery {
struct SearchQuery {
q: String,
offset: Option<usize>,
limit: Option<usize>,
@ -25,8 +31,8 @@ pub struct SearchQuery {
matches: Option<bool>,
}
#[get("/indexes/{index_uid}/search")]
pub async fn search_with_url_query(
#[get("/indexes/{index_uid}/search", wrap = "Authentication::Public")]
async fn search_with_url_query(
data: web::Data<Data>,
path: web::Path<IndexParam>,
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 std::collections::{BTreeMap, BTreeSet, HashSet};
use crate::error::ResponseError;
use crate::helpers::Authentication;
use crate::routes::{IndexParam, IndexUpdateResponse};
use crate::Data;
#[post("/indexes/{index_uid}/settings")]
pub async fn update_all(
pub fn services(cfg: &mut web::ServiceConfig) {
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>,
path: web::Path<IndexParam>,
body: web::Json<Settings>,
@ -28,8 +50,8 @@ pub async fn update_all(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
#[get("/indexes/{index_uid}/settings")]
pub async fn get_all(
#[get("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
async fn get_all(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> {
@ -98,8 +120,8 @@ pub async fn get_all(
Ok(HttpResponse::Ok().json(settings))
}
#[delete("/indexes/{index_uid}/settings")]
pub async fn delete_all(
#[delete("/indexes/{index_uid}/settings", wrap = "Authentication::Private")]
async fn delete_all(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> {
@ -126,8 +148,11 @@ pub async fn delete_all(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
#[get("/indexes/{index_uid}/settings/ranking-rules")]
pub async fn get_rules(
#[get(
"/indexes/{index_uid}/settings/ranking-rules",
wrap = "Authentication::Private"
)]
async fn get_rules(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> {
@ -148,8 +173,11 @@ pub async fn get_rules(
Ok(HttpResponse::Ok().json(ranking_rules))
}
#[post("/indexes/{index_uid}/settings/ranking-rules")]
pub async fn update_rules(
#[post(
"/indexes/{index_uid}/settings/ranking-rules",
wrap = "Authentication::Private"
)]
async fn update_rules(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<Option<Vec<String>>>,
@ -172,8 +200,11 @@ pub async fn update_rules(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
#[delete("/indexes/{index_uid}/settings/ranking-rules")]
pub async fn delete_rules(
#[delete(
"/indexes/{index_uid}/settings/ranking-rules",
wrap = "Authentication::Private"
)]
async fn delete_rules(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> {
@ -195,8 +226,11 @@ pub async fn delete_rules(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
#[get("/indexes/{index_uid}/settings/distinct-attribute")]
pub async fn get_distinct(
#[get(
"/indexes/{index_uid}/settings/distinct-attribute",
wrap = "Authentication::Private"
)]
async fn get_distinct(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> {
@ -210,8 +244,11 @@ pub async fn get_distinct(
Ok(HttpResponse::Ok().json(distinct_attribute))
}
#[post("/indexes/{index_uid}/settings/distinct-attribute")]
pub async fn update_distinct(
#[post(
"/indexes/{index_uid}/settings/distinct-attribute",
wrap = "Authentication::Private"
)]
async fn update_distinct(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<Option<String>>,
@ -234,8 +271,11 @@ pub async fn update_distinct(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
#[delete("/indexes/{index_uid}/settings/distinct-attribute")]
pub async fn delete_distinct(
#[delete(
"/indexes/{index_uid}/settings/distinct-attribute",
wrap = "Authentication::Private"
)]
async fn delete_distinct(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> {
@ -257,8 +297,11 @@ pub async fn delete_distinct(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
#[get("/indexes/{index_uid}/settings/searchable-attributes")]
pub async fn get_searchable(
#[get(
"/indexes/{index_uid}/settings/searchable-attributes",
wrap = "Authentication::Private"
)]
async fn get_searchable(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> {
@ -274,8 +317,11 @@ pub async fn get_searchable(
Ok(HttpResponse::Ok().json(searchable_attributes))
}
#[post("/indexes/{index_uid}/settings/searchable-attributes")]
pub async fn update_searchable(
#[post(
"/indexes/{index_uid}/settings/searchable-attributes",
wrap = "Authentication::Private"
)]
async fn update_searchable(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<Option<Vec<String>>>,
@ -298,8 +344,11 @@ pub async fn update_searchable(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
#[delete("/indexes/{index_uid}/settings/searchable-attributes")]
pub async fn delete_searchable(
#[delete(
"/indexes/{index_uid}/settings/searchable-attributes",
wrap = "Authentication::Private"
)]
async fn delete_searchable(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> {
@ -320,8 +369,11 @@ pub async fn delete_searchable(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
#[get("/indexes/{index_uid}/settings/displayed-attributes")]
pub async fn get_displayed(
#[get(
"/indexes/{index_uid}/settings/displayed-attributes",
wrap = "Authentication::Private"
)]
async fn get_displayed(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> {
@ -343,8 +395,11 @@ pub async fn get_displayed(
Ok(HttpResponse::Ok().json(displayed_attributes))
}
#[post("/indexes/{index_uid}/settings/displayed-attributes")]
pub async fn update_displayed(
#[post(
"/indexes/{index_uid}/settings/displayed-attributes",
wrap = "Authentication::Private"
)]
async fn update_displayed(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<Option<HashSet<String>>>,
@ -367,8 +422,11 @@ pub async fn update_displayed(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
#[delete("/indexes/{index_uid}/settings/displayed-attributes")]
pub async fn delete_displayed(
#[delete(
"/indexes/{index_uid}/settings/displayed-attributes",
wrap = "Authentication::Private"
)]
async fn delete_displayed(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> {
@ -389,8 +447,11 @@ pub async fn delete_displayed(
Ok(HttpResponse::Accepted().json(IndexUpdateResponse::with_id(update_id)))
}
#[get("/indexes/{index_uid}/settings/accept-new-fields")]
pub async fn get_accept_new_fields(
#[get(
"/indexes/{index_uid}/settings/accept-new-fields",
wrap = "Authentication::Private"
)]
async fn get_accept_new_fields(
data: web::Data<Data>,
path: web::Path<IndexParam>,
) -> Result<HttpResponse, ResponseError> {
@ -407,8 +468,11 @@ pub async fn get_accept_new_fields(
Ok(HttpResponse::Ok().json(accept_new_fields))
}
#[post("/indexes/{index_uid}/settings/accept-new-fields")]
pub async fn update_accept_new_fields(
#[post(
"/indexes/{index_uid}/settings/accept-new-fields",
wrap = "Authentication::Private"
)]
async fn update_accept_new_fields(
data: web::Data<Data>,
path: web::Path<IndexParam>,
body: web::Json<Option<bool>>,

View File

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

View File

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