mirror of
https://github.com/meilisearch/meilisearch.git
synced 2024-11-26 03:55:07 +08:00
Patch errors
This commit is contained in:
parent
b2e2dc8558
commit
94b32cce01
@ -22,12 +22,14 @@ pub enum AuthControllerError {
|
|||||||
"`name` field value `{0}` is invalid. It should be a string or specified as a null value."
|
"`name` field value `{0}` is invalid. It should be a string or specified as a null value."
|
||||||
)]
|
)]
|
||||||
InvalidApiKeyName(Value),
|
InvalidApiKeyName(Value),
|
||||||
#[error("`uid` field value `{0}` is invalid. It should be a valid uuidv4 string or ommited.")]
|
#[error("`uid` field value `{0}` is invalid. It should be a valid UUID v4 string or omitted.")]
|
||||||
InvalidApiKeyUid(Value),
|
InvalidApiKeyUid(Value),
|
||||||
#[error("API key `{0}` not found.")]
|
#[error("API key `{0}` not found.")]
|
||||||
ApiKeyNotFound(String),
|
ApiKeyNotFound(String),
|
||||||
#[error("`uid` field value `{0}` already exists for an API key.")]
|
#[error("`uid` field value `{0}` is already an existing API key.")]
|
||||||
ApiKeyAlreadyExists(String),
|
ApiKeyAlreadyExists(String),
|
||||||
|
#[error("`{0}` field cannot be modified for the given resource.")]
|
||||||
|
ImmutableField(String),
|
||||||
#[error("Internal error: {0}")]
|
#[error("Internal error: {0}")]
|
||||||
Internal(Box<dyn Error + Send + Sync + 'static>),
|
Internal(Box<dyn Error + Send + Sync + 'static>),
|
||||||
}
|
}
|
||||||
@ -51,6 +53,7 @@ impl ErrorCode for AuthControllerError {
|
|||||||
Self::ApiKeyNotFound(_) => Code::ApiKeyNotFound,
|
Self::ApiKeyNotFound(_) => Code::ApiKeyNotFound,
|
||||||
Self::InvalidApiKeyUid(_) => Code::InvalidApiKeyUid,
|
Self::InvalidApiKeyUid(_) => Code::InvalidApiKeyUid,
|
||||||
Self::ApiKeyAlreadyExists(_) => Code::ApiKeyAlreadyExists,
|
Self::ApiKeyAlreadyExists(_) => Code::ApiKeyAlreadyExists,
|
||||||
|
Self::ImmutableField(_) => Code::ImmutableField,
|
||||||
Self::Internal(_) => Code::Internal,
|
Self::Internal(_) => Code::Internal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -99,6 +99,30 @@ impl Key {
|
|||||||
self.name = des?;
|
self.name = des?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if value.get("uid").is_some() {
|
||||||
|
return Err(AuthControllerError::ImmutableField("uid".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.get("actions").is_some() {
|
||||||
|
return Err(AuthControllerError::ImmutableField("actions".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.get("indexes").is_some() {
|
||||||
|
return Err(AuthControllerError::ImmutableField("indexes".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.get("expiresAt").is_some() {
|
||||||
|
return Err(AuthControllerError::ImmutableField("expiresAt".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.get("createdAt").is_some() {
|
||||||
|
return Err(AuthControllerError::ImmutableField("createdAt".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if value.get("updatedAt").is_some() {
|
||||||
|
return Err(AuthControllerError::ImmutableField("updatedAt".to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
self.updated_at = OffsetDateTime::now_utc();
|
self.updated_at = OffsetDateTime::now_utc();
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -168,6 +168,7 @@ pub enum Code {
|
|||||||
InvalidApiKeyDescription,
|
InvalidApiKeyDescription,
|
||||||
InvalidApiKeyName,
|
InvalidApiKeyName,
|
||||||
InvalidApiKeyUid,
|
InvalidApiKeyUid,
|
||||||
|
ImmutableField,
|
||||||
ApiKeyAlreadyExists,
|
ApiKeyAlreadyExists,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -278,6 +279,7 @@ impl Code {
|
|||||||
InvalidApiKeyName => ErrCode::invalid("invalid_api_key_name", StatusCode::BAD_REQUEST),
|
InvalidApiKeyName => ErrCode::invalid("invalid_api_key_name", StatusCode::BAD_REQUEST),
|
||||||
InvalidApiKeyUid => ErrCode::invalid("invalid_api_key_uid", StatusCode::BAD_REQUEST),
|
InvalidApiKeyUid => ErrCode::invalid("invalid_api_key_uid", StatusCode::BAD_REQUEST),
|
||||||
ApiKeyAlreadyExists => ErrCode::invalid("api_key_already_exists", StatusCode::CONFLICT),
|
ApiKeyAlreadyExists => ErrCode::invalid("api_key_already_exists", StatusCode::CONFLICT),
|
||||||
|
ImmutableField => ErrCode::invalid("immutable_field", StatusCode::BAD_REQUEST),
|
||||||
InvalidMinWordLengthForTypo => {
|
InvalidMinWordLengthForTypo => {
|
||||||
ErrCode::invalid("invalid_min_word_length_for_typo", StatusCode::BAD_REQUEST)
|
ErrCode::invalid("invalid_min_word_length_for_typo", StatusCode::BAD_REQUEST)
|
||||||
}
|
}
|
||||||
|
@ -470,7 +470,7 @@ async fn error_add_api_key_invalid_parameters_uid() {
|
|||||||
assert_eq!(400, code, "{:?}", &response);
|
assert_eq!(400, code, "{:?}", &response);
|
||||||
|
|
||||||
let expected_response = json!({
|
let expected_response = json!({
|
||||||
"message": r#"`uid` field value `"aaaaabbbbbccc"` is invalid. It should be a valid uuidv4 string or ommited."#,
|
"message": r#"`uid` field value `"aaaaabbbbbccc"` is invalid. It should be a valid UUID v4 string or omitted."#,
|
||||||
"code": "invalid_api_key_uid",
|
"code": "invalid_api_key_uid",
|
||||||
"type": "invalid_request",
|
"type": "invalid_request",
|
||||||
"link": "https://docs.meilisearch.com/errors#invalid_api_key_uid"
|
"link": "https://docs.meilisearch.com/errors#invalid_api_key_uid"
|
||||||
@ -499,7 +499,7 @@ async fn error_add_api_key_parameters_uid_already_exist() {
|
|||||||
assert_eq!(409, code, "{:?}", &response);
|
assert_eq!(409, code, "{:?}", &response);
|
||||||
|
|
||||||
let expected_response = json!({
|
let expected_response = json!({
|
||||||
"message": "`uid` field value `4bc0887a-0e41-4f3b-935d-0c451dcee9c8` already exists for an API key.",
|
"message": "`uid` field value `4bc0887a-0e41-4f3b-935d-0c451dcee9c8` is already an existing API key.",
|
||||||
"code": "api_key_already_exists",
|
"code": "api_key_already_exists",
|
||||||
"type": "invalid_request",
|
"type": "invalid_request",
|
||||||
"link": "https://docs.meilisearch.com/errors#api_key_already_exists"
|
"link": "https://docs.meilisearch.com/errors#api_key_already_exists"
|
||||||
@ -1112,7 +1112,7 @@ async fn patch_api_key_name() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn patch_api_key_indexes_unchanged() {
|
async fn error_patch_api_key_indexes() {
|
||||||
let mut server = Server::new_auth().await;
|
let mut server = Server::new_auth().await;
|
||||||
server.use_api_key("MASTER_KEY");
|
server.use_api_key("MASTER_KEY");
|
||||||
|
|
||||||
@ -1143,44 +1143,24 @@ async fn patch_api_key_indexes_unchanged() {
|
|||||||
assert!(response["updatedAt"].is_string());
|
assert!(response["updatedAt"].is_string());
|
||||||
|
|
||||||
let uid = response["uid"].as_str().unwrap();
|
let uid = response["uid"].as_str().unwrap();
|
||||||
let created_at = response["createdAt"].as_str().unwrap();
|
|
||||||
let updated_at = response["updatedAt"].as_str().unwrap();
|
|
||||||
|
|
||||||
let content = json!({ "indexes": ["products", "prices"] });
|
let content = json!({ "indexes": ["products", "prices"] });
|
||||||
|
|
||||||
thread::sleep(time::Duration::new(1, 0));
|
thread::sleep(time::Duration::new(1, 0));
|
||||||
let (response, code) = server.patch_api_key(&uid, content).await;
|
let (response, code) = server.patch_api_key(&uid, content).await;
|
||||||
assert_eq!(200, code, "{:?}", &response);
|
assert_eq!(400, code, "{:?}", &response);
|
||||||
assert!(response["key"].is_string());
|
|
||||||
assert!(response["expiresAt"].is_string());
|
|
||||||
assert!(response["createdAt"].is_string());
|
|
||||||
assert_ne!(response["updatedAt"].as_str().unwrap(), updated_at);
|
|
||||||
assert_eq!(response["createdAt"].as_str().unwrap(), created_at);
|
|
||||||
|
|
||||||
let expected = json!({
|
let expected = json!({"message": "`indexes` field cannot be modified for the given resource.",
|
||||||
"description": "Indexing API key",
|
"code": "immutable_field",
|
||||||
"indexes": ["products"],
|
"type": "invalid_request",
|
||||||
"actions": [
|
"link": "https://docs.meilisearch.com/errors#immutable_field"
|
||||||
"search",
|
|
||||||
"documents.add",
|
|
||||||
"documents.get",
|
|
||||||
"documents.delete",
|
|
||||||
"indexes.create",
|
|
||||||
"indexes.get",
|
|
||||||
"indexes.update",
|
|
||||||
"indexes.delete",
|
|
||||||
"stats.get",
|
|
||||||
"dumps.create",
|
|
||||||
"dumps.get"
|
|
||||||
],
|
|
||||||
"expiresAt": "2050-11-13T00:00:00Z"
|
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_json_include!(actual: response, expected: expected);
|
assert_json_include!(actual: response, expected: expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn patch_api_key_actions_unchanged() {
|
async fn error_patch_api_key_actions() {
|
||||||
let mut server = Server::new_auth().await;
|
let mut server = Server::new_auth().await;
|
||||||
server.use_api_key("MASTER_KEY");
|
server.use_api_key("MASTER_KEY");
|
||||||
|
|
||||||
@ -1212,9 +1192,6 @@ async fn patch_api_key_actions_unchanged() {
|
|||||||
|
|
||||||
let uid = response["uid"].as_str().unwrap();
|
let uid = response["uid"].as_str().unwrap();
|
||||||
|
|
||||||
let created_at = response["createdAt"].as_str().unwrap();
|
|
||||||
let updated_at = response["updatedAt"].as_str().unwrap();
|
|
||||||
|
|
||||||
let content = json!({
|
let content = json!({
|
||||||
"actions": [
|
"actions": [
|
||||||
"search",
|
"search",
|
||||||
@ -1227,37 +1204,19 @@ async fn patch_api_key_actions_unchanged() {
|
|||||||
|
|
||||||
thread::sleep(time::Duration::new(1, 0));
|
thread::sleep(time::Duration::new(1, 0));
|
||||||
let (response, code) = server.patch_api_key(&uid, content).await;
|
let (response, code) = server.patch_api_key(&uid, content).await;
|
||||||
assert_eq!(200, code, "{:?}", &response);
|
assert_eq!(400, code, "{:?}", &response);
|
||||||
assert!(response["key"].is_string());
|
|
||||||
assert!(response["expiresAt"].is_string());
|
|
||||||
assert!(response["createdAt"].is_string());
|
|
||||||
assert_ne!(response["updatedAt"].as_str().unwrap(), updated_at);
|
|
||||||
assert_eq!(response["createdAt"].as_str().unwrap(), created_at);
|
|
||||||
|
|
||||||
let expected = json!({
|
let expected = json!({"message": "`actions` field cannot be modified for the given resource.",
|
||||||
"description": "Indexing API key",
|
"code": "immutable_field",
|
||||||
"indexes": ["products"],
|
"type": "invalid_request",
|
||||||
"actions": [
|
"link": "https://docs.meilisearch.com/errors#immutable_field"
|
||||||
"search",
|
|
||||||
"documents.add",
|
|
||||||
"documents.get",
|
|
||||||
"documents.delete",
|
|
||||||
"indexes.create",
|
|
||||||
"indexes.get",
|
|
||||||
"indexes.update",
|
|
||||||
"indexes.delete",
|
|
||||||
"stats.get",
|
|
||||||
"dumps.create",
|
|
||||||
"dumps.get"
|
|
||||||
],
|
|
||||||
"expiresAt": "2050-11-13T00:00:00Z"
|
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_json_include!(actual: response, expected: expected);
|
assert_json_include!(actual: response, expected: expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[actix_rt::test]
|
#[actix_rt::test]
|
||||||
async fn patch_api_key_expiration_date_unchanged() {
|
async fn error_patch_api_key_expiration_date() {
|
||||||
let mut server = Server::new_auth().await;
|
let mut server = Server::new_auth().await;
|
||||||
server.use_api_key("MASTER_KEY");
|
server.use_api_key("MASTER_KEY");
|
||||||
|
|
||||||
@ -1288,37 +1247,17 @@ async fn patch_api_key_expiration_date_unchanged() {
|
|||||||
assert!(response["updatedAt"].is_string());
|
assert!(response["updatedAt"].is_string());
|
||||||
|
|
||||||
let uid = response["uid"].as_str().unwrap();
|
let uid = response["uid"].as_str().unwrap();
|
||||||
let created_at = response["createdAt"].as_str().unwrap();
|
|
||||||
let updated_at = response["updatedAt"].as_str().unwrap();
|
|
||||||
|
|
||||||
let content = json!({ "expiresAt": "2055-11-13T00:00:00Z" });
|
let content = json!({ "expiresAt": "2055-11-13T00:00:00Z" });
|
||||||
|
|
||||||
thread::sleep(time::Duration::new(1, 0));
|
thread::sleep(time::Duration::new(1, 0));
|
||||||
let (response, code) = server.patch_api_key(&uid, content).await;
|
let (response, code) = server.patch_api_key(&uid, content).await;
|
||||||
assert_eq!(200, code, "{:?}", &response);
|
assert_eq!(400, code, "{:?}", &response);
|
||||||
assert!(response["key"].is_string());
|
|
||||||
assert!(response["expiresAt"].is_string());
|
|
||||||
assert!(response["createdAt"].is_string());
|
|
||||||
assert_ne!(response["updatedAt"].as_str().unwrap(), updated_at);
|
|
||||||
assert_eq!(response["createdAt"].as_str().unwrap(), created_at);
|
|
||||||
|
|
||||||
let expected = json!({
|
let expected = json!({"message": "`expiresAt` field cannot be modified for the given resource.",
|
||||||
"description": "Indexing API key",
|
"code": "immutable_field",
|
||||||
"indexes": ["products"],
|
"type": "invalid_request",
|
||||||
"actions": [
|
"link": "https://docs.meilisearch.com/errors#immutable_field"
|
||||||
"search",
|
|
||||||
"documents.add",
|
|
||||||
"documents.get",
|
|
||||||
"documents.delete",
|
|
||||||
"indexes.create",
|
|
||||||
"indexes.get",
|
|
||||||
"indexes.update",
|
|
||||||
"indexes.delete",
|
|
||||||
"stats.get",
|
|
||||||
"dumps.create",
|
|
||||||
"dumps.get"
|
|
||||||
],
|
|
||||||
"expiresAt": "2050-11-13T00:00:00Z"
|
|
||||||
});
|
});
|
||||||
|
|
||||||
assert_json_include!(actual: response, expected: expected);
|
assert_json_include!(actual: response, expected: expected);
|
||||||
|
@ -149,31 +149,22 @@ async fn error_access_unauthorized_index() {
|
|||||||
#[cfg_attr(target_os = "windows", ignore)]
|
#[cfg_attr(target_os = "windows", ignore)]
|
||||||
async fn error_access_unauthorized_action() {
|
async fn error_access_unauthorized_action() {
|
||||||
let mut server = Server::new_auth().await;
|
let mut server = Server::new_auth().await;
|
||||||
server.use_api_key("MASTER_KEY");
|
|
||||||
|
|
||||||
let content = json!({
|
|
||||||
"indexes": ["products"],
|
|
||||||
"actions": [],
|
|
||||||
"expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let (response, code) = server.add_api_key(content).await;
|
|
||||||
assert_eq!(201, code, "{:?}", &response);
|
|
||||||
assert!(response["key"].is_string());
|
|
||||||
|
|
||||||
let key = response["key"].as_str().unwrap();
|
|
||||||
server.use_api_key(&key);
|
|
||||||
|
|
||||||
for ((method, route), action) in AUTHORIZATIONS.iter() {
|
for ((method, route), action) in AUTHORIZATIONS.iter() {
|
||||||
|
// create a new API key letting only the needed action.
|
||||||
server.use_api_key("MASTER_KEY");
|
server.use_api_key("MASTER_KEY");
|
||||||
|
|
||||||
// Patch API key letting all rights but the needed one.
|
|
||||||
let content = json!({
|
let content = json!({
|
||||||
|
"indexes": ["products"],
|
||||||
"actions": ALL_ACTIONS.difference(action).collect::<Vec<_>>(),
|
"actions": ALL_ACTIONS.difference(action).collect::<Vec<_>>(),
|
||||||
|
"expiresAt": (OffsetDateTime::now_utc() + Duration::hours(1)).format(&Rfc3339).unwrap(),
|
||||||
});
|
});
|
||||||
let (response, code) = server.patch_api_key(&key, content).await;
|
|
||||||
assert_eq!(200, code, "{:?}", &response);
|
|
||||||
|
|
||||||
|
let (response, code) = server.add_api_key(content).await;
|
||||||
|
assert_eq!(201, code, "{:?}", &response);
|
||||||
|
assert!(response["key"].is_string());
|
||||||
|
|
||||||
|
let key = response["key"].as_str().unwrap();
|
||||||
server.use_api_key(&key);
|
server.use_api_key(&key);
|
||||||
let (response, code) = server.dummy_request(method, route).await;
|
let (response, code) = server.dummy_request(method, route).await;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user