mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-05 17:58:55 +00:00
consolidate more error types (#1572)
This commit is contained in:
1 parent
8ecc8cf7b3
commit
a7b9ec1d95
97 files changed
+823
-3616
No files matched your search
@@ -651,7 +651,6 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
BatchGetUserBookmarksError,
|
||||
BatchGetUserBookmarksQueryParams,
|
||||
BatchGetUserBookmarksResponse,
|
||||
BatchGetUserRatingError,
|
||||
BatchGetUserRatingQueryParams,
|
||||
BatchGetUserRatingResponse,
|
||||
GenerateGptImage1TextToImageImageQuality,
|
||||
@@ -668,17 +667,13 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
GetPromptImageContextItem,
|
||||
BookmarkRow,
|
||||
ByQueueStats,
|
||||
ChangeMediaFileAnimationTypeError,
|
||||
ChangeMediaFileAnimationTypeRequest,
|
||||
ChangeMediaFileEngineCategoryError,
|
||||
ChangeMediaFileEngineCategoryRequest,
|
||||
ChangeMediaFileVisibilityError,
|
||||
ChangeMediaFileVisibilityRequest,
|
||||
CreateAccountErrorResponse,
|
||||
CreateAccountErrorType,
|
||||
CreateAccountRequest,
|
||||
CreateAccountSuccessResponse,
|
||||
CreateBetaKeysError,
|
||||
CreateBetaKeysRequest,
|
||||
CreateBetaKeysSuccessResponse,
|
||||
CreateCheckoutSessionError,
|
||||
@@ -687,7 +682,6 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
CreateCommentError,
|
||||
CreateCommentRequest,
|
||||
CreateCommentSuccessResponse,
|
||||
CreateFeaturedItemError,
|
||||
CreateFeaturedItemRequest,
|
||||
CreateFeaturedItemSuccessResponse,
|
||||
CreateSceneSuccessResponse,
|
||||
@@ -697,27 +691,22 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
DeleteCommentError,
|
||||
DeleteCommentPathInfo,
|
||||
DeleteCommentRequest,
|
||||
DeleteFeaturedItemError,
|
||||
DeleteFeaturedItemRequest,
|
||||
DeleteMediaFilePathInfo,
|
||||
DeleteMediaFileRequest,
|
||||
DeleteUserBookmarkError,
|
||||
DeleteUserBookmarkPathInfo,
|
||||
DeleteUserBookmarkRequest,
|
||||
DeleteWeightError,
|
||||
DeleteWeightPathInfo,
|
||||
DeleteWeightRequest,
|
||||
DismissFinishedSessionJobsSuccessResponse,
|
||||
EditBetaKeyDistributedFlagError,
|
||||
EditBetaKeyDistributedFlagPathInfo,
|
||||
EditBetaKeyDistributedFlagRequest,
|
||||
EditBetaKeyDistributedFlagSuccessResponse,
|
||||
EditBetaKeyNoteError,
|
||||
EditBetaKeyNotePathInfo,
|
||||
EditBetaKeyNoteRequest,
|
||||
EditBetaKeyNoteSuccessResponse,
|
||||
EditUserFeatureFlagPathInfo,
|
||||
EditUserFeatureFlagsError,
|
||||
EditUserFeatureFlagsOption,
|
||||
EditUserFeatureFlagsRequest,
|
||||
ModerationSendAlertRequest,
|
||||
@@ -790,13 +779,10 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
GptImage1EditImageNumImages,
|
||||
GptImage1EditImageImageQuality,
|
||||
GptImage1EditImageResponse,
|
||||
ChangePasswordError,
|
||||
ChangePasswordRequest,
|
||||
ChangePasswordResponse,
|
||||
EditEmailError,
|
||||
EditEmailRequest,
|
||||
EditEmailResponse,
|
||||
EditUsernameError,
|
||||
EditUsernameRequest,
|
||||
EditUsernameResponse,
|
||||
EnqueueFaceFusionCropDimensions,
|
||||
@@ -870,7 +856,6 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
GenerateVeo2ImageToVideoResponse,
|
||||
GetInferenceJobStatusPathInfo,
|
||||
GetInferenceJobStatusSuccessResponse,
|
||||
GetIsFeaturedItemError,
|
||||
GetIsFeaturedItemPathInfo,
|
||||
GetIsFeaturedItemSuccessResponse,
|
||||
GetMediaFileModelInfo,
|
||||
@@ -882,9 +867,7 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
GetPromptSuccessResponse,
|
||||
GetUnifiedQueueStatsError,
|
||||
GetUnifiedQueueStatsSuccessResponse,
|
||||
GetUserRatingError,
|
||||
GetUserRatingResponse,
|
||||
GetWeightError,
|
||||
GetWeightPathInfo,
|
||||
GetWeightResponse,
|
||||
GoogleCreateAccountRequest,
|
||||
@@ -898,7 +881,6 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
ListActiveUserSubscriptionsResponse,
|
||||
ListAvailableWeightsQuery,
|
||||
ListAvailableWeightsSuccessResponse,
|
||||
ListBetaKeysError,
|
||||
ListBetaKeysFilterOption,
|
||||
ListBetaKeysQueryParams,
|
||||
ListBetaKeysSuccessResponse,
|
||||
@@ -943,7 +925,6 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
ListSessionRequestDetailsResponse,
|
||||
ListSessionResultDetailsResponse,
|
||||
ListSessionStatusDetailsResponse,
|
||||
ListTagsForEntityError,
|
||||
ListTagsForEntityPathInfo,
|
||||
ListTagsForEntitySuccessResponse,
|
||||
ListUserBookmarksForEntityError,
|
||||
@@ -953,7 +934,6 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
ListUserBookmarksForUserSuccessResponse,
|
||||
ListUserBookmarksPathInfo,
|
||||
ListWeightError,
|
||||
ListWeightsByUserError,
|
||||
ListWeightsByUserPathInfo,
|
||||
ListWeightsByUserSuccessResponse,
|
||||
LogBrowserSessionError,
|
||||
@@ -963,7 +943,6 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
LoginErrorType,
|
||||
LoginRequest,
|
||||
LoginSuccessResponse,
|
||||
LogoutError,
|
||||
LogoutSuccessResponse,
|
||||
MediaFileData,
|
||||
MediaFileForUserListItem,
|
||||
@@ -980,24 +959,20 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
ModernInferenceQueueStats,
|
||||
PinnedMediaFile,
|
||||
PinnedModelWeightForList,
|
||||
ProfileError,
|
||||
PromptInfo,
|
||||
RatingRow,
|
||||
RedeemBetaKeyRequest,
|
||||
RedeemBetaKeySuccessResponse,
|
||||
RemoveImageBackgroundRequest,
|
||||
RemoveImageBackgroundResponse,
|
||||
RenameMediaFileError,
|
||||
RenameMediaFileRequest,
|
||||
RequestDetailsResponse,
|
||||
ResultDetailsResponse,
|
||||
StaffAuditLogResponse,
|
||||
SearchFeaturedMediaFileListItem,
|
||||
SearchFeaturedMediaFilesError,
|
||||
SearchFeaturedMediaFilesQueryParams,
|
||||
SearchFeaturedMediaFilesSuccessResponse,
|
||||
SearchMediaFileListItem,
|
||||
SearchMediaFilesError,
|
||||
SearchMediaFilesQueryParams,
|
||||
SearchMediaFilesSuccessResponse,
|
||||
SearchModelWeightsError,
|
||||
@@ -1005,31 +980,23 @@ use crate::http_server::endpoints::media_files::list::list_batch_generated_redux
|
||||
SearchModelWeightsSortDirection,
|
||||
SearchModelWeightsSortField,
|
||||
SearchModelWeightsSuccessResponse,
|
||||
SessionTokenInfoError,
|
||||
SessionTokenInfoSuccessResponse,
|
||||
SetMediaFileCoverImageError,
|
||||
SetMediaFileCoverImageRequest,
|
||||
SetModelWeightCoverImageError,
|
||||
SetModelWeightCoverImagePathInfo,
|
||||
SetModelWeightCoverImageRequest,
|
||||
SetModelWeightCoverImageResponse,
|
||||
SetTagsForEntityError,
|
||||
SetTagsForEntityPathInfo,
|
||||
SetTagsForEntityRequest,
|
||||
SetTagsForEntitySuccessResponse,
|
||||
SetUserRatingError,
|
||||
SetUserRatingRequest,
|
||||
SetUserRatingResponse,
|
||||
StatusAlertCategory,
|
||||
StatusAlertError,
|
||||
StatusAlertInfo,
|
||||
StatusAlertResponse,
|
||||
StatusDetailsResponse,
|
||||
SubscriptionProductKey,
|
||||
TerminateInferenceJobError,
|
||||
TerminateInferenceJobPathInfo,
|
||||
TerminateInferenceJobSuccessResponse,
|
||||
UpdateWeightError,
|
||||
UpdateWeightPathInfo,
|
||||
UpdateWeightRequest,
|
||||
UploadAudioMediaFileForm,
|
||||
|
||||
+7
-34
@@ -11,6 +11,7 @@ use http_server_common::response::serialize_as_json_error::serialize_as_json_err
|
||||
use mysql_queries::queries::api_tokens::create_api_token::create_api_token_for_user;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -28,41 +29,13 @@ pub struct CreateApiTokenResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum CreateApiTokenError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for CreateApiTokenError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
CreateApiTokenError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
CreateApiTokenError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
CreateApiTokenError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl fmt::Display for CreateApiTokenError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn create_api_token_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<CreateApiTokenRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CreateApiTokenError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -70,20 +43,20 @@ pub async fn create_api_token_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
CreateApiTokenError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(CreateApiTokenError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
if user_session.is_banned {
|
||||
warn!("banned users cannot create API tokens");
|
||||
return Err(CreateApiTokenError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let creator_ip_address = get_request_ip(&http_request);
|
||||
@@ -96,7 +69,7 @@ pub async fn create_api_token_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("API token creation errror: {:?}", e);
|
||||
CreateApiTokenError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
let response = CreateApiTokenResponse {
|
||||
@@ -105,7 +78,7 @@ pub async fn create_api_token_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| CreateApiTokenError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+9
-38
@@ -13,6 +13,7 @@ use mysql_queries::queries::api_tokens::delete_api_token::delete_api_token;
|
||||
use mysql_queries::queries::api_tokens::list_available_api_tokens_for_user::list_available_api_tokens_for_user;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -31,43 +32,13 @@ pub struct DeleteApiTokenResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum DeleteApiTokenError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for DeleteApiTokenError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
DeleteApiTokenError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
DeleteApiTokenError::NotFound => StatusCode::NOT_FOUND,
|
||||
DeleteApiTokenError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
DeleteApiTokenError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for DeleteApiTokenError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn delete_api_token_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<DeleteApiTokenPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, DeleteApiTokenError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -75,20 +46,20 @@ pub async fn delete_api_token_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
DeleteApiTokenError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(DeleteApiTokenError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
if user_session.is_banned {
|
||||
warn!("banned users cannot edit API tokens");
|
||||
return Err(DeleteApiTokenError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let tokens = list_available_api_tokens_for_user(
|
||||
@@ -97,7 +68,7 @@ pub async fn delete_api_token_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Error querying tokens: {:?}", e);
|
||||
DeleteApiTokenError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
let valid_token = tokens.iter()
|
||||
@@ -106,7 +77,7 @@ pub async fn delete_api_token_handler(
|
||||
|
||||
if !valid_token {
|
||||
warn!("Invalid API Token");
|
||||
return Err(DeleteApiTokenError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
}
|
||||
|
||||
let creator_ip_address = get_request_ip(&http_request);
|
||||
@@ -119,7 +90,7 @@ pub async fn delete_api_token_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Error with query: {:?}", e);
|
||||
DeleteApiTokenError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
});
|
||||
|
||||
let response = DeleteApiTokenResponse {
|
||||
@@ -127,7 +98,7 @@ pub async fn delete_api_token_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| DeleteApiTokenError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+9
-38
@@ -12,6 +12,7 @@ use mysql_queries::queries::api_tokens::edit_api_token::edit_api_token;
|
||||
use mysql_queries::queries::api_tokens::list_available_api_tokens_for_user::list_available_api_tokens_for_user;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -32,43 +33,13 @@ pub struct EditApiTokenResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum EditApiTokenError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for EditApiTokenError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
EditApiTokenError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
EditApiTokenError::NotFound => StatusCode::NOT_FOUND,
|
||||
EditApiTokenError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
EditApiTokenError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for EditApiTokenError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn edit_api_token_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<EditApiTokenRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, EditApiTokenError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -76,20 +47,20 @@ pub async fn edit_api_token_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
EditApiTokenError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(EditApiTokenError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
if user_session.is_banned {
|
||||
warn!("banned users cannot edit API tokens");
|
||||
return Err(EditApiTokenError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let tokens = list_available_api_tokens_for_user(
|
||||
@@ -98,7 +69,7 @@ pub async fn edit_api_token_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Error querying tokens: {:?}", e);
|
||||
EditApiTokenError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
let valid_token = tokens.iter()
|
||||
@@ -107,7 +78,7 @@ pub async fn edit_api_token_handler(
|
||||
|
||||
if !valid_token {
|
||||
warn!("Invalid API Token");
|
||||
return Err(EditApiTokenError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
}
|
||||
|
||||
let creator_ip_address = get_request_ip(&http_request);
|
||||
@@ -121,7 +92,7 @@ pub async fn edit_api_token_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Error with query: {:?}", e);
|
||||
EditApiTokenError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
});
|
||||
|
||||
let response = EditApiTokenResponse {
|
||||
@@ -129,7 +100,7 @@ pub async fn edit_api_token_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| EditApiTokenError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+7
-32
@@ -11,6 +11,7 @@ use http_server_common::response::serialize_as_json_error::serialize_as_json_err
|
||||
use mysql_queries::queries::api_tokens::list_available_api_tokens_for_user::list_available_api_tokens_for_user;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Success Response ===============
|
||||
|
||||
@@ -30,38 +31,12 @@ pub struct ApiToken {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum ListApiTokensError {
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ListApiTokensError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListApiTokensError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
ListApiTokensError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ListApiTokensError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn list_api_tokens_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, ListApiTokensError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -69,20 +44,20 @@ pub async fn list_api_tokens_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ListApiTokensError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(ListApiTokensError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
if user_session.is_banned {
|
||||
warn!("banned users cannot use API tokens");
|
||||
return Err(ListApiTokensError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let api_tokens = list_available_api_tokens_for_user(
|
||||
@@ -91,7 +66,7 @@ pub async fn list_api_tokens_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("API token query error: {:?}", e);
|
||||
ListApiTokensError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
let mut api_tokens = api_tokens.into_iter()
|
||||
@@ -111,7 +86,7 @@ pub async fn list_api_tokens_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| ListApiTokensError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+9
-36
@@ -12,6 +12,7 @@ use mysql_queries::queries::model_categories::create_category::{create_category,
|
||||
use tokens::tokens::model_categories::ModelCategoryToken;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
const DEFAULT_CAN_DIRECTLY_HAVE_MODELS : bool = true;
|
||||
const DEFAULT_CAN_HAVE_SUBCATEGORIES : bool = false;
|
||||
@@ -50,41 +51,13 @@ pub struct CreateCategoryResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum CreateCategoryError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for CreateCategoryError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
CreateCategoryError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
CreateCategoryError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
CreateCategoryError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl fmt::Display for CreateCategoryError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn create_category_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<CreateCategoryRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CreateCategoryError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -92,14 +65,14 @@ pub async fn create_category_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
CreateCategoryError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(CreateCategoryError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -109,7 +82,7 @@ pub async fn create_category_handler(
|
||||
|
||||
let model_type = match request.model_type {
|
||||
None => {
|
||||
return Err(CreateCategoryError::BadInput("no model type".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("no model type".to_string()));
|
||||
}
|
||||
Some(ModelType::Tts) => "tts",
|
||||
Some(ModelType::W2l) => "w2l",
|
||||
@@ -117,11 +90,11 @@ pub async fn create_category_handler(
|
||||
|
||||
let idempotency_token = request.idempotency_token
|
||||
.clone()
|
||||
.ok_or(CreateCategoryError::BadInput("no idempotency token provided".to_string()))?;
|
||||
.ok_or(CommonWebError::BadInputWithSimpleMessage("no idempotency token provided".to_string()))?;
|
||||
|
||||
let name = request.name
|
||||
.clone()
|
||||
.ok_or(CreateCategoryError::BadInput("no name provided".to_string()))?;
|
||||
.ok_or(CommonWebError::BadInputWithSimpleMessage("no name provided".to_string()))?;
|
||||
|
||||
let category_token = ModelCategoryToken::generate().to_string();
|
||||
|
||||
@@ -164,7 +137,7 @@ pub async fn create_category_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Create category edit DB error: {:?}", err);
|
||||
return Err(CreateCategoryError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -174,7 +147,7 @@ pub async fn create_category_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| CreateCategoryError::ServerError)?;
|
||||
?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+6
-31
@@ -12,6 +12,7 @@ use http_server_common::response::serialize_as_json_error::serialize_as_json_err
|
||||
use mysql_queries::queries::model_categories::get_category_by_token::get_category_by_token;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -63,39 +64,13 @@ pub struct DisplayCategory {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum GetCategoryError {
|
||||
NotFound,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for GetCategoryError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetCategoryError::NotFound => StatusCode::NOT_FOUND,
|
||||
GetCategoryError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for GetCategoryError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn get_category_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<GetCategoryPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, GetCategoryError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -103,7 +78,7 @@ pub async fn get_category_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
GetCategoryError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
// TODO: We don't have any permissions for categories. This is a proxy.
|
||||
@@ -120,11 +95,11 @@ pub async fn get_category_handler(
|
||||
},
|
||||
Ok(None) => {
|
||||
warn!("could not find category");
|
||||
return Err(GetCategoryError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("error looking up category: {:?}", err);
|
||||
return Err(GetCategoryError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
},
|
||||
};
|
||||
|
||||
@@ -156,7 +131,7 @@ pub async fn get_category_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| GetCategoryError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+4
-33
@@ -3,21 +3,18 @@
|
||||
#![forbid(unused_mut)]
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::error;
|
||||
|
||||
use datetimes::CHRONO_DATETIME_UNIX_EPOCH;
|
||||
use enums::by_table::model_categories::model_type::ModelType;
|
||||
use http_server_common::response::serialize_as_json_error::serialize_as_json_error;
|
||||
use tokens::tokens::model_categories::ModelCategoryToken;
|
||||
|
||||
use crate::configs::static_model::categories::synthetic_category_list::SYNTHETIC_CATEGORY_LIST;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::cached_queries::list_cached_tts_categories_for_public_dropdown::list_cached_tts_categories_for_public_dropdown_db_pool;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
@@ -64,45 +61,19 @@ pub struct DisplayCategory {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum ListTtsCategoriesError {
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ListTtsCategoriesError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListTtsCategoriesError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
ListTtsCategoriesError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ListTtsCategoriesError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn list_tts_categories_handler(
|
||||
_http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, ListTtsCategoriesError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let database_categories = list_cached_tts_categories_for_public_dropdown_db_pool(
|
||||
&server_state.caches.ephemeral.database_tts_category_list, &server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("error querying categories from db/cache: {:?}", e);
|
||||
ListTtsCategoriesError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
// NB: These will be already sorted.
|
||||
@@ -164,7 +135,7 @@ pub async fn list_tts_categories_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| ListTtsCategoriesError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+6
-33
@@ -3,20 +3,17 @@
|
||||
#![forbid(unused_mut)]
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::web::Path;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::warn;
|
||||
|
||||
use http_server_common::response::serialize_as_json_error::serialize_as_json_error;
|
||||
use mysql_queries::queries::tts::tts_category_assignments::list_assigned_tts_categories_query_builder::ListAssignedTtsCategoriesQueryBuilder;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -65,43 +62,19 @@ pub struct DisplayCategory {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum ListTtsModelAssignedCategoriesError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ListTtsModelAssignedCategoriesError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListTtsModelAssignedCategoriesError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ListTtsModelAssignedCategoriesError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn list_tts_model_assigned_categories_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<ListTtsModelAssignedCategoriesPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, ListTtsModelAssignedCategoriesError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let mut mysql_connection = server_state.mysql_pool.acquire()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Could not acquire DB pool: {:?}", e);
|
||||
ListTtsModelAssignedCategoriesError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let maybe_user_session = server_state
|
||||
@@ -110,7 +83,7 @@ pub async fn list_tts_model_assigned_categories_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ListTtsModelAssignedCategoriesError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
// TODO: We don't have any permissions for categories. This is a proxy.
|
||||
@@ -130,7 +103,7 @@ pub async fn list_tts_model_assigned_categories_handler(
|
||||
Ok(results) => results,
|
||||
Err(err) => {
|
||||
warn!("DB error: {:?}", err);
|
||||
return Err(ListTtsModelAssignedCategoriesError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -162,7 +135,7 @@ pub async fn list_tts_model_assigned_categories_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| ListTtsModelAssignedCategoriesError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+8
-38
@@ -15,6 +15,7 @@ use mysql_queries::queries::media_files::get::get_media_file::get_media_file;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
/// For the URL PathInfo
|
||||
@@ -43,45 +44,14 @@ pub struct MediaFileInfo {
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum GetSceneError {
|
||||
ServerError,
|
||||
NotFound,
|
||||
}
|
||||
|
||||
impl ResponseError for GetSceneError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetSceneError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
GetSceneError::NotFound => StatusCode::NOT_FOUND,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
GetSceneError::ServerError => "server error".to_string(),
|
||||
GetSceneError::NotFound => "not found".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for GetSceneError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
path = "/v1/engine/scene/{token}",
|
||||
responses(
|
||||
(status = 200, description = "Found", body = GetSceneSuccessResponse),
|
||||
(status = 404, description = "Not found", body = GetSceneError),
|
||||
(status = 500, description = "Server error", body = GetSceneError),
|
||||
(status = 404, description = "Not found", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("path" = GetScenePathInfo, description = "Path for Request")
|
||||
@@ -90,7 +60,7 @@ impl fmt::Display for GetSceneError {
|
||||
pub async fn get_scene_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<GetScenePathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, GetSceneError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let media_file_token = path.into_inner().token;
|
||||
|
||||
@@ -98,7 +68,7 @@ pub async fn get_scene_handler(
|
||||
false, &server_state).await?;
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| GetSceneError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
@@ -109,7 +79,7 @@ async fn modern_media_file_lookup(
|
||||
media_file_token: &MediaFileToken,
|
||||
show_deleted_results: bool,
|
||||
server_state: &ServerState,
|
||||
) -> Result<GetSceneSuccessResponse, GetSceneError> {
|
||||
) -> Result<GetSceneSuccessResponse, CommonWebError> {
|
||||
|
||||
let result = get_media_file(
|
||||
media_file_token,
|
||||
@@ -120,9 +90,9 @@ async fn modern_media_file_lookup(
|
||||
let result = match result {
|
||||
Err(e) => {
|
||||
warn!("query error: {:?}", e);
|
||||
return Err(GetSceneError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(e));
|
||||
}
|
||||
Ok(None) => return Err(GetSceneError::NotFound),
|
||||
Ok(None) => return Err(CommonWebError::NotFound),
|
||||
Ok(Some(result)) => result,
|
||||
};
|
||||
|
||||
|
||||
+4
-25
@@ -8,6 +8,7 @@ use derive_more::Display;
|
||||
use log::error;
|
||||
|
||||
use crate::http_server::common_responses::user_avatars::default_avatar_color_from_username::default_avatar_color_from_username;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::user_avatars::default_avatar_from_username::default_avatar_from_username;
|
||||
use mysql_queries::queries::public_event_feed::list_public_event_feed_items::list_public_event_feed_items;
|
||||
|
||||
@@ -54,39 +55,17 @@ pub struct ListEventsSuccessResponse {
|
||||
pub success: bool,
|
||||
pub events: Vec<EventRecord>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Display)]
|
||||
pub enum ListEventsError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ListEventsError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListEventsError::ServerError=> StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
ListEventsError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_events_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ListEventsError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
// NB: Since this is publicly exposed, we don't query sensitive data.
|
||||
let events = list_public_event_feed_items(&server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("error querying for event feed events: {:?}", err);
|
||||
ListEventsError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?
|
||||
.into_iter()
|
||||
.map(|event| {
|
||||
@@ -131,7 +110,7 @@ pub async fn list_events_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| ListEventsError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+7
-38
@@ -9,6 +9,7 @@ use chrono::{DateTime, Utc};
|
||||
use log::warn;
|
||||
|
||||
use crate::http_server::session::lookup::user_session_extended::UserSessionExtended;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use enums::by_table::media_uploads::media_upload_type::MediaUploadType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use mysql_queries::queries::media_uploads::reverse_list_user_media_uploads_of_type::reverse_list_user_media_uploads_of_type_with_connection;
|
||||
@@ -48,52 +49,20 @@ pub struct MediaUploadEntry {
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[deprecated(note = "Use `media_files` instead of `media_uploads`.")]
|
||||
#[derive(Debug)]
|
||||
pub enum ListUserMediaUploadsOfTypeError {
|
||||
ServerError,
|
||||
NotAuthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for ListUserMediaUploadsOfTypeError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
Self::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
Self::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
Self::ServerError => "server error".to_string(),
|
||||
Self::NotAuthorized => "not authorized".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ListUserMediaUploadsOfTypeError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
#[deprecated(note = "Use `media_files` instead of `media_uploads`.")]
|
||||
pub async fn list_user_media_uploads_of_type_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<ListUserMediaUploadsOfTypeProfilePathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ListUserMediaUploadsOfTypeError>
|
||||
) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let mut mysql_connection = server_state.mysql_pool
|
||||
.acquire()
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("MySql pool error: {:?}", err);
|
||||
ListUserMediaUploadsOfTypeError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
// ==================== USER SESSION ==================== //
|
||||
@@ -104,12 +73,12 @@ pub async fn list_user_media_uploads_of_type_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ListUserMediaUploadsOfTypeError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_token = match maybe_user_session {
|
||||
None => {
|
||||
return Err(ListUserMediaUploadsOfTypeError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
Some(user_session) => UserToken::new_from_str(&user_session.user_token),
|
||||
};
|
||||
@@ -124,7 +93,7 @@ pub async fn list_user_media_uploads_of_type_handler(
|
||||
Ok(results) => results,
|
||||
Err(e) => {
|
||||
warn!("Query error: {:?}", e);
|
||||
return Err(ListUserMediaUploadsOfTypeError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(e));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -143,7 +112,7 @@ pub async fn list_user_media_uploads_of_type_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| ListUserMediaUploadsOfTypeError::ServerError)?;
|
||||
.map_err(|e| CommonWebError::from_error(e))?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+7
-34
@@ -11,6 +11,7 @@ use http_server_common::response::serialize_as_json_error::serialize_as_json_err
|
||||
use mysql_queries::queries::model_categories::toggle_model_category_soft_delete::{toggle_model_category_soft_delete, ToggleSoftDeleteState};
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -33,42 +34,14 @@ pub struct DeleteCategoryResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum DeleteCategoryError {
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for DeleteCategoryError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
DeleteCategoryError::NotFound => StatusCode::NOT_FOUND,
|
||||
DeleteCategoryError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
DeleteCategoryError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl fmt::Display for DeleteCategoryError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn delete_category_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<DeleteCategoryPathInfo>,
|
||||
request: web::Json<DeleteCategoryRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, DeleteCategoryError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -76,21 +49,21 @@ pub async fn delete_category_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
DeleteCategoryError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(DeleteCategoryError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: We don't have a permission for categories, so we use this as a proxy.
|
||||
if !user_session.can_ban_users {
|
||||
warn!("no permission to delete categories");
|
||||
return Err(DeleteCategoryError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let soft_delete_state = if request.set_delete {
|
||||
@@ -109,7 +82,7 @@ pub async fn delete_category_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Delete/undelete category edit DB error: {:?}", err);
|
||||
return Err(DeleteCategoryError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -118,7 +91,7 @@ pub async fn delete_category_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| DeleteCategoryError::ServerError)?;
|
||||
?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+11
-40
@@ -12,6 +12,7 @@ use mysql_queries::queries::model_categories::get_category_by_token::get_categor
|
||||
use mysql_queries::queries::model_categories::update_model_category::{update_model_category, UpdateModelCategoryArgs};
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -50,44 +51,14 @@ pub struct EditCategoryResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum EditCategoryError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for EditCategoryError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
EditCategoryError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
EditCategoryError::NotFound => StatusCode::NOT_FOUND,
|
||||
EditCategoryError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
EditCategoryError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for EditCategoryError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn edit_category_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<EditCategoryPathInfo>,
|
||||
request: web::Json<EditCategoryRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, EditCategoryError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -95,27 +66,27 @@ pub async fn edit_category_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
EditCategoryError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(EditCategoryError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: We don't have a permission for categories, so we use this as a proxy.
|
||||
if !user_session.can_ban_users {
|
||||
warn!("no permission to edit categories");
|
||||
return Err(EditCategoryError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
// Category tree integrity
|
||||
if let Some(parent_category_token) = request.maybe_super_category_token.as_deref() {
|
||||
if parent_category_token == &path.token {
|
||||
return Err(EditCategoryError::BadInput(
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(
|
||||
"category cannot have itself as a parent".to_string()));
|
||||
}
|
||||
|
||||
@@ -125,14 +96,14 @@ pub async fn edit_category_handler(
|
||||
match parent_category_lookup {
|
||||
Ok(Some(parent_category)) => {
|
||||
if !parent_category.can_have_subcategories {
|
||||
return Err(EditCategoryError::BadInput(
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(
|
||||
"parent category cannot have children".to_string()));
|
||||
}
|
||||
},
|
||||
Ok(None) => return Err(EditCategoryError::NotFound),
|
||||
Ok(None) => return Err(CommonWebError::NotFound),
|
||||
Err(err) => {
|
||||
warn!("Category lookup DB error: {:?}", err);
|
||||
return Err(EditCategoryError::ServerError)
|
||||
return Err(CommonWebError::from_anyhow_error(err))
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -155,7 +126,7 @@ pub async fn edit_category_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Edit category DB error: {:?}", err);
|
||||
return Err(EditCategoryError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -164,7 +135,7 @@ pub async fn edit_category_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| EditCategoryError::ServerError)?;
|
||||
?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+7
-32
@@ -11,6 +11,7 @@ use http_server_common::response::serialize_as_json_error::serialize_as_json_err
|
||||
use mysql_queries::queries::model_categories::list_categories_query_builder::ListCategoriesQueryBuilder;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -70,39 +71,13 @@ pub struct CategoryForModeration {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum ListTtsCategoriesForModerationError {
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ListTtsCategoriesForModerationError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListTtsCategoriesForModerationError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
ListTtsCategoriesForModerationError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ListTtsCategoriesForModerationError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn list_tts_categories_for_moderation_handler(
|
||||
http_request: HttpRequest,
|
||||
query: web::Query<QueryParams>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, ListTtsCategoriesForModerationError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -110,21 +85,21 @@ pub async fn list_tts_categories_for_moderation_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ListTtsCategoriesForModerationError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(ListTtsCategoriesForModerationError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: We don't have a permission for categories, so we use this as a proxy.
|
||||
if !user_session.can_ban_users {
|
||||
warn!("no permission to edit categories");
|
||||
return Err(ListTtsCategoriesForModerationError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
// The objects we'll show or hide
|
||||
@@ -153,7 +128,7 @@ pub async fn list_tts_categories_for_moderation_handler(
|
||||
Ok(results) => results,
|
||||
Err(err) => {
|
||||
warn!("DB error: {:?}", err);
|
||||
return Err(ListTtsCategoriesForModerationError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -192,7 +167,7 @@ pub async fn list_tts_categories_for_moderation_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| ListTtsCategoriesForModerationError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+7
-32
@@ -7,6 +7,7 @@ use log::warn;
|
||||
use mysql_queries::queries::stats::get_on_prem_worker_stats::get_on_prem_worker_stats;
|
||||
|
||||
use crate::http_server::web_utils::serialize_as_json_error::serialize_as_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
const MIN_SAMPLE_SIZE : u32 = 100;
|
||||
@@ -31,38 +32,12 @@ pub struct WorkerMixStats {
|
||||
pub on_prem_count: i64,
|
||||
pub cloud_count: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum GetOnPremWorkerStatsError {
|
||||
ServerError,
|
||||
Unauthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for GetOnPremWorkerStatsError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetOnPremWorkerStatsError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
GetOnPremWorkerStatsError::Unauthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl std::fmt::Display for GetOnPremWorkerStatsError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_on_prem_worker_stats_handler(
|
||||
http_request: HttpRequest,
|
||||
query: Query<QueryFields>,
|
||||
server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<HttpResponse, GetOnPremWorkerStatsError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -70,21 +45,21 @@ pub async fn get_on_prem_worker_stats_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
GetOnPremWorkerStatsError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(GetOnPremWorkerStatsError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Not a good fit for this permission.
|
||||
if !user_session.can_edit_other_users_tts_models {
|
||||
warn!("user is not allowed to edit user tts: {:?}", user_session.user_token);
|
||||
return Err(GetOnPremWorkerStatsError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let sample_size = query.sample_size
|
||||
@@ -97,7 +72,7 @@ pub async fn get_on_prem_worker_stats_handler(
|
||||
)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
GetOnPremWorkerStatsError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
let response = GetOnPremWorkerStatsResponse {
|
||||
@@ -110,7 +85,7 @@ pub async fn get_on_prem_worker_stats_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| GetOnPremWorkerStatsError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+7
-32
@@ -8,6 +8,7 @@ use log::warn;
|
||||
use mysql_queries::queries::stats::get_voice_count_stats::get_voice_count_stats;
|
||||
|
||||
use crate::http_server::web_utils::serialize_as_json_error::serialize_as_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -16,37 +17,11 @@ pub struct GetVoiceCountStatsResponse {
|
||||
pub all_voices_count_including_deleted: i64,
|
||||
pub public_voices_count: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum GetVoiceCountStatsError {
|
||||
ServerError,
|
||||
Unauthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for GetVoiceCountStatsError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetVoiceCountStatsError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
GetVoiceCountStatsError::Unauthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl std::fmt::Display for GetVoiceCountStatsError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_voice_count_stats_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, GetVoiceCountStatsError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -54,27 +29,27 @@ pub async fn get_voice_count_stats_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
GetVoiceCountStatsError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(GetVoiceCountStatsError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Not a good fit for this permission.
|
||||
if !user_session.can_edit_other_users_tts_models {
|
||||
warn!("user is not allowed to edit user tts: {:?}", user_session.user_token);
|
||||
return Err(GetVoiceCountStatsError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let result = get_voice_count_stats(&server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
GetVoiceCountStatsError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
let response = GetVoiceCountStatsResponse {
|
||||
@@ -84,7 +59,7 @@ pub async fn get_voice_count_stats_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| GetVoiceCountStatsError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+7
-40
@@ -9,6 +9,7 @@ use log::warn;
|
||||
use mysql_queries::queries::users::user_roles::list_user_roles::{list_user_roles, UserRoleForList};
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -16,45 +17,11 @@ pub struct ListUserRolesResponse {
|
||||
pub success: bool,
|
||||
pub user_roles: Vec<UserRoleForList>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ListUserRolesError {
|
||||
BadInput(String),
|
||||
ServerError,
|
||||
Unauthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for ListUserRolesError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListUserRolesError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
ListUserRolesError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ListUserRolesError::Unauthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
ListUserRolesError::BadInput(reason) => reason.to_string(),
|
||||
ListUserRolesError::ServerError => "server error".to_string(),
|
||||
ListUserRolesError::Unauthorized => "unauthorized".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ListUserRolesError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_user_roles_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ListUserRolesError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -62,21 +29,21 @@ pub async fn list_user_roles_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ListUserRolesError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(ListUserRolesError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Add new permission for this.
|
||||
if !user_session.can_ban_users {
|
||||
warn!("user is not allowed to view user roles: {:?}", user_session.user_token);
|
||||
return Err(ListUserRolesError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let maybe_user_roles =
|
||||
@@ -86,7 +53,7 @@ pub async fn list_user_roles_handler(
|
||||
Ok(results) => results,
|
||||
Err(e) => {
|
||||
warn!("Error querying user roles: {:?}", e);
|
||||
return Err(ListUserRolesError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(e));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -96,7 +63,7 @@ pub async fn list_user_roles_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| ListUserRolesError::ServerError)?;
|
||||
.map_err(|e| CommonWebError::from_error(e))?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+7
-34
@@ -9,6 +9,7 @@ use log::{error, warn};
|
||||
use mysql_queries::queries::users::user_roles::list_staff::list_staff;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -25,38 +26,10 @@ pub struct StaffRecordForList {
|
||||
pub user_role_slug: String,
|
||||
pub user_role_name: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Display)]
|
||||
pub enum ListStaffError {
|
||||
BadInput(String),
|
||||
ServerError,
|
||||
Unauthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for ListStaffError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListStaffError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
ListStaffError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ListStaffError::Unauthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
ListStaffError::BadInput(reason) => reason.to_string(),
|
||||
ListStaffError::ServerError => "server error".to_string(),
|
||||
ListStaffError::Unauthorized => "unauthorized".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_staff_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ListStaffError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -64,28 +37,28 @@ pub async fn list_staff_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ListStaffError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(ListStaffError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: This is not the correct permission.
|
||||
if !user_session.can_ban_users {
|
||||
warn!("user is not allowed to delete bans: {:?}", user_session.user_token);
|
||||
return Err(ListStaffError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let results = list_staff(&server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("list staff db error: {:?}", err);
|
||||
ListStaffError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?
|
||||
.into_iter()
|
||||
.map(|user| StaffRecordForList {
|
||||
@@ -103,7 +76,7 @@ pub async fn list_staff_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| ListStaffError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+10
-46
@@ -12,6 +12,7 @@ use mysql_queries::queries::users::user_roles::list_user_roles::list_user_roles;
|
||||
use mysql_queries::queries::users::user_roles::set_user_role::set_user_role;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::response_success_helpers::simple_json_success;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
@@ -25,49 +26,12 @@ pub struct SetUserRolePathInfo {
|
||||
pub struct SetUserRoleRequest {
|
||||
user_role_slug: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SetUserRoleError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
NotFound,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for SetUserRoleError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
SetUserRoleError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
SetUserRoleError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
SetUserRoleError::NotFound => StatusCode::NOT_FOUND,
|
||||
SetUserRoleError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
SetUserRoleError::BadInput(reason) => reason.to_string(),
|
||||
SetUserRoleError::NotAuthorized => "unauthorized".to_string(),
|
||||
SetUserRoleError::NotFound => "not found".to_string(),
|
||||
SetUserRoleError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for SetUserRoleError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn set_user_role_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<SetUserRolePathInfo>,
|
||||
request: web::Json<SetUserRoleRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, SetUserRoleError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -75,21 +39,21 @@ pub async fn set_user_role_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
SetUserRoleError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(SetUserRoleError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: This is not the correct permission
|
||||
if !user_session.can_ban_users {
|
||||
warn!("user is not allowed to change user roles: {:?}", user_session.user_token);
|
||||
return Err(SetUserRoleError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
// TODO: This is lazy and inefficient
|
||||
@@ -97,7 +61,7 @@ pub async fn set_user_role_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("error listing roles: {:?}", err);
|
||||
SetUserRoleError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let role_exists = user_roles.into_iter()
|
||||
@@ -105,7 +69,7 @@ pub async fn set_user_role_handler(
|
||||
.is_some();
|
||||
|
||||
if !role_exists {
|
||||
return Err(SetUserRoleError::BadInput("invalid user role".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("invalid user role".to_string()));
|
||||
}
|
||||
|
||||
let user_lookup_result =
|
||||
@@ -113,10 +77,10 @@ pub async fn set_user_role_handler(
|
||||
|
||||
let target_user = match user_lookup_result {
|
||||
Ok(Some(result)) => result,
|
||||
Ok(None) => return Err(SetUserRoleError::NotFound),
|
||||
Ok(None) => return Err(CommonWebError::NotFound),
|
||||
Err(err) => {
|
||||
warn!("lookup error: {:?}", err);
|
||||
return Err(SetUserRoleError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -130,7 +94,7 @@ pub async fn set_user_role_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("unable to update user role: {:?}", err);
|
||||
return Err(SetUserRoleError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+3
-26
@@ -9,6 +9,7 @@ use chrono::{DateTime, Utc};
|
||||
use http_server_common::response::serialize_as_json_error::serialize_as_json_error;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Success Response ===============
|
||||
|
||||
@@ -40,36 +41,12 @@ pub struct AppModelDownloadsResponse {
|
||||
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum AppModelDownloadsError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for AppModelDownloadsError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
AppModelDownloadsError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for AppModelDownloadsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn get_app_model_downloads_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, AppModelDownloadsError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
// TODO: Real news items.
|
||||
|
||||
@@ -95,7 +72,7 @@ pub async fn get_app_model_downloads_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| AppModelDownloadsError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+3
-26
@@ -9,6 +9,7 @@ use chrono::{DateTime, Utc};
|
||||
use http_server_common::response::serialize_as_json_error::serialize_as_json_error;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Success Response ===============
|
||||
|
||||
@@ -37,36 +38,12 @@ pub struct AppNewsResponse {
|
||||
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum AppNewsError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for AppNewsError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
AppNewsError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for AppNewsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn get_app_news_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, AppNewsError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
// TODO: Real news items.
|
||||
|
||||
@@ -97,7 +74,7 @@ pub async fn get_app_news_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| AppNewsError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+4
-27
@@ -10,6 +10,7 @@ use enums::common::payments_namespace::PaymentsNamespace;
|
||||
use http_server_common::response::serialize_as_json_error::serialize_as_json_error;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Success Response ===============
|
||||
|
||||
@@ -53,36 +54,12 @@ pub struct AppFeature {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum AppPlansError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for AppPlansError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
AppPlansError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for AppPlansError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn get_app_plans_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, AppPlansError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user = server_state
|
||||
.session_checker
|
||||
@@ -90,7 +67,7 @@ pub async fn get_app_plans_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
AppPlansError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let unlimited_time = maybe_user
|
||||
@@ -155,7 +132,7 @@ pub async fn get_app_plans_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| AppPlansError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+4
-31
@@ -10,6 +10,7 @@ use http_server_common::request::get_request_ip::get_request_ip;
|
||||
use http_server_common::response::serialize_as_json_error::serialize_as_json_error;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -75,41 +76,13 @@ pub struct PostAppAnalyticsResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum PostAppAnalyticsError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for PostAppAnalyticsError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
PostAppAnalyticsError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
PostAppAnalyticsError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
PostAppAnalyticsError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl fmt::Display for PostAppAnalyticsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn post_app_analytics_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<PostAppAnalyticsRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, PostAppAnalyticsError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -117,7 +90,7 @@ pub async fn post_app_analytics_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
PostAppAnalyticsError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let creator_ip_address = get_request_ip(&http_request);
|
||||
@@ -129,7 +102,7 @@ pub async fn post_app_analytics_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| PostAppAnalyticsError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+6
-40
@@ -3,11 +3,8 @@
|
||||
#![forbid(unused_mut)]
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::web::Path;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
@@ -17,7 +14,7 @@ use enums::common::visibility::Visibility;
|
||||
use enums::common::vocoder_type::VocoderType;
|
||||
use mysql_queries::queries::vocoder::get_vocoder_model::get_vocoder_model_by_token;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
// =============== Request ===============
|
||||
@@ -77,43 +74,12 @@ pub struct VocoderModFields {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GetVocoderError {
|
||||
NotFound,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for GetVocoderError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetVocoderError::NotFound => StatusCode::NOT_FOUND,
|
||||
GetVocoderError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
GetVocoderError::NotFound => "not found".to_string(),
|
||||
GetVocoderError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for GetVocoderError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_vocoder_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<GetVocoderPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, GetVocoderError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let is_moderator = server_state
|
||||
.session_checker
|
||||
@@ -121,7 +87,7 @@ pub async fn get_vocoder_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
GetVocoderError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?
|
||||
.map(|session| {
|
||||
// NB: Since we need to rip out and replace the permissions system,
|
||||
@@ -140,10 +106,10 @@ pub async fn get_vocoder_handler(
|
||||
|
||||
let vocoder = match query_result {
|
||||
Ok(Some(model)) => model,
|
||||
Ok(None) => return Err(GetVocoderError::NotFound),
|
||||
Ok(None) => return Err(CommonWebError::NotFound),
|
||||
Err(e) => {
|
||||
warn!("query error: {:?}", e);
|
||||
return Err(GetVocoderError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(e));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -185,7 +151,7 @@ pub async fn get_vocoder_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| GetVocoderError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+5
-37
@@ -3,11 +3,8 @@
|
||||
#![forbid(unused_mut)]
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::warn;
|
||||
@@ -15,7 +12,7 @@ use log::warn;
|
||||
use enums::common::vocoder_type::VocoderType;
|
||||
use mysql_queries::queries::vocoder::list_vocoder_models::{list_vocoder_models, VocoderModelListItem};
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -53,40 +50,11 @@ pub struct VocoderListItemModFields {
|
||||
pub user_deleted_at: Option<DateTime<Utc>>,
|
||||
pub mod_deleted_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ListVocodersError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ListVocodersError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListVocodersError::ServerError=> StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
ListVocodersError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ListVocodersError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_vocoders_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ListVocodersError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let is_moderator = server_state
|
||||
.session_checker
|
||||
@@ -94,7 +62,7 @@ pub async fn list_vocoders_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ListVocodersError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?
|
||||
.map(|session| {
|
||||
// NB: Since we need to rip out and replace the permissions system,
|
||||
@@ -115,7 +83,7 @@ pub async fn list_vocoders_handler(
|
||||
Ok(results) => results,
|
||||
Err(e) => {
|
||||
warn!("vocoder list query error: {:?}", e);
|
||||
return Err(ListVocodersError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(e));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -156,7 +124,7 @@ pub async fn list_vocoders_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| ListVocodersError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+11
-44
@@ -13,6 +13,7 @@ use mysql_queries::queries::beta_keys::insert_batch_beta_keys::{insert_batch_bet
|
||||
use mysql_queries::queries::users::user_profiles::get_user_profile_by_username::get_user_profile_by_username;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::user_session::require_moderator::{require_moderator, RequireModeratorError, UseDatabase};
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
@@ -37,41 +38,7 @@ pub struct CreateBetaKeysSuccessResponse {
|
||||
pub success: bool,
|
||||
pub beta_keys: Vec<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum CreateBetaKeysError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for CreateBetaKeysError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
CreateBetaKeysError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
CreateBetaKeysError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
CreateBetaKeysError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
CreateBetaKeysError::BadInput(reason) => reason.to_string(),
|
||||
CreateBetaKeysError::NotAuthorized => "unauthorized".to_string(),
|
||||
CreateBetaKeysError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for CreateBetaKeysError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create beta keys in bulk, and possibly assign them to a referrer user.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
@@ -79,9 +46,9 @@ impl fmt::Display for CreateBetaKeysError {
|
||||
path = "/v1/beta_keys/create",
|
||||
responses(
|
||||
(status = 200, description = "Success", body = CreateBetaKeysSuccessResponse),
|
||||
(status = 400, description = "Bad input", body = CreateBetaKeysError),
|
||||
(status = 401, description = "Not authorized", body = CreateBetaKeysError),
|
||||
(status = 500, description = "Server error", body = CreateBetaKeysError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = CreateBetaKeysRequest, description = "Payload for Request"),
|
||||
@@ -91,13 +58,13 @@ pub async fn create_beta_keys_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<CreateBetaKeysRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<HttpResponse, CreateBetaKeysError>
|
||||
) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let user_session = require_moderator(&http_request, &server_state, UseDatabase::GrabNewConnection)
|
||||
.await
|
||||
.map_err(|err| match err {
|
||||
RequireModeratorError::ServerError => CreateBetaKeysError::ServerError,
|
||||
RequireModeratorError::NotAuthorized => CreateBetaKeysError::NotAuthorized,
|
||||
RequireModeratorError::ServerError => CommonWebError::from_error(err),
|
||||
RequireModeratorError::NotAuthorized => CommonWebError::NotAuthorized,
|
||||
})?;
|
||||
|
||||
let mut maybe_referrer_user_token = None;
|
||||
@@ -108,13 +75,13 @@ pub async fn create_beta_keys_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("Error inserting beta keys: {:?}", err);
|
||||
CreateBetaKeysError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let user = match maybe_user {
|
||||
Some(user) => user,
|
||||
None => {
|
||||
return Err(CreateBetaKeysError::BadInput("referrer user not found".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("referrer user not found".to_string()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -136,7 +103,7 @@ pub async fn create_beta_keys_handler(
|
||||
mysql_pool: &server_state.mysql_pool,
|
||||
}).await.map_err(|err| {
|
||||
warn!("Error inserting beta keys: {:?}", err);
|
||||
CreateBetaKeysError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let response = CreateBetaKeysSuccessResponse {
|
||||
@@ -145,7 +112,7 @@ pub async fn create_beta_keys_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| CreateBetaKeysError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+9
-42
@@ -13,6 +13,7 @@ use tokens::tokens::beta_keys::BetaKeyToken;
|
||||
use tokens::tokens::w2l_results::W2lResultToken;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::user_session::require_moderator::{require_moderator, RequireModeratorError, UseDatabase};
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
@@ -33,41 +34,7 @@ pub struct EditBetaKeyDistributedFlagRequest {
|
||||
pub struct EditBetaKeyDistributedFlagSuccessResponse {
|
||||
pub success: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum EditBetaKeyDistributedFlagError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for EditBetaKeyDistributedFlagError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
EditBetaKeyDistributedFlagError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
EditBetaKeyDistributedFlagError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
EditBetaKeyDistributedFlagError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
EditBetaKeyDistributedFlagError::BadInput(reason) => reason.to_string(),
|
||||
EditBetaKeyDistributedFlagError::NotAuthorized => "unauthorized".to_string(),
|
||||
EditBetaKeyDistributedFlagError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for EditBetaKeyDistributedFlagError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Edit the "distributed" flag on a beta key to mark it as shared
|
||||
#[utoipa::path(
|
||||
post,
|
||||
@@ -75,9 +42,9 @@ impl fmt::Display for EditBetaKeyDistributedFlagError {
|
||||
path = "/v1/beta_keys/{token}/distributed",
|
||||
responses(
|
||||
(status = 200, description = "Success", body = EditBetaKeyDistributedFlagSuccessResponse),
|
||||
(status = 400, description = "Bad input", body = EditBetaKeyDistributedFlagError),
|
||||
(status = 401, description = "Not authorized", body = EditBetaKeyDistributedFlagError),
|
||||
(status = 500, description = "Server error", body = EditBetaKeyDistributedFlagError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = EditBetaKeyDistributedFlagRequest, description = "Payload for Request"),
|
||||
@@ -89,20 +56,20 @@ pub async fn edit_beta_key_distributed_flag_handler(
|
||||
request: web::Json<EditBetaKeyDistributedFlagRequest>,
|
||||
path: Path<EditBetaKeyDistributedFlagPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<HttpResponse, EditBetaKeyDistributedFlagError>
|
||||
) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let user_session = require_moderator(&http_request, &server_state, UseDatabase::GrabNewConnection)
|
||||
.await
|
||||
.map_err(|err| match err {
|
||||
RequireModeratorError::ServerError => EditBetaKeyDistributedFlagError::ServerError,
|
||||
RequireModeratorError::NotAuthorized => EditBetaKeyDistributedFlagError::NotAuthorized,
|
||||
RequireModeratorError::ServerError => CommonWebError::from_error(err),
|
||||
RequireModeratorError::NotAuthorized => CommonWebError::NotAuthorized,
|
||||
})?;
|
||||
|
||||
edit_beta_key_distributed_flag(&path.token, request.is_distributed, &server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("Error editing beta key note: {:?}", err);
|
||||
EditBetaKeyDistributedFlagError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let response = EditBetaKeyDistributedFlagSuccessResponse {
|
||||
@@ -110,7 +77,7 @@ pub async fn edit_beta_key_distributed_flag_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| EditBetaKeyDistributedFlagError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+9
-42
@@ -12,6 +12,7 @@ use mysql_queries::queries::beta_keys::edit_beta_key_note::edit_beta_key_note;
|
||||
use tokens::tokens::beta_keys::BetaKeyToken;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::user_session::require_moderator::{require_moderator, RequireModeratorError, UseDatabase};
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
@@ -32,41 +33,7 @@ pub struct EditBetaKeyNoteRequest {
|
||||
pub struct EditBetaKeyNoteSuccessResponse {
|
||||
pub success: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum EditBetaKeyNoteError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for EditBetaKeyNoteError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
EditBetaKeyNoteError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
EditBetaKeyNoteError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
EditBetaKeyNoteError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
EditBetaKeyNoteError::BadInput(reason) => reason.to_string(),
|
||||
EditBetaKeyNoteError::NotAuthorized => "unauthorized".to_string(),
|
||||
EditBetaKeyNoteError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for EditBetaKeyNoteError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Edit or clear a note on a beta key
|
||||
#[utoipa::path(
|
||||
post,
|
||||
@@ -74,9 +41,9 @@ impl fmt::Display for EditBetaKeyNoteError {
|
||||
path = "/v1/beta_keys/{token}/note",
|
||||
responses(
|
||||
(status = 200, description = "Success", body = EditBetaKeyNoteSuccessResponse),
|
||||
(status = 400, description = "Bad input", body = EditBetaKeyNoteError),
|
||||
(status = 401, description = "Not authorized", body = EditBetaKeyNoteError),
|
||||
(status = 500, description = "Server error", body = EditBetaKeyNoteError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = EditBetaKeyNoteRequest, description = "Payload for Request"),
|
||||
@@ -88,13 +55,13 @@ pub async fn edit_beta_key_note_handler(
|
||||
request: web::Json<EditBetaKeyNoteRequest>,
|
||||
path: Path<EditBetaKeyNotePathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<HttpResponse, EditBetaKeyNoteError>
|
||||
) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let user_session = require_moderator(&http_request, &server_state, UseDatabase::GrabNewConnection)
|
||||
.await
|
||||
.map_err(|err| match err {
|
||||
RequireModeratorError::ServerError => EditBetaKeyNoteError::ServerError,
|
||||
RequireModeratorError::NotAuthorized => EditBetaKeyNoteError::NotAuthorized,
|
||||
RequireModeratorError::ServerError => CommonWebError::from_error(err),
|
||||
RequireModeratorError::NotAuthorized => CommonWebError::NotAuthorized,
|
||||
})?;
|
||||
|
||||
let maybe_note = request.note.as_deref()
|
||||
@@ -106,7 +73,7 @@ pub async fn edit_beta_key_note_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("Error editing beta key note: {:?}", err);
|
||||
EditBetaKeyNoteError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let response = EditBetaKeyNoteSuccessResponse {
|
||||
@@ -114,7 +81,7 @@ pub async fn edit_beta_key_note_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| EditBetaKeyNoteError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+10
-33
@@ -15,6 +15,7 @@ use mysql_queries::queries::users::user_profiles::get_user_profile_by_username::
|
||||
use tokens::tokens::beta_keys::BetaKeyToken;
|
||||
|
||||
use crate::http_server::common_responses::pagination_page::PaginationPage;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
|
||||
use crate::http_server::web_utils::user_session::require_user_session::{require_user_session, RequireUserSessionError};
|
||||
use crate::state::server_state::ServerState;
|
||||
@@ -88,30 +89,6 @@ pub struct BetaKeyItem {
|
||||
/// When the key was redeemed (the key will no longer be usable once redeemed)
|
||||
pub maybe_redeemed_at: Option<DateTime<Utc>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum ListBetaKeysError {
|
||||
BadRequest(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ListBetaKeysError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ResponseError for ListBetaKeysError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListBetaKeysError::BadRequest(_)=> StatusCode::BAD_REQUEST,
|
||||
ListBetaKeysError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
ListBetaKeysError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// List beta keys.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
@@ -122,20 +99,20 @@ impl ResponseError for ListBetaKeysError {
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "List Featured Media Files", body = ListBetaKeysSuccessResponse),
|
||||
(status = 401, description = "Not authorized", body = ListBetaKeysError),
|
||||
(status = 500, description = "Server error", body = ListBetaKeysError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
)]
|
||||
pub async fn list_beta_keys_handler(
|
||||
http_request: HttpRequest,
|
||||
query: Query<ListBetaKeysQueryParams>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ListBetaKeysError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
let user_session = require_user_session(&http_request, &server_state)
|
||||
.await
|
||||
.map_err(|err| match err {
|
||||
RequireUserSessionError::ServerError => ListBetaKeysError::ServerError,
|
||||
RequireUserSessionError::NotAuthorized => ListBetaKeysError::NotAuthorized,
|
||||
RequireUserSessionError::ServerError => CommonWebError::from_error(err),
|
||||
RequireUserSessionError::NotAuthorized => CommonWebError::NotAuthorized,
|
||||
})?;
|
||||
|
||||
let mut is_mod = user_session.can_ban_users;
|
||||
@@ -152,11 +129,11 @@ pub async fn list_beta_keys_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("get user profile error: {:?}", e);
|
||||
ListBetaKeysError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
match maybe_referrer_user {
|
||||
None => return Err(ListBetaKeysError::BadRequest("referrer user not found".to_string())),
|
||||
None => return Err(CommonWebError::BadInputWithSimpleMessage("referrer user not found".to_string())),
|
||||
Some(user) => {
|
||||
maybe_scope_user_token = Some(user.user_token.clone());
|
||||
},
|
||||
@@ -193,7 +170,7 @@ pub async fn list_beta_keys_handler(
|
||||
Ok(results) => results,
|
||||
Err(err) => {
|
||||
warn!("Query error: {:?}", err);
|
||||
return Err(ListBetaKeysError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -240,7 +217,7 @@ pub async fn list_beta_keys_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| ListBetaKeysError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+13
-46
@@ -23,6 +23,7 @@ use tokens::tokens::users::UserToken;
|
||||
use tokens::tokens::w2l_templates::W2lTemplateToken;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
@@ -35,41 +36,7 @@ pub struct CreateFeaturedItemRequest {
|
||||
pub struct CreateFeaturedItemSuccessResponse {
|
||||
pub success: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum CreateFeaturedItemError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for CreateFeaturedItemError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
CreateFeaturedItemError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
CreateFeaturedItemError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
CreateFeaturedItemError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
CreateFeaturedItemError::BadInput(reason) => reason.to_string(),
|
||||
CreateFeaturedItemError::NotAuthorized => "unauthorized".to_string(),
|
||||
CreateFeaturedItemError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for CreateFeaturedItemError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a featured item (only mods can do this).
|
||||
#[utoipa::path(
|
||||
post,
|
||||
@@ -78,14 +45,14 @@ impl fmt::Display for CreateFeaturedItemError {
|
||||
request_body = CreateFeaturedItemRequest,
|
||||
responses(
|
||||
(status = 200, body = CreateFeaturedItemSuccessResponse),
|
||||
(status = 400, body = CreateFeaturedItemError),
|
||||
(status = 400, body = CommonWebError),
|
||||
)
|
||||
)]
|
||||
pub async fn create_featured_item_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<CreateFeaturedItemRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<HttpResponse, CreateFeaturedItemError>
|
||||
) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
// NB(bt,2023-12-14): Kasisnu found that we're getting entity type mismatches in production. Apart from
|
||||
// querying the database for entity existence, this is the next best way to prevent incorrect comment
|
||||
@@ -100,7 +67,7 @@ pub async fn create_featured_item_handler(
|
||||
|
||||
if !token_prefix_matches {
|
||||
warn!("invalid token prefix: {:?} for {:?}", request.entity_token, request.entity_type);
|
||||
return Err(CreateFeaturedItemError::BadInput("invalid token prefix".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("invalid token prefix".to_string()));
|
||||
}
|
||||
|
||||
let mut mysql_connection = server_state.mysql_pool
|
||||
@@ -108,7 +75,7 @@ pub async fn create_featured_item_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("MySql pool error: {:?}", err);
|
||||
CreateFeaturedItemError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
let maybe_user_session = server_state
|
||||
@@ -117,14 +84,14 @@ pub async fn create_featured_item_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
CreateFeaturedItemError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(CreateFeaturedItemError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -132,7 +99,7 @@ pub async fn create_featured_item_handler(
|
||||
|
||||
if !is_mod {
|
||||
warn!("not moderator");
|
||||
return Err(CreateFeaturedItemError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let entity = FeaturedItemEntity::from_entity_type_and_token(
|
||||
@@ -141,7 +108,7 @@ pub async fn create_featured_item_handler(
|
||||
let mut transaction = mysql_connection.begin().await
|
||||
.map_err(|err| {
|
||||
error!("error creating transaction: {:?}", err);
|
||||
CreateFeaturedItemError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
match request.entity_type {
|
||||
@@ -155,7 +122,7 @@ pub async fn create_featured_item_handler(
|
||||
|
||||
if let Err(err) = result {
|
||||
warn!("error modifying visibility: {:?}", err);
|
||||
return Err(CreateFeaturedItemError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
}
|
||||
FeaturedItemEntityType::ModelWeight => {} // TODO
|
||||
@@ -170,7 +137,7 @@ pub async fn create_featured_item_handler(
|
||||
|
||||
if let Err(err) = upsert_result {
|
||||
warn!("error setting featured: {:?}", err);
|
||||
return Err(CreateFeaturedItemError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
|
||||
let ip_address = get_request_ip(&http_request);
|
||||
@@ -189,7 +156,7 @@ pub async fn create_featured_item_handler(
|
||||
transaction.commit().await
|
||||
.map_err(|err| {
|
||||
error!("error committing transaction: {:?}", err);
|
||||
CreateFeaturedItemError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
let response = CreateFeaturedItemSuccessResponse {
|
||||
@@ -197,7 +164,7 @@ pub async fn create_featured_item_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| CreateFeaturedItemError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+14
-50
@@ -21,6 +21,7 @@ use tokens::tokens::users::UserToken;
|
||||
|
||||
use artcraft_api_defs::common::responses::simple_generic_json_success::SimpleGenericJsonSuccess;
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::response_success_helpers::simple_json_success;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
@@ -29,44 +30,7 @@ pub struct DeleteFeaturedItemRequest {
|
||||
entity_token: String,
|
||||
entity_type: FeaturedItemEntityType,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum DeleteFeaturedItemError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
NotFound,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for DeleteFeaturedItemError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
DeleteFeaturedItemError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
DeleteFeaturedItemError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
DeleteFeaturedItemError::NotFound => StatusCode::NOT_FOUND,
|
||||
DeleteFeaturedItemError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
DeleteFeaturedItemError::BadInput(reason) => reason.to_string(),
|
||||
DeleteFeaturedItemError::NotAuthorized => "unauthorized".to_string(),
|
||||
DeleteFeaturedItemError::NotFound => "not found".to_string(),
|
||||
DeleteFeaturedItemError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for DeleteFeaturedItemError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove a featured item (only mods can do this).
|
||||
#[utoipa::path(
|
||||
delete,
|
||||
@@ -75,17 +39,17 @@ impl fmt::Display for DeleteFeaturedItemError {
|
||||
request_body = DeleteFeaturedItemRequest,
|
||||
responses(
|
||||
(status = 200, description = "Success", body = SimpleGenericJsonSuccess),
|
||||
(status = 400, description = "Bad input", body = DeleteFeaturedItemError),
|
||||
(status = 401, description = "Not authorized", body = DeleteFeaturedItemError),
|
||||
(status = 404, description = "Not found", body = DeleteFeaturedItemError),
|
||||
(status = 500, description = "Server error", body = DeleteFeaturedItemError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 404, description = "Not found", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
)]
|
||||
pub async fn delete_featured_item_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<DeleteFeaturedItemRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, DeleteFeaturedItemError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
// NB(bt,2023-12-14): Kasisnu found that we're getting entity type mismatches in production. Apart from
|
||||
// querying the database for entity existence, this is the next best way to prevent incorrect comment
|
||||
@@ -100,7 +64,7 @@ pub async fn delete_featured_item_handler(
|
||||
|
||||
if !token_prefix_matches {
|
||||
warn!("invalid token prefix: {:?} for {:?}", request.entity_token, request.entity_type);
|
||||
return Err(DeleteFeaturedItemError::BadInput("invalid token prefix".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("invalid token prefix".to_string()));
|
||||
}
|
||||
|
||||
let mut mysql_connection = server_state.mysql_pool
|
||||
@@ -108,7 +72,7 @@ pub async fn delete_featured_item_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("MySql pool error: {:?}", err);
|
||||
DeleteFeaturedItemError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
let maybe_user_session = server_state
|
||||
@@ -117,13 +81,13 @@ pub async fn delete_featured_item_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
DeleteFeaturedItemError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
return Err(DeleteFeaturedItemError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -131,7 +95,7 @@ pub async fn delete_featured_item_handler(
|
||||
|
||||
if !is_mod {
|
||||
warn!("not moderator");
|
||||
return Err(DeleteFeaturedItemError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let entity = FeaturedItemEntity::from_entity_type_and_token(
|
||||
@@ -140,7 +104,7 @@ pub async fn delete_featured_item_handler(
|
||||
let mut transaction = mysql_connection.begin().await
|
||||
.map_err(|err| {
|
||||
error!("error creating transaction: {:?}", err);
|
||||
DeleteFeaturedItemError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
let delete_result = delete_featured_item(
|
||||
@@ -164,13 +128,13 @@ pub async fn delete_featured_item_handler(
|
||||
transaction.commit().await
|
||||
.map_err(|err| {
|
||||
error!("error committing transaction: {:?}", err);
|
||||
DeleteFeaturedItemError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
match delete_result {
|
||||
Ok(_) => {},
|
||||
Err(_err) => {
|
||||
return Err(DeleteFeaturedItemError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(_err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+5
-38
@@ -17,6 +17,7 @@ use tokens::tokens::users::UserToken;
|
||||
use tokens::tokens::w2l_templates::W2lTemplateToken;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
@@ -30,41 +31,7 @@ pub struct GetIsFeaturedItemSuccessResponse {
|
||||
pub success: bool,
|
||||
pub is_featured: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum GetIsFeaturedItemError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for GetIsFeaturedItemError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetIsFeaturedItemError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
GetIsFeaturedItemError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
GetIsFeaturedItemError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
GetIsFeaturedItemError::BadInput(reason) => reason.to_string(),
|
||||
GetIsFeaturedItemError::NotAuthorized => "unauthorized".to_string(),
|
||||
GetIsFeaturedItemError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for GetIsFeaturedItemError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Determine if an item is featured
|
||||
#[utoipa::path(
|
||||
get,
|
||||
@@ -73,14 +40,14 @@ impl fmt::Display for GetIsFeaturedItemError {
|
||||
request_body = GetIsFeaturedItemPathInfo,
|
||||
responses(
|
||||
(status = 200, body = GetIsFeaturedItemSuccessResponse),
|
||||
(status = 400, body = GetIsFeaturedItemError),
|
||||
(status = 400, body = CommonWebError),
|
||||
)
|
||||
)]
|
||||
pub async fn get_is_featured_item_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<GetIsFeaturedItemPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<Json<GetIsFeaturedItemSuccessResponse>, GetIsFeaturedItemError>
|
||||
) -> Result<Json<GetIsFeaturedItemSuccessResponse>, CommonWebError>
|
||||
{
|
||||
// NB(bt,2023-12-14): Kasisnu found that we're getting entity type mismatches in production. Apart from
|
||||
// querying the database for entity existence, this is the next best way to prevent incorrect comment
|
||||
@@ -95,7 +62,7 @@ pub async fn get_is_featured_item_handler(
|
||||
|
||||
if !token_prefix_matches {
|
||||
warn!("invalid token prefix: {:?} for {:?}", path.entity_token, path.entity_type);
|
||||
return Err(GetIsFeaturedItemError::BadInput("invalid token prefix".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("invalid token prefix".to_string()));
|
||||
}
|
||||
|
||||
let entity = FeaturedItemEntity::from_entity_type_and_token(path.entity_type, &path.entity_token);
|
||||
@@ -104,7 +71,7 @@ pub async fn get_is_featured_item_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("MySql error: {:?}", err);
|
||||
GetIsFeaturedItemError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
Ok(Json(GetIsFeaturedItemSuccessResponse {
|
||||
|
||||
+10
-43
@@ -2,6 +2,7 @@ use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
@@ -58,41 +59,7 @@ pub enum UpdatedJobStatus {
|
||||
pub struct UpdateGptImageJobStatusSuccessResponse {
|
||||
pub success: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum UpdateGptImageJobStatusError {
|
||||
ServerError,
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for UpdateGptImageJobStatusError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
UpdateGptImageJobStatusError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
UpdateGptImageJobStatusError::NotFound => StatusCode::NOT_FOUND,
|
||||
UpdateGptImageJobStatusError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
Self::ServerError => "server error".to_string(),
|
||||
Self::NotFound => "not found".to_string(),
|
||||
Self::NotAuthorized => "unauthorized".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for UpdateGptImageJobStatusError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// [INTERNAL ENDPOINT] Update a GPT Image generation job status.
|
||||
/// This is called by our internal infra, not users. Keep it guarded.
|
||||
/// We can do secrets-based auth later.
|
||||
@@ -102,7 +69,7 @@ impl fmt::Display for UpdateGptImageJobStatusError {
|
||||
path = "/v1/image_studio/update_job_status",
|
||||
responses(
|
||||
(status = 200, body = UpdateGptImageJobStatusSuccessResponse),
|
||||
(status = 500, body = UpdateGptImageJobStatusError),
|
||||
(status = 500, body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = UpdateGptImageJobStatusRequest, description = "Request"),
|
||||
@@ -111,14 +78,14 @@ impl fmt::Display for UpdateGptImageJobStatusError {
|
||||
pub async fn update_gpt_image_job_status_handler(
|
||||
http_request: HttpRequest,
|
||||
request: Json<UpdateGptImageJobStatusRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<Json<UpdateGptImageJobStatusSuccessResponse>, UpdateGptImageJobStatusError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<Json<UpdateGptImageJobStatusSuccessResponse>, CommonWebError>
|
||||
{
|
||||
//// TODO(bt,2024-06-16): Reuse connection
|
||||
//let mut mysql_connection = server_state.mysql_pool.acquire()
|
||||
// .await
|
||||
// .map_err(|e| {
|
||||
// warn!("Could not acquire DB pool: {:?}", e);
|
||||
// UpdateGptImageJobStatusError::ServerError
|
||||
// CommonWebError::from_error(e)
|
||||
// })?;
|
||||
|
||||
let inference_job = get_inference_job_status(
|
||||
@@ -128,10 +95,10 @@ pub async fn update_gpt_image_job_status_handler(
|
||||
|
||||
let inference_job = match inference_job {
|
||||
Ok(Some(record)) => record,
|
||||
Ok(None) => return Err(UpdateGptImageJobStatusError::NotFound),
|
||||
Ok(None) => return Err(CommonWebError::NotFound),
|
||||
Err(err) => {
|
||||
error!("tts job query error: {:?}", err);
|
||||
return Err(UpdateGptImageJobStatusError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -142,10 +109,10 @@ pub async fn update_gpt_image_job_status_handler(
|
||||
return Ok(Json(UpdateGptImageJobStatusSuccessResponse { success: true }))
|
||||
},
|
||||
// TODO: Handle other states as terminal states?
|
||||
//JobStatusPlus::CompleteFailure => return Err(UpdateGptImageJobStatusError::ServerError),
|
||||
//JobStatusPlus::CompleteFailure => return Err(CommonWebError::from_error(err)),
|
||||
//JobStatusPlus::AttemptFailed => {}
|
||||
//JobStatusPlus::Dead => {}
|
||||
//JobStatusPlus::CancelledByUser => return Err(UpdateGptImageJobStatusError::ServerError),
|
||||
//JobStatusPlus::CancelledByUser => return Err(CommonWebError::from_error(err)),
|
||||
//JobStatusPlus::CancelledBySystem => {}
|
||||
_ => {} // Intentional fall through.
|
||||
}
|
||||
@@ -170,7 +137,7 @@ pub async fn update_gpt_image_job_status_handler(
|
||||
Ok(media_token) => media_token,
|
||||
Err(err) => {
|
||||
error!("Error uploading image: {:?}", err);
|
||||
return Err(UpdateGptImageJobStatusError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -182,7 +149,7 @@ pub async fn update_gpt_image_job_status_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("Error updating job: {:?}", err);
|
||||
UpdateGptImageJobStatusError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
info!("Job record updated for job: {:?}", request.job_token);
|
||||
|
||||
+7
-36
@@ -14,6 +14,7 @@ use mysql_queries::queries::generic_inference::web::kill_generic_inference_jobs;
|
||||
use mysql_queries::queries::generic_inference::web::kill_generic_inference_jobs::{kill_generic_inference_jobs, KillGenericInferenceJobsArgs};
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
/// Only certain job statuses should be modified.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Deserialize)]
|
||||
@@ -46,43 +47,13 @@ pub struct KillInferenceJobsRequest {
|
||||
pub struct KillInferenceJobsResponse {
|
||||
pub success: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum KillInferenceJobsError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for KillInferenceJobsError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
KillInferenceJobsError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
KillInferenceJobsError::NotFound => StatusCode::NOT_FOUND,
|
||||
KillInferenceJobsError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
KillInferenceJobsError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for KillInferenceJobsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn kill_generic_inference_jobs_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<KillInferenceJobsRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, KillInferenceJobsError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -90,21 +61,21 @@ pub async fn kill_generic_inference_jobs_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
KillInferenceJobsError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(KillInferenceJobsError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: We don't have a permission for this, so use this as a proxy permission
|
||||
if !user_session.can_ban_users {
|
||||
warn!("no permission to edit categories");
|
||||
return Err(KillInferenceJobsError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let job_statuses = request.job_statuses.iter()
|
||||
@@ -128,7 +99,7 @@ pub async fn kill_generic_inference_jobs_handler(
|
||||
mysql_pool: &server_state.mysql_pool,
|
||||
}).await.map_err(|err| {
|
||||
warn!("Query Error: {:?}", err);
|
||||
KillInferenceJobsError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let response = KillInferenceJobsResponse {
|
||||
@@ -136,7 +107,7 @@ pub async fn kill_generic_inference_jobs_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| KillInferenceJobsError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+11
-44
@@ -14,6 +14,7 @@ use mysql_queries::queries::generic_inference::web::mark_generic_inference_job_c
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
/// For the URL PathInfo
|
||||
@@ -26,41 +27,7 @@ pub struct TerminateInferenceJobPathInfo {
|
||||
pub struct TerminateInferenceJobSuccessResponse {
|
||||
pub success: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum TerminateInferenceJobError {
|
||||
ServerError,
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for TerminateInferenceJobError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
TerminateInferenceJobError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
TerminateInferenceJobError::NotFound => StatusCode::NOT_FOUND,
|
||||
TerminateInferenceJobError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
Self::ServerError => "server error".to_string(),
|
||||
Self::NotFound => "not found".to_string(),
|
||||
Self::NotAuthorized => "unauthorized".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for TerminateInferenceJobError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Terminate a job for the user.
|
||||
///
|
||||
/// The user must own the job. This works for logged in users as well as logged out users
|
||||
@@ -74,19 +41,19 @@ impl fmt::Display for TerminateInferenceJobError {
|
||||
),
|
||||
responses(
|
||||
(status = 200, body = TerminateInferenceJobSuccessResponse),
|
||||
(status = 500, body = TerminateInferenceJobError),
|
||||
(status = 500, body = CommonWebError),
|
||||
),
|
||||
)]
|
||||
pub async fn terminate_inference_job_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<TerminateInferenceJobPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, TerminateInferenceJobError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let mut mysql_connection = server_state.mysql_pool.acquire()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Could not acquire DB pool: {:?}", e);
|
||||
TerminateInferenceJobError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let maybe_user_session = server_state
|
||||
@@ -95,7 +62,7 @@ pub async fn terminate_inference_job_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
TerminateInferenceJobError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let maybe_status = get_inference_job_status_from_connection(
|
||||
@@ -103,10 +70,10 @@ pub async fn terminate_inference_job_handler(
|
||||
|
||||
let job_status = match maybe_status {
|
||||
Ok(Some(record)) => record,
|
||||
Ok(None) => return Err(TerminateInferenceJobError::NotFound),
|
||||
Ok(None) => return Err(CommonWebError::NotFound),
|
||||
Err(err) => {
|
||||
error!("tts job query error: {:?}", err);
|
||||
return Err(TerminateInferenceJobError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -117,13 +84,13 @@ pub async fn terminate_inference_job_handler(
|
||||
|
||||
if let Some((session_user_token, job_user_token)) = maybe_user_tokens {
|
||||
if session_user_token != job_user_token {
|
||||
return Err(TerminateInferenceJobError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
} else {
|
||||
let ip_address = get_request_ip(&http_request);
|
||||
if ip_address != job_status.user_details.creator_ip_address {
|
||||
// TODO(bt,2023-10-24): Allow if anonymous visitor token cookie matches
|
||||
return Err(TerminateInferenceJobError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +98,7 @@ pub async fn terminate_inference_job_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("tts job query error: {:?}", err);
|
||||
TerminateInferenceJobError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let response = TerminateInferenceJobSuccessResponse {
|
||||
@@ -141,7 +108,7 @@ pub async fn terminate_inference_job_handler(
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| {
|
||||
error!("error returning response: {:?}", e);
|
||||
TerminateInferenceJobError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
|
||||
+12
-41
@@ -15,6 +15,7 @@ use mysql_queries::queries::media_files::edit::update_media_file_animation_type:
|
||||
use mysql_queries::queries::media_files::get::get_media_file::get_media_file;
|
||||
|
||||
use crate::http_server::common_requests::media_file_token_path_info::MediaFileTokenPathInfo;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::simple_response::SimpleResponse;
|
||||
use crate::http_server::web_utils::user_session::require_user_session::require_user_session;
|
||||
use crate::state::server_state::ServerState;
|
||||
@@ -27,37 +28,7 @@ pub struct ChangeMediaFileAnimationTypeRequest {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub enum ChangeMediaFileAnimationTypeError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ChangeMediaFileAnimationTypeError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ChangeMediaFileAnimationTypeError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
ChangeMediaFileAnimationTypeError::NotFound => StatusCode::NOT_FOUND,
|
||||
ChangeMediaFileAnimationTypeError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
ChangeMediaFileAnimationTypeError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ChangeMediaFileAnimationTypeError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
/// Change the animation type for a media file.
|
||||
@@ -69,9 +40,9 @@ impl fmt::Display for ChangeMediaFileAnimationTypeError {
|
||||
path = "/v1/media_files/animation_type/{token}",
|
||||
responses(
|
||||
(status = 200, description = "Success", body = SimpleResponse),
|
||||
(status = 400, description = "Bad input", body = ChangeMediaFileAnimationTypeError),
|
||||
(status = 401, description = "Not authorized", body = ChangeMediaFileAnimationTypeError),
|
||||
(status = 500, description = "Server error", body = ChangeMediaFileAnimationTypeError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = ChangeMediaFileAnimationTypeRequest, description = "Payload for Request"),
|
||||
@@ -83,13 +54,13 @@ pub async fn change_media_file_animation_type_handler(
|
||||
path: Path<MediaFileTokenPathInfo>,
|
||||
request: Json<ChangeMediaFileAnimationTypeRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<Json<SimpleResponse>, ChangeMediaFileAnimationTypeError> {
|
||||
) -> Result<Json<SimpleResponse>, CommonWebError> {
|
||||
|
||||
let user_session = require_user_session(&http_request, &server_state)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Not authorized: {:?}", e);
|
||||
ChangeMediaFileAnimationTypeError::NotAuthorized
|
||||
CommonWebError::NotAuthorized
|
||||
})?;
|
||||
|
||||
let media_file_token = path.token.clone();
|
||||
@@ -105,11 +76,11 @@ pub async fn change_media_file_animation_type_handler(
|
||||
Ok(Some(media_file)) => media_file,
|
||||
Ok(None) => {
|
||||
warn!("MediaFile not found: {:?}", media_file_token);
|
||||
return Err(ChangeMediaFileAnimationTypeError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up media_file: {:?}", err);
|
||||
return Err(ChangeMediaFileAnimationTypeError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -120,7 +91,7 @@ pub async fn change_media_file_animation_type_handler(
|
||||
Some(MediaFileEngineCategory::Character) => {}
|
||||
// Everything else is disallowed
|
||||
_ => {
|
||||
return Err(ChangeMediaFileAnimationTypeError::BadInput(
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(
|
||||
"this media file engine category does not support animation".to_string()));
|
||||
}
|
||||
}
|
||||
@@ -128,7 +99,7 @@ pub async fn change_media_file_animation_type_handler(
|
||||
if request.maybe_animation_type.is_none()
|
||||
&& media_file.maybe_engine_category != Some(MediaFileEngineCategory::Character)
|
||||
{
|
||||
return Err(ChangeMediaFileAnimationTypeError::BadInput(
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(
|
||||
"animation type can only be cleared for character types".to_string()));
|
||||
}
|
||||
|
||||
@@ -137,7 +108,7 @@ pub async fn change_media_file_animation_type_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to edit this media_file: {:?}", user_session.user_token);
|
||||
return Err(ChangeMediaFileAnimationTypeError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let query_result = update_media_file_animation_type(
|
||||
@@ -150,7 +121,7 @@ pub async fn change_media_file_animation_type_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Update MediaFile DB error: {:?}", err);
|
||||
return Err(ChangeMediaFileAnimationTypeError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+13
-42
@@ -14,6 +14,7 @@ use mysql_queries::queries::media_files::edit::update_media_file_engine_category
|
||||
use mysql_queries::queries::media_files::get::get_media_file::get_media_file;
|
||||
|
||||
use crate::http_server::common_requests::media_file_token_path_info::MediaFileTokenPathInfo;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::simple_response::SimpleResponse;
|
||||
use crate::http_server::web_utils::user_session::require_user_session::require_user_session;
|
||||
use crate::state::server_state::ServerState;
|
||||
@@ -24,37 +25,7 @@ pub struct ChangeMediaFileEngineCategoryRequest {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub enum ChangeMediaFileEngineCategoryError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ChangeMediaFileEngineCategoryError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ChangeMediaFileEngineCategoryError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
ChangeMediaFileEngineCategoryError::NotFound => StatusCode::NOT_FOUND,
|
||||
ChangeMediaFileEngineCategoryError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
ChangeMediaFileEngineCategoryError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ChangeMediaFileEngineCategoryError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
/// Change the engine category of a media file.
|
||||
@@ -66,9 +37,9 @@ impl fmt::Display for ChangeMediaFileEngineCategoryError {
|
||||
path = "/v1/media_files/engine_category/{token}",
|
||||
responses(
|
||||
(status = 200, description = "Success", body = SimpleResponse),
|
||||
(status = 400, description = "Bad input", body = ChangeMediaFileEngineCategoryError),
|
||||
(status = 401, description = "Not authorized", body = ChangeMediaFileEngineCategoryError),
|
||||
(status = 500, description = "Server error", body = ChangeMediaFileEngineCategoryError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = ChangeMediaFileEngineCategoryRequest, description = "Payload for Request"),
|
||||
@@ -80,13 +51,13 @@ pub async fn change_media_file_engine_category_handler(
|
||||
path: Path<MediaFileTokenPathInfo>,
|
||||
request: Json<ChangeMediaFileEngineCategoryRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<Json<SimpleResponse>, ChangeMediaFileEngineCategoryError> {
|
||||
) -> Result<Json<SimpleResponse>, CommonWebError> {
|
||||
|
||||
let user_session = require_user_session(&http_request, &server_state)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Not authorized: {:?}", e);
|
||||
ChangeMediaFileEngineCategoryError::NotAuthorized
|
||||
CommonWebError::NotAuthorized
|
||||
})?;
|
||||
|
||||
let media_file_token = path.token.clone();
|
||||
@@ -102,28 +73,28 @@ pub async fn change_media_file_engine_category_handler(
|
||||
Ok(Some(media_file)) => media_file,
|
||||
Ok(None) => {
|
||||
warn!("MediaFile not found: {:?}", media_file_token);
|
||||
return Err(ChangeMediaFileEngineCategoryError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up media_file: {:?}", err);
|
||||
return Err(ChangeMediaFileEngineCategoryError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
match media_file.maybe_engine_category {
|
||||
None => return Err(ChangeMediaFileEngineCategoryError::BadInput(
|
||||
None => return Err(CommonWebError::BadInputWithSimpleMessage(
|
||||
"No engine category on existing object".to_string())),
|
||||
|
||||
Some(existing_category) => {
|
||||
if !is_valid_transition(existing_category) {
|
||||
return Err(ChangeMediaFileEngineCategoryError::BadInput(
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(
|
||||
format!("Invalid engine category on existing object: {:?}", existing_category)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !is_valid_transition(request.engine_category) {
|
||||
return Err(ChangeMediaFileEngineCategoryError::BadInput(
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(
|
||||
format!("Invalid engine category: {:?}", request.engine_category)));
|
||||
}
|
||||
|
||||
@@ -132,7 +103,7 @@ pub async fn change_media_file_engine_category_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to edit this media_file: {:?}", user_session.user_token);
|
||||
return Err(ChangeMediaFileEngineCategoryError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let query_result = update_media_file_engine_category(
|
||||
@@ -145,7 +116,7 @@ pub async fn change_media_file_engine_category_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Update MediaFile DB error: {:?}", err);
|
||||
return Err(ChangeMediaFileEngineCategoryError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+12
-41
@@ -16,6 +16,7 @@ use mysql_queries::queries::media_files::edit::update_media_file_visibility::{up
|
||||
use mysql_queries::queries::media_files::get::get_media_file::get_media_file;
|
||||
|
||||
use crate::http_server::common_requests::media_file_token_path_info::MediaFileTokenPathInfo;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
@@ -24,37 +25,7 @@ pub struct ChangeMediaFileVisibilityRequest {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub enum ChangeMediaFileVisibilityError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ChangeMediaFileVisibilityError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ChangeMediaFileVisibilityError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
ChangeMediaFileVisibilityError::NotFound => StatusCode::NOT_FOUND,
|
||||
ChangeMediaFileVisibilityError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
ChangeMediaFileVisibilityError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ChangeMediaFileVisibilityError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
/// Change the visibility (public, hidden, private) of a media file.
|
||||
@@ -64,9 +35,9 @@ impl fmt::Display for ChangeMediaFileVisibilityError {
|
||||
path = "/v1/media_files/visibility/{token}",
|
||||
responses(
|
||||
(status = 200, description = "Success", body = SimpleGenericJsonSuccess),
|
||||
(status = 400, description = "Bad input", body = ChangeMediaFileVisibilityError),
|
||||
(status = 401, description = "Not authorized", body = ChangeMediaFileVisibilityError),
|
||||
(status = 500, description = "Server error", body = ChangeMediaFileVisibilityError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = ChangeMediaFileVisibilityRequest, description = "Payload for Request"),
|
||||
@@ -77,7 +48,7 @@ pub async fn change_media_file_visibility_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<MediaFileTokenPathInfo>,
|
||||
request: web::Json<ChangeMediaFileVisibilityRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, ChangeMediaFileVisibilityError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -85,14 +56,14 @@ pub async fn change_media_file_visibility_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ChangeMediaFileVisibilityError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(ChangeMediaFileVisibilityError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -109,11 +80,11 @@ pub async fn change_media_file_visibility_handler(
|
||||
Ok(Some(media_file)) => media_file,
|
||||
Ok(None) => {
|
||||
warn!("MediaFile not found: {:?}", media_file_token);
|
||||
return Err(ChangeMediaFileVisibilityError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up media_file: {:?}", err);
|
||||
return Err(ChangeMediaFileVisibilityError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -122,7 +93,7 @@ pub async fn change_media_file_visibility_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to edit this media_file: {:?}", user_session.user_token);
|
||||
return Err(ChangeMediaFileVisibilityError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let mut creator_set_visibility = Visibility::Public;
|
||||
@@ -130,7 +101,7 @@ pub async fn change_media_file_visibility_handler(
|
||||
|
||||
if let Some(visibility) = request.creator_set_visibility.as_deref() {
|
||||
creator_set_visibility = Visibility::from_str(visibility)
|
||||
.map_err(|_| ChangeMediaFileVisibilityError::BadInput("bad record visibility".to_string()))?;
|
||||
.map_err(|_| CommonWebError::BadInputWithSimpleMessage("bad record visibility".to_string()))?;
|
||||
}
|
||||
|
||||
let ip_address = get_request_ip(&http_request);
|
||||
@@ -152,7 +123,7 @@ pub async fn change_media_file_visibility_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Update MediaFile DB error: {:?}", err);
|
||||
return Err(ChangeMediaFileVisibilityError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+11
-40
@@ -9,6 +9,7 @@ use log::warn;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::http_server::common_requests::media_file_token_path_info::MediaFileTokenPathInfo;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use artcraft_api_defs::common::responses::simple_generic_json_success::SimpleGenericJsonSuccess;
|
||||
use crate::http_server::web_utils::response_success_helpers::simple_json_success;
|
||||
use crate::state::server_state::ServerState;
|
||||
@@ -24,37 +25,7 @@ pub struct RenameMediaFileRequest {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub enum RenameMediaFileError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for RenameMediaFileError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
RenameMediaFileError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
RenameMediaFileError::NotFound => StatusCode::NOT_FOUND,
|
||||
RenameMediaFileError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
RenameMediaFileError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for RenameMediaFileError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
/// Change (or remove) the "title" of a media file.
|
||||
@@ -64,9 +35,9 @@ impl fmt::Display for RenameMediaFileError {
|
||||
path = "/v1/media_files/rename/{token}",
|
||||
responses(
|
||||
(status = 200, description = "Success", body = SimpleGenericJsonSuccess),
|
||||
(status = 400, description = "Bad input", body = RenameMediaFileError),
|
||||
(status = 401, description = "Not authorized", body = RenameMediaFileError),
|
||||
(status = 500, description = "Server error", body = RenameMediaFileError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = RenameMediaFileRequest, description = "Payload for Request"),
|
||||
@@ -78,21 +49,21 @@ pub async fn rename_media_file_handler(
|
||||
path: Path<MediaFileTokenPathInfo>,
|
||||
request: web::Json<RenameMediaFileRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, RenameMediaFileError>{
|
||||
) -> Result<HttpResponse, CommonWebError>{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
.maybe_get_user_session(&http_request, &server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
RenameMediaFileError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(RenameMediaFileError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -108,11 +79,11 @@ pub async fn rename_media_file_handler(
|
||||
Ok(Some(media_file)) => media_file,
|
||||
Ok(None) => {
|
||||
warn!("MediaFile not found: {:?}", path.token);
|
||||
return Err(RenameMediaFileError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up media_file: {:?}", err);
|
||||
return Err(RenameMediaFileError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -121,7 +92,7 @@ pub async fn rename_media_file_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to delete this media_file: {:?}", user_session.user_token);
|
||||
return Err(RenameMediaFileError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
rename_media_file(
|
||||
@@ -130,7 +101,7 @@ pub async fn rename_media_file_handler(
|
||||
&server_state.mysql_pool
|
||||
).await.map_err(|err| {
|
||||
warn!("Error renaming media_file: {:?}", err);
|
||||
RenameMediaFileError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
Ok(simple_json_success())
|
||||
|
||||
+14
-43
@@ -15,6 +15,7 @@ use mysql_queries::queries::media_files::get::get_media_file::get_media_file;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
|
||||
use crate::http_server::common_requests::media_file_token_path_info::MediaFileTokenPathInfo;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use artcraft_api_defs::common::responses::simple_generic_json_success::SimpleGenericJsonSuccess;
|
||||
use crate::http_server::web_utils::response_success_helpers::simple_json_success;
|
||||
use crate::state::server_state::ServerState;
|
||||
@@ -27,37 +28,7 @@ pub struct SetMediaFileCoverImageRequest {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub enum SetMediaFileCoverImageError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for SetMediaFileCoverImageError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
SetMediaFileCoverImageError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
SetMediaFileCoverImageError::NotFound => StatusCode::NOT_FOUND,
|
||||
SetMediaFileCoverImageError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
SetMediaFileCoverImageError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for SetMediaFileCoverImageError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
/// Set or remove the "cover image" (which are used as thumbnails) on a file.
|
||||
@@ -70,9 +41,9 @@ impl fmt::Display for SetMediaFileCoverImageError {
|
||||
path = "/v1/media_files/cover_image/{token}",
|
||||
responses(
|
||||
(status = 200, description = "Success Delete", body = SimpleGenericJsonSuccess),
|
||||
(status = 400, description = "Bad input", body = SetMediaFileCoverImageError),
|
||||
(status = 401, description = "Not authorized", body = SetMediaFileCoverImageError),
|
||||
(status = 500, description = "Server error", body = SetMediaFileCoverImageError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = SetMediaFileCoverImageRequest, description = "Payload for Request"),
|
||||
@@ -84,21 +55,21 @@ pub async fn set_media_file_cover_image_handler(
|
||||
path: Path<MediaFileTokenPathInfo>,
|
||||
request: web::Json<SetMediaFileCoverImageRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, SetMediaFileCoverImageError>{
|
||||
) -> Result<HttpResponse, CommonWebError>{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
.maybe_get_user_session(&http_request, &server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
SetMediaFileCoverImageError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(SetMediaFileCoverImageError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -114,11 +85,11 @@ pub async fn set_media_file_cover_image_handler(
|
||||
Ok(Some(media_file)) => media_file,
|
||||
Ok(None) => {
|
||||
warn!("MediaFile not found: {:?}", path.token);
|
||||
return Err(SetMediaFileCoverImageError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up media_file: {:?}", err);
|
||||
return Err(SetMediaFileCoverImageError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -127,7 +98,7 @@ pub async fn set_media_file_cover_image_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to delete this media_file: {:?}", user_session.user_token);
|
||||
return Err(SetMediaFileCoverImageError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let mut maybe_set_media_file_token = None;
|
||||
@@ -151,11 +122,11 @@ pub async fn set_media_file_cover_image_handler(
|
||||
Ok(Some(media_file)) => media_file,
|
||||
Ok(None) => {
|
||||
warn!("Media file not found: {:?}", media_file_token);
|
||||
return Err(SetMediaFileCoverImageError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up model_weights : {:?}", err);
|
||||
return Err(SetMediaFileCoverImageError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -165,7 +136,7 @@ pub async fn set_media_file_cover_image_handler(
|
||||
let can_use_image = media_file.media_type == MediaFileType::Image;
|
||||
|
||||
if !can_use_image {
|
||||
return Err(SetMediaFileCoverImageError::BadInput("Invalid media file token.".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("Invalid media file token.".to_string()));
|
||||
}
|
||||
|
||||
maybe_set_media_file_token = Some(media_file.token);
|
||||
@@ -182,7 +153,7 @@ pub async fn set_media_file_cover_image_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Update MediaFile DB error: {:?}", err);
|
||||
return Err(SetMediaFileCoverImageError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+9
-38
@@ -16,6 +16,7 @@ use mysql_queries::queries::media_files::get::get_media_file::get_media_file;
|
||||
use tokens::tokens::media_files::MediaFileToken;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct UpdateMediaFileRequest {
|
||||
@@ -34,44 +35,14 @@ pub struct UpdateMediaFilePathInfo {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum UpdateMediaFileError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for UpdateMediaFileError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
UpdateMediaFileError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
UpdateMediaFileError::NotFound => StatusCode::NOT_FOUND,
|
||||
UpdateMediaFileError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
UpdateMediaFileError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for UpdateMediaFileError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn update_media_file_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<UpdateMediaFilePathInfo>,
|
||||
request: web::Json<UpdateMediaFileRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, UpdateMediaFileError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -79,14 +50,14 @@ pub async fn update_media_file_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
UpdateMediaFileError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(UpdateMediaFileError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -103,11 +74,11 @@ pub async fn update_media_file_handler(
|
||||
Ok(Some(media_file)) => media_file,
|
||||
Ok(None) => {
|
||||
warn!("MediaFile not found: {:?}", media_file_token);
|
||||
return Err(UpdateMediaFileError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up media_file: {:?}", err);
|
||||
return Err(UpdateMediaFileError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -116,7 +87,7 @@ pub async fn update_media_file_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to edit this media_file: {:?}", user_session.user_token);
|
||||
return Err(UpdateMediaFileError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let mut creator_set_visibility = Visibility::Public;
|
||||
@@ -124,7 +95,7 @@ pub async fn update_media_file_handler(
|
||||
|
||||
if let Some(visibility) = request.creator_set_visibility.as_deref() {
|
||||
creator_set_visibility = Visibility::from_str(visibility)
|
||||
.map_err(|_| UpdateMediaFileError::BadInput("bad record visibility".to_string()))?;
|
||||
.map_err(|_| CommonWebError::BadInputWithSimpleMessage("bad record visibility".to_string()))?;
|
||||
}
|
||||
|
||||
let ip_address = get_request_ip(&http_request);
|
||||
@@ -146,7 +117,7 @@ pub async fn update_media_file_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Update MediaFile DB error: {:?}", err);
|
||||
return Err(UpdateMediaFileError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+4
-34
@@ -18,6 +18,7 @@ use tokens::tokens::media_files::MediaFileToken;
|
||||
use utoipa::{IntoParams, ToSchema};
|
||||
|
||||
use crate::http_server::common_responses::media::media_file_cover_image_details::MediaFileCoverImageDetails;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::media::media_links_builder::MediaLinksBuilder;
|
||||
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_media_domain::get_media_domain;
|
||||
@@ -143,37 +144,6 @@ pub struct SearchFeaturedMediaFileListItem {
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum SearchFeaturedMediaFilesError {
|
||||
ServerError,
|
||||
NotAuthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for SearchFeaturedMediaFilesError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
SearchFeaturedMediaFilesError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
SearchFeaturedMediaFilesError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
SearchFeaturedMediaFilesError::ServerError => "server error".to_string(),
|
||||
SearchFeaturedMediaFilesError::NotAuthorized => "not authorized".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for SearchFeaturedMediaFilesError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Search for featured media files based on various criteria.
|
||||
#[utoipa::path(
|
||||
get,
|
||||
@@ -182,14 +152,14 @@ impl std::fmt::Display for SearchFeaturedMediaFilesError {
|
||||
params(SearchFeaturedMediaFilesQueryParams),
|
||||
responses(
|
||||
(status = 200, description = "Success Response", body = SearchFeaturedMediaFilesSuccessResponse),
|
||||
(status = 500, description = "Server error", body = SearchFeaturedMediaFilesError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
)]
|
||||
pub async fn search_featured_media_files_handler(
|
||||
http_request: HttpRequest,
|
||||
query: Query<SearchFeaturedMediaFilesQueryParams>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<Json<SearchFeaturedMediaFilesSuccessResponse>, SearchFeaturedMediaFilesError>
|
||||
) -> Result<Json<SearchFeaturedMediaFilesSuccessResponse>, CommonWebError>
|
||||
{
|
||||
let mut maybe_filter_media_types = get_scoped_media_types(query.filter_media_type.as_deref());
|
||||
let mut maybe_filter_media_classes = get_scoped_media_classes(query.filter_media_classes.as_deref());
|
||||
@@ -209,7 +179,7 @@ pub async fn search_featured_media_files_handler(
|
||||
Ok(results) => results,
|
||||
Err(err) => {
|
||||
warn!("Searching error: {:?}", err);
|
||||
return Err(SearchFeaturedMediaFilesError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+8
-38
@@ -19,6 +19,7 @@ use tokens::tokens::users::UserToken;
|
||||
use utoipa::{IntoParams, ToSchema};
|
||||
|
||||
use crate::http_server::common_responses::media::media_file_cover_image_details::MediaFileCoverImageDetails;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::media::media_links_builder::MediaLinksBuilder;
|
||||
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_media_domain::get_media_domain;
|
||||
@@ -144,37 +145,6 @@ pub struct SearchMediaFileListItem {
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum SearchMediaFilesError {
|
||||
ServerError,
|
||||
NotAuthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for SearchMediaFilesError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
SearchMediaFilesError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
SearchMediaFilesError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
SearchMediaFilesError::ServerError => "server error".to_string(),
|
||||
SearchMediaFilesError::NotAuthorized => "not authorized".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for SearchMediaFilesError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Search for media files for the active user based on various criteria.
|
||||
///
|
||||
/// This only returns media files owned by the active user.
|
||||
@@ -185,15 +155,15 @@ impl std::fmt::Display for SearchMediaFilesError {
|
||||
params(SearchMediaFilesQueryParams),
|
||||
responses(
|
||||
(status = 200, description = "Success response", body = SearchMediaFilesSuccessResponse),
|
||||
(status = 401, description = "Not authorized", body = SearchMediaFilesError),
|
||||
(status = 500, description = "Server error", body = SearchMediaFilesError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
)]
|
||||
pub async fn search_session_media_files_handler(
|
||||
http_request: HttpRequest,
|
||||
query: Query<SearchMediaFilesQueryParams>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<Json<SearchMediaFilesSuccessResponse>, SearchMediaFilesError>
|
||||
) -> Result<Json<SearchMediaFilesSuccessResponse>, CommonWebError>
|
||||
{
|
||||
// NB(bt,2024-07-01): This isn't great. Though we HMAC our cookies, this could
|
||||
// result in bad situations where we don't invalidate sessions, etc. We're only
|
||||
@@ -205,17 +175,17 @@ pub async fn search_session_media_files_handler(
|
||||
let session = match session_result {
|
||||
Ok(Some(session)) => session,
|
||||
Ok(None) => {
|
||||
return Err(SearchMediaFilesError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Session decode error: {:?}", err);
|
||||
return Err(SearchMediaFilesError::ServerError);
|
||||
return Err(CommonWebError::from_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
let user_token = match session.maybe_user_token {
|
||||
Some(user_token) => UserToken::new_from_str(&user_token),
|
||||
None => return Err(SearchMediaFilesError::NotAuthorized),
|
||||
None => return Err(CommonWebError::NotAuthorized),
|
||||
};
|
||||
|
||||
let mut maybe_filter_media_types = get_scoped_media_types(query.filter_media_type.as_deref());
|
||||
@@ -236,7 +206,7 @@ pub async fn search_session_media_files_handler(
|
||||
Ok(results) => results,
|
||||
Err(err) => {
|
||||
warn!("Searching error: {:?}", err);
|
||||
return Err(SearchMediaFilesError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+2
-25
@@ -7,6 +7,7 @@ use actix_web::web::Json;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
|
||||
use crate::http_server::endpoints::app_state::components::get_user_locale::get_user_locale;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
use http_server_common::response::serialize_as_json_error::serialize_as_json_error;
|
||||
|
||||
@@ -22,37 +23,13 @@ pub struct DetectLocaleResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum DetectLocaleError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for DetectLocaleError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
DetectLocaleError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for DetectLocaleError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn detect_locale_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<Json<DetectLocaleResponse>, DetectLocaleError> {
|
||||
) -> Result<Json<DetectLocaleResponse>, CommonWebError> {
|
||||
let locale = get_user_locale(&http_request);
|
||||
|
||||
Ok(Json(DetectLocaleResponse {
|
||||
|
||||
+8
-33
@@ -24,6 +24,7 @@ use tokens::tokens::prompts::PromptToken;
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
use crate::http_server::web_utils::serialize_as_json_error::serialize_as_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::user_session::require_moderator::{require_moderator, RequireModeratorError, UseDatabase};
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
@@ -39,41 +40,15 @@ pub struct ModeratorTokenInfoResponse {
|
||||
/// Json-encoded payload
|
||||
pub maybe_payload: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub enum ModeratorTokenInfoError {
|
||||
ServerError,
|
||||
Unauthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for ModeratorTokenInfoError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ModeratorTokenInfoError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ModeratorTokenInfoError::Unauthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl fmt::Display for ModeratorTokenInfoError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
tag = "Moderation",
|
||||
path = "/v1/moderation/token_info/{token}",
|
||||
responses(
|
||||
(status = 200, description = "Found", body = ModeratorTokenInfoResponse),
|
||||
(status = 401, description = "Not authorized", body = ModeratorTokenInfoError),
|
||||
(status = 500, description = "Server error", body = ModeratorTokenInfoError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("path" = ModeratorTokenInfoPath, description = "Path for Request")
|
||||
@@ -83,13 +58,13 @@ pub async fn moderator_get_token_info_handler(
|
||||
path: Path<ModeratorTokenInfoPath>,
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ModeratorTokenInfoError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let user_session = require_moderator(&http_request, &server_state, UseDatabase::GrabNewConnection)
|
||||
.await
|
||||
.map_err(|err| match err {
|
||||
RequireModeratorError::ServerError => ModeratorTokenInfoError::ServerError,
|
||||
RequireModeratorError::NotAuthorized => ModeratorTokenInfoError::Unauthorized,
|
||||
RequireModeratorError::ServerError => CommonWebError::from_error(err),
|
||||
RequireModeratorError::NotAuthorized => CommonWebError::NotAuthorized,
|
||||
})?;
|
||||
|
||||
let token = path.token.trim();
|
||||
@@ -97,7 +72,7 @@ pub async fn moderator_get_token_info_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("get tts pending count error: {:?}", err);
|
||||
ModeratorTokenInfoError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let response = ModeratorTokenInfoResponse {
|
||||
@@ -106,7 +81,7 @@ pub async fn moderator_get_token_info_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| ModeratorTokenInfoError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+7
-40
@@ -10,6 +10,7 @@ use mysql_queries::queries::ip_bans::upsert_ip_ban::{upsert_ip_ban, UpsertIpBanA
|
||||
use user_input_common::validate_user_provided_ip_address::validate_user_provided_ip_address;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::response_success_helpers::simple_json_success;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
@@ -19,46 +20,12 @@ pub struct AddIpBanRequest {
|
||||
mod_notes: String,
|
||||
maybe_target_user_token: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum AddIpBanError {
|
||||
BadInput(String),
|
||||
ServerError,
|
||||
Unauthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for AddIpBanError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
AddIpBanError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
AddIpBanError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
AddIpBanError::Unauthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
AddIpBanError::BadInput(reason) => reason.to_string(),
|
||||
AddIpBanError::ServerError => "server error".to_string(),
|
||||
AddIpBanError::Unauthorized => "unauthorized".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for AddIpBanError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn add_ip_ban_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<AddIpBanRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, AddIpBanError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -66,27 +33,27 @@ pub async fn add_ip_ban_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
AddIpBanError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(AddIpBanError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
if !user_session.can_ban_users {
|
||||
warn!("user is not allowed to add bans: {:?}", user_session.user_token);
|
||||
return Err(AddIpBanError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let ip_address = request.ip_address.trim();
|
||||
|
||||
if let Err(e) = validate_user_provided_ip_address(&ip_address) {
|
||||
warn!("Bad ip address: {}", e);
|
||||
return Err(AddIpBanError::BadInput(e.to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(e.to_string()));
|
||||
}
|
||||
|
||||
info!("Creating ban...");
|
||||
@@ -100,7 +67,7 @@ pub async fn add_ip_ban_handler(
|
||||
}).await
|
||||
.map_err(|err| {
|
||||
warn!("Add IP ban DB error: {:?}", err);
|
||||
AddIpBanError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
Ok(simple_json_success())
|
||||
|
||||
+6
-33
@@ -10,6 +10,7 @@ use log::{info, warn};
|
||||
use mysql_queries::queries::ip_bans::toggle_ip_ban::{toggle_ip_ban, IpBanToggleState};
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::response_success_helpers::simple_json_success;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
@@ -23,40 +24,12 @@ pub struct DeleteIpBanPathInfo {
|
||||
pub struct DeleteIpBanRequest {
|
||||
delete: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Display)]
|
||||
pub enum DeleteIpBanError {
|
||||
BadInput(String),
|
||||
ServerError,
|
||||
Unauthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for DeleteIpBanError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
DeleteIpBanError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
DeleteIpBanError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
DeleteIpBanError::Unauthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
DeleteIpBanError::BadInput(reason) => reason.to_string(),
|
||||
DeleteIpBanError::ServerError => "server error".to_string(),
|
||||
DeleteIpBanError::Unauthorized => "unauthorized".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn delete_ip_ban_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<DeleteIpBanPathInfo>,
|
||||
request: web::Json<DeleteIpBanRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, DeleteIpBanError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -64,20 +37,20 @@ pub async fn delete_ip_ban_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
DeleteIpBanError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(DeleteIpBanError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
if !user_session.can_ban_users {
|
||||
warn!("user is not allowed to delete bans: {:?}", user_session.user_token.as_str());
|
||||
return Err(DeleteIpBanError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let toggle_action = if request.delete {
|
||||
@@ -100,7 +73,7 @@ pub async fn delete_ip_ban_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("(un)delete IP ban DB error: {:?}", err);
|
||||
return Err(DeleteIpBanError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+8
-38
@@ -11,6 +11,7 @@ use log::{error, warn};
|
||||
use mysql_queries::queries::ip_bans::get_ip_ban::get_ip_ban;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
/// For the URL PathInfo
|
||||
@@ -37,42 +38,11 @@ pub struct IpBanRecord {
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Display)]
|
||||
pub enum GetIpBanError {
|
||||
BadInput(String),
|
||||
ServerError,
|
||||
NotFound,
|
||||
Unauthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for GetIpBanError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetIpBanError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
GetIpBanError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
GetIpBanError::NotFound => StatusCode::NOT_FOUND,
|
||||
GetIpBanError::Unauthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
GetIpBanError::BadInput(reason) => reason.to_string(),
|
||||
GetIpBanError::ServerError => "server error".to_string(),
|
||||
GetIpBanError::NotFound => "not found".to_string(),
|
||||
GetIpBanError::Unauthorized => "unauthorized".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_ip_ban_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<GetIpBanPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, GetIpBanError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -80,20 +50,20 @@ pub async fn get_ip_ban_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
GetIpBanError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(GetIpBanError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
if !user_session.can_ban_users {
|
||||
warn!("user is not allowed to view bans: {:?}", user_session.user_token);
|
||||
return Err(GetIpBanError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let ip_address = path.ip_address.trim();
|
||||
@@ -102,12 +72,12 @@ pub async fn get_ip_ban_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("get ip ban db error: {:?}", err);
|
||||
GetIpBanError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let result : IpBanRecord = match maybe_result {
|
||||
None => {
|
||||
return Err(GetIpBanError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Some(ban) => IpBanRecord {
|
||||
ip_address: ban.ip_address,
|
||||
@@ -128,7 +98,7 @@ pub async fn get_ip_ban_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| GetIpBanError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+7
-40
@@ -9,6 +9,7 @@ use log::{error, warn};
|
||||
use mysql_queries::queries::ip_bans::list_ip_bans::list_ip_bans;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -29,45 +30,11 @@ pub struct IpBanRecordForList {
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ListIpBansError {
|
||||
BadInput(String),
|
||||
ServerError,
|
||||
Unauthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for ListIpBansError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListIpBansError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
ListIpBansError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ListIpBansError::Unauthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
ListIpBansError::BadInput(reason) => reason.to_string(),
|
||||
ListIpBansError::ServerError => "server error".to_string(),
|
||||
ListIpBansError::Unauthorized => "unauthorized".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl std::fmt::Display for ListIpBansError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_ip_bans_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ListIpBansError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -75,27 +42,27 @@ pub async fn list_ip_bans_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ListIpBansError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(ListIpBansError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
if !user_session.can_ban_users {
|
||||
warn!("user is not allowed to see bans: {:?}", user_session.user_token);
|
||||
return Err(ListIpBansError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let results = list_ip_bans(&server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("list ip bans db error: {:?}", err);
|
||||
ListIpBansError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?
|
||||
.into_iter()
|
||||
.map(|ban| {
|
||||
@@ -119,7 +86,7 @@ pub async fn list_ip_bans_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| ListIpBansError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+7
-32
@@ -9,6 +9,7 @@ use log::warn;
|
||||
use mysql_queries::queries::tts::tts_inference_jobs::get_pending_tts_inference_job_detailed_stats::{get_pending_tts_inference_job_detailed_stats, PendingCountResult};
|
||||
|
||||
use crate::http_server::web_utils::serialize_as_json_error::serialize_as_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -29,37 +30,11 @@ pub struct GetTtsInferenceQueueCountResponse {
|
||||
// Failed, but not permanently dead
|
||||
pub attempt_failed_count: i64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum GetTtsInferenceQueueCountError {
|
||||
ServerError,
|
||||
Unauthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for GetTtsInferenceQueueCountError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetTtsInferenceQueueCountError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
GetTtsInferenceQueueCountError::Unauthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl fmt::Display for GetTtsInferenceQueueCountError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_tts_inference_queue_count_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, GetTtsInferenceQueueCountError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -67,28 +42,28 @@ pub async fn get_tts_inference_queue_count_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
GetTtsInferenceQueueCountError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(GetTtsInferenceQueueCountError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: Not a good fit for this permission.
|
||||
if !user_session.can_ban_users {
|
||||
warn!("user is not allowed to view bans: {:?}", user_session.user_token);
|
||||
return Err(GetTtsInferenceQueueCountError::Unauthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let result = get_pending_tts_inference_job_detailed_stats(&server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("get tts pending count error: {:?}", err);
|
||||
GetTtsInferenceQueueCountError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?
|
||||
.unwrap_or(
|
||||
// NB: Not Found for null results means nothing is pending in the queue (not an error!)
|
||||
@@ -111,7 +86,7 @@ pub async fn get_tts_inference_queue_count_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| GetTtsInferenceQueueCountError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+7
-36
@@ -10,6 +10,7 @@ use http_server_common::response::serialize_as_json_error::serialize_as_json_err
|
||||
use mysql_queries::queries::tts::tts_inference_jobs::kill_tts_inference_jobs::{kill_tts_inference_jobs, JobStatus};
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -39,43 +40,13 @@ pub struct KillTtsInferenceJobsResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum KillTtsInferenceJobsError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for KillTtsInferenceJobsError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
KillTtsInferenceJobsError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
KillTtsInferenceJobsError::NotFound => StatusCode::NOT_FOUND,
|
||||
KillTtsInferenceJobsError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
KillTtsInferenceJobsError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for KillTtsInferenceJobsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn kill_tts_inference_jobs_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<KillTtsInferenceJobsRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, KillTtsInferenceJobsError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -83,21 +54,21 @@ pub async fn kill_tts_inference_jobs_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
KillTtsInferenceJobsError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(KillTtsInferenceJobsError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
// TODO: We don't have a permission for this, so use this as a proxy permission
|
||||
if !user_session.can_ban_users {
|
||||
warn!("no permission to edit categories");
|
||||
return Err(KillTtsInferenceJobsError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let job_status = match request.kill_action {
|
||||
@@ -110,7 +81,7 @@ pub async fn kill_tts_inference_jobs_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Error with query: {:?}", e);
|
||||
KillTtsInferenceJobsError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
let response = KillTtsInferenceJobsResponse {
|
||||
@@ -118,7 +89,7 @@ pub async fn kill_tts_inference_jobs_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| KillTtsInferenceJobsError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+15
-48
@@ -24,6 +24,7 @@ use mysql_queries::queries::users::user_profiles::get_user_profile_by_token::get
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
use crate::http_server::session::lookup::user_session_feature_flags::UserSessionFeatureFlags;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::web_utils::response_success_helpers::simple_json_success;
|
||||
use crate::http_server::web_utils::user_session::require_moderator::{
|
||||
@@ -64,50 +65,16 @@ pub enum EditUserFeatureFlagsOption {
|
||||
/// Clear all flags from the user.
|
||||
ClearAllFlags,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum EditUserFeatureFlagsError {
|
||||
BadInput(String),
|
||||
ServerError,
|
||||
Unauthorized,
|
||||
}
|
||||
|
||||
impl ResponseError for EditUserFeatureFlagsError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
EditUserFeatureFlagsError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
EditUserFeatureFlagsError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
EditUserFeatureFlagsError::Unauthorized => StatusCode::UNAUTHORIZED,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
EditUserFeatureFlagsError::BadInput(reason) => reason.to_string(),
|
||||
EditUserFeatureFlagsError::ServerError => "server error".to_string(),
|
||||
EditUserFeatureFlagsError::Unauthorized => "unauthorized".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for EditUserFeatureFlagsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
tag = "Moderation",
|
||||
path = "/v1/moderation/user_feature_flags/user/{username_or_token}",
|
||||
responses(
|
||||
(status = 200, description = "Success", body = SimpleGenericJsonSuccess),
|
||||
(status = 401, description = "Unauthorized", body = EditUserFeatureFlagsError),
|
||||
(status = 404, description = "Not found", body = EditUserFeatureFlagsError),
|
||||
(status = 500, description = "Server error", body = EditUserFeatureFlagsError),
|
||||
(status = 401, description = "Unauthorized", body = CommonWebError),
|
||||
(status = 404, description = "Not found", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("path" = EditUserFeatureFlagPathInfo, description = "Path for Request"),
|
||||
@@ -120,7 +87,7 @@ pub async fn moderator_edit_user_feature_flags_handler(
|
||||
request: Json<EditUserFeatureFlagsRequest>,
|
||||
server_state: Data<Arc<ServerState>>,
|
||||
redis_pool: Data<r2d2::Pool<Client>>,
|
||||
) -> Result<HttpResponse, EditUserFeatureFlagsError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let user_session = require_moderator(
|
||||
&http_request,
|
||||
@@ -128,7 +95,7 @@ pub async fn moderator_edit_user_feature_flags_handler(
|
||||
UseDatabase::GrabNewConnection,
|
||||
).await.map_err(|err| {
|
||||
warn!("Moderator check failed: {:?}", err);
|
||||
EditUserFeatureFlagsError::Unauthorized
|
||||
CommonWebError::NotAuthorized
|
||||
})?;
|
||||
|
||||
let username_or_token = path.username_or_token.trim();
|
||||
@@ -140,18 +107,18 @@ pub async fn moderator_edit_user_feature_flags_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Could not get user token by username: {:?}", e);
|
||||
EditUserFeatureFlagsError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?
|
||||
.ok_or(EditUserFeatureFlagsError::ServerError)?
|
||||
.ok_or(CommonWebError::server_error_with_message("uncaught server error"))?
|
||||
};
|
||||
|
||||
let user_profile = get_user_profile_by_token(&user_token, &server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Could not get user profile by token: {:?}", e);
|
||||
EditUserFeatureFlagsError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?
|
||||
.ok_or(EditUserFeatureFlagsError::ServerError)?;
|
||||
.ok_or(CommonWebError::server_error_with_message("uncaught server error"))?;
|
||||
|
||||
let mut user_feature_flags =
|
||||
UserSessionFeatureFlags::new(user_profile.maybe_feature_flags.as_deref());
|
||||
@@ -188,7 +155,7 @@ pub async fn moderator_edit_user_feature_flags_handler(
|
||||
}).await
|
||||
.map_err(|e| {
|
||||
warn!("Could not set flags: {:?}", e);
|
||||
EditUserFeatureFlagsError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
// Insert staff audit log.
|
||||
@@ -196,14 +163,14 @@ pub async fn moderator_edit_user_feature_flags_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Could not acquire MySQL connection for audit log: {:?}", e);
|
||||
EditUserFeatureFlagsError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let mut transaction = mysql_connection.begin()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Could not start transaction for audit log: {:?}", e);
|
||||
EditUserFeatureFlagsError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let _audit_token = insert_staff_audit_log(InsertStaffAuditLogArgs {
|
||||
@@ -216,14 +183,14 @@ pub async fn moderator_edit_user_feature_flags_handler(
|
||||
phantom: PhantomData,
|
||||
}).await.map_err(|err| {
|
||||
warn!("Failed to insert staff audit log: {:?}", err);
|
||||
EditUserFeatureFlagsError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
transaction.commit()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Could not commit audit log transaction: {:?}", e);
|
||||
EditUserFeatureFlagsError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
// Invalidate Redis cache for the user profile.
|
||||
|
||||
+2
-25
@@ -1,6 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::http_server::endpoints::app_state::components::get_server_info::get_server_info;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::web::Json;
|
||||
@@ -13,35 +14,11 @@ pub struct PublicInfoResponse {
|
||||
pub server_build_sha: String,
|
||||
pub server_hostname: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum PublicInfoError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for PublicInfoError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
PublicInfoError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl std::fmt::Display for PublicInfoError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_public_info_handler(
|
||||
_http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<Json<PublicInfoResponse>, PublicInfoError> {
|
||||
) -> Result<Json<PublicInfoResponse>, CommonWebError> {
|
||||
let server_info = get_server_info(&server_state);
|
||||
Ok(Json(PublicInfoResponse {
|
||||
success: true,
|
||||
|
||||
+3
-26
@@ -7,6 +7,7 @@ use actix_web::{web, HttpRequest, HttpResponse, ResponseError};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::http_server::endpoints::app_state::components::get_status_alert::{get_status_alert, AppStateStatusAlertCategory};
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
use http_server_common::response::serialize_as_json_error::serialize_as_json_error;
|
||||
|
||||
@@ -51,31 +52,7 @@ pub enum StatusAlertCategory {
|
||||
/// System is down for maintenance
|
||||
DownForMaintenance,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub enum StatusAlertError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for StatusAlertError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
StatusAlertError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl std::fmt::Display for StatusAlertError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
tag = "Misc",
|
||||
@@ -86,13 +63,13 @@ impl std::fmt::Display for StatusAlertError {
|
||||
description = "Check service status for frontend alert messages",
|
||||
body = StatusAlertResponse,
|
||||
),
|
||||
(status = 500, description = "Server error", body = StatusAlertError)
|
||||
(status = 500, description = "Server error", body = CommonWebError)
|
||||
),
|
||||
)]
|
||||
pub async fn status_alert_handler(
|
||||
_http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<Json<StatusAlertResponse>, StatusAlertError> {
|
||||
) -> Result<Json<StatusAlertResponse>, CommonWebError> {
|
||||
|
||||
let maybe_alert = get_status_alert(&server_state);
|
||||
|
||||
|
||||
+7
-32
@@ -9,6 +9,7 @@ use http_server_common::response::serialize_as_json_error::serialize_as_json_err
|
||||
use mysql_queries::queries::unsubscribe_reason::insert_unsubscribe_reason::UnsubscribeReasonInsertBuilder;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -26,44 +27,18 @@ pub struct SetUnsubscribeReasonResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum SetUnsubscribeReasonError {
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for SetUnsubscribeReasonError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
SetUnsubscribeReasonError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
SetUnsubscribeReasonError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for SetUnsubscribeReasonError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn set_unsubscribe_reason_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<SetUnsubscribeReasonRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, SetUnsubscribeReasonError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let mut mysql_connection = server_state.mysql_pool.acquire()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Could not acquire DB pool: {:?}", e);
|
||||
SetUnsubscribeReasonError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let maybe_user_session = server_state
|
||||
@@ -72,14 +47,14 @@ pub async fn set_unsubscribe_reason_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Session checker error: {:?}", e);
|
||||
SetUnsubscribeReasonError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
info!("not logged in");
|
||||
return Err(SetUnsubscribeReasonError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -91,7 +66,7 @@ pub async fn set_unsubscribe_reason_handler(
|
||||
.set_unsubscribe_reason(&request.reason)
|
||||
.insert(&mut mysql_connection)
|
||||
.await
|
||||
.map_err(|_e| SetUnsubscribeReasonError::ServerError)?;
|
||||
.map_err(CommonWebError::from_anyhow_error)?;
|
||||
|
||||
|
||||
let response = SetUnsubscribeReasonResponse {
|
||||
@@ -99,7 +74,7 @@ pub async fn set_unsubscribe_reason_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| SetUnsubscribeReasonError::ServerError)?;
|
||||
.map_err(|_e| CommonWebError::from_error(_e))?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+8
-41
@@ -7,6 +7,7 @@ use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::http_server::common_responses::tag_info::TagInfo;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::state::server_state::ServerState;
|
||||
use actix_web::error::ResponseError;
|
||||
@@ -34,41 +35,7 @@ pub struct ListTagsForEntitySuccessResponse {
|
||||
pub success: bool,
|
||||
pub tags: Vec<TagInfo>,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum ListTagsForEntityError {
|
||||
NotFound,
|
||||
ServerError,
|
||||
BadInput(String),
|
||||
}
|
||||
|
||||
impl ResponseError for ListTagsForEntityError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListTagsForEntityError::NotFound => StatusCode::NOT_FOUND,
|
||||
ListTagsForEntityError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ListTagsForEntityError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
ListTagsForEntityError::NotFound => "not found".to_string(),
|
||||
ListTagsForEntityError::ServerError => "server error".to_string(),
|
||||
ListTagsForEntityError::BadInput(ref reason) => reason.clone(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ListTagsForEntityError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// List the tags for an entity
|
||||
#[utoipa::path(
|
||||
get,
|
||||
@@ -76,9 +43,9 @@ impl fmt::Display for ListTagsForEntityError {
|
||||
path = "/v1/tags/list/{entity_type}/{entity_token}",
|
||||
responses(
|
||||
(status = 200, description = "Success", body = ListTagsForEntitySuccessResponse),
|
||||
(status = 400, description = "Bad input", body = ListTagsForEntityError),
|
||||
(status = 401, description = "Not authorized", body = ListTagsForEntityError),
|
||||
(status = 500, description = "Server error", body = ListTagsForEntityError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = ListTagsForEntityPathInfo, description = "Payload for Request"),
|
||||
@@ -88,7 +55,7 @@ pub async fn list_tags_for_entity_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<ListTagsForEntityPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<Json<ListTagsForEntitySuccessResponse>, ListTagsForEntityError>
|
||||
) -> Result<Json<ListTagsForEntitySuccessResponse>, CommonWebError>
|
||||
{
|
||||
let token = path.entity_token.as_str();
|
||||
let token_prefix_matches = match path.entity_type {
|
||||
@@ -98,7 +65,7 @@ pub async fn list_tags_for_entity_handler(
|
||||
|
||||
if !token_prefix_matches {
|
||||
warn!("invalid token prefix: {:?} for {:?}", path.entity_token, path.entity_type);
|
||||
return Err(ListTagsForEntityError::BadInput("invalid token prefix".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("invalid token prefix".to_string()));
|
||||
}
|
||||
|
||||
let mut mysql_connection = server_state.mysql_pool
|
||||
@@ -106,7 +73,7 @@ pub async fn list_tags_for_entity_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("MySql pool error: {:?}", err);
|
||||
ListTagsForEntityError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
let entity = TagUseEntity::from_entity_type_and_token(
|
||||
@@ -116,7 +83,7 @@ pub async fn list_tags_for_entity_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("error listing tags: {:?}", e);
|
||||
ListTagsForEntityError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
tags.sort_by(|a, b| a.tag_value.cmp(&b.tag_value));
|
||||
|
||||
+18
-54
@@ -7,6 +7,7 @@ use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::http_server::common_responses::tag_info::TagInfo;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::web_utils::user_session::require_user_session_extended_using_connection::require_user_session_extended_using_connection;
|
||||
use crate::state::server_state::ServerState;
|
||||
@@ -51,44 +52,7 @@ pub struct SetTagsForEntitySuccessResponse {
|
||||
pub success: bool,
|
||||
pub tags: Vec<TagInfo>,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum SetTagsForEntityError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
NotFound,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for SetTagsForEntityError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
SetTagsForEntityError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
SetTagsForEntityError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
SetTagsForEntityError::NotFound => StatusCode::NOT_FOUND,
|
||||
SetTagsForEntityError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
SetTagsForEntityError::BadInput(reason) => reason.to_string(),
|
||||
SetTagsForEntityError::NotAuthorized => "unauthorized".to_string(),
|
||||
SetTagsForEntityError::NotFound => "not found".to_string(),
|
||||
SetTagsForEntityError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for SetTagsForEntityError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Edit the tags (in bulk) for an entity. Comma-separated.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
@@ -96,9 +60,9 @@ impl fmt::Display for SetTagsForEntityError {
|
||||
path = "/v1/tags/edit/{entity_type}/{entity_token}",
|
||||
responses(
|
||||
(status = 200, description = "Success", body = SetTagsForEntitySuccessResponse),
|
||||
(status = 400, description = "Bad input", body = SetTagsForEntityError),
|
||||
(status = 401, description = "Not authorized", body = SetTagsForEntityError),
|
||||
(status = 500, description = "Server error", body = SetTagsForEntityError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = SetTagsForEntityRequest, description = "Payload for Request"),
|
||||
@@ -109,7 +73,7 @@ pub async fn set_tags_for_entity_handler(
|
||||
request: Json<SetTagsForEntityRequest>,
|
||||
path: Path<SetTagsForEntityPathInfo>,
|
||||
server_state: Data<Arc<ServerState>>,
|
||||
) -> Result<Json<SetTagsForEntitySuccessResponse>, SetTagsForEntityError>
|
||||
) -> Result<Json<SetTagsForEntitySuccessResponse>, CommonWebError>
|
||||
{
|
||||
let token = path.entity_token.as_str();
|
||||
let token_prefix_matches = match path.entity_type {
|
||||
@@ -119,7 +83,7 @@ pub async fn set_tags_for_entity_handler(
|
||||
|
||||
if !token_prefix_matches {
|
||||
warn!("invalid token prefix: {:?} for {:?}", path.entity_token, path.entity_type);
|
||||
return Err(SetTagsForEntityError::BadInput("invalid token prefix".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("invalid token prefix".to_string()));
|
||||
}
|
||||
|
||||
let mut mysql_connection = server_state.mysql_pool
|
||||
@@ -127,7 +91,7 @@ pub async fn set_tags_for_entity_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("MySql pool error: {:?}", err);
|
||||
SetTagsForEntityError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
let user_session = require_user_session_extended_using_connection(
|
||||
@@ -136,11 +100,11 @@ pub async fn set_tags_for_entity_handler(
|
||||
&mut mysql_connection)
|
||||
.await
|
||||
.map_err(|_err| {
|
||||
SetTagsForEntityError::NotAuthorized
|
||||
CommonWebError::NotAuthorized
|
||||
})?;
|
||||
|
||||
if user_session.role.is_banned {
|
||||
return Err(SetTagsForEntityError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let is_mod = user_session.role.can_ban_users;
|
||||
@@ -154,7 +118,7 @@ pub async fn set_tags_for_entity_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to modify entity: {:?}", user_session.user_token);
|
||||
return Err(SetTagsForEntityError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let request_tags = to_normalized_tags(&request.tags);
|
||||
@@ -169,7 +133,7 @@ pub async fn set_tags_for_entity_handler(
|
||||
.collect::<Vec<TagInfo>>())
|
||||
.map_err(|e| {
|
||||
warn!("error selecting tags: {:?}", e);
|
||||
SetTagsForEntityError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
let matching_tag_values = matching_tags
|
||||
@@ -191,7 +155,7 @@ pub async fn set_tags_for_entity_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("error creating tag: {:?}", e);
|
||||
SetTagsForEntityError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
new_tags.push(TagInfo {
|
||||
token,
|
||||
@@ -217,7 +181,7 @@ pub async fn set_tags_for_entity_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("error updating tags: {:?}", e);
|
||||
SetTagsForEntityError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
Ok(Json(SetTagsForEntitySuccessResponse {
|
||||
@@ -231,7 +195,7 @@ async fn get_is_creator(
|
||||
entity_token: &str,
|
||||
user_token: &UserToken,
|
||||
mysql_connection: &mut MySqlConnection
|
||||
) -> Result<bool, SetTagsForEntityError> {
|
||||
) -> Result<bool, CommonWebError> {
|
||||
match entity_type {
|
||||
TagUseEntityType::MediaFile => {
|
||||
let entity_token = MediaFileToken::new_from_str(entity_token);
|
||||
@@ -245,10 +209,10 @@ async fn get_is_creator(
|
||||
Ok(media_file.maybe_creator_user_token
|
||||
.is_some_and(|t| t.as_str() == user_token.as_str()))
|
||||
},
|
||||
Ok(None) => Err(SetTagsForEntityError::NotFound),
|
||||
Ok(None) => Err(CommonWebError::NotFound),
|
||||
Err(err) => {
|
||||
warn!("Error looking up media_file: {:?}", err);
|
||||
Err(SetTagsForEntityError::ServerError)
|
||||
Err(CommonWebError::from_anyhow_error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -263,10 +227,10 @@ async fn get_is_creator(
|
||||
Ok(Some(model_weight)) => {
|
||||
Ok(model_weight.creator_user_token.as_str() == user_token.as_str())
|
||||
},
|
||||
Ok(None) => Err(SetTagsForEntityError::NotFound),
|
||||
Ok(None) => Err(CommonWebError::NotFound),
|
||||
Err(err) => {
|
||||
warn!("Error looking up model_weight: {:?}", err);
|
||||
Err(SetTagsForEntityError::ServerError)
|
||||
Err(CommonWebError::from_anyhow_error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+6
-29
@@ -22,6 +22,7 @@ use mysql_queries::queries::trending_model_analytics::list_trending_tts_models::
|
||||
use tokens::tokens::tts_models::TtsModelToken;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// TODO TODO TODO: This endpoint is not done!
|
||||
// TODO TODO TODO: This endpoint is not done!
|
||||
@@ -45,36 +46,12 @@ pub type WindowTrends = HashMap<WindowName, Vec<TtsModelToken>>;
|
||||
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum ListTrendingTtsModelsError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ListTrendingTtsModelsError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListTrendingTtsModelsError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ListTrendingTtsModelsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn list_trending_tts_models_handler(
|
||||
_http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, ListTrendingTtsModelsError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
|
||||
// TODO: Cache the outputs!
|
||||
@@ -82,7 +59,7 @@ pub async fn list_trending_tts_models_handler(
|
||||
// let maybe_category_assignments = server_state.caches.tts_model_category_assignments.copy_without_bump_if_unexpired()
|
||||
// .map_err(|e| {
|
||||
// error!("Error consulting cache: {:?}", e);
|
||||
// ListTrendingTtsModelsError::ServerError
|
||||
// CommonWebError::from_error(e)
|
||||
// })?;
|
||||
//
|
||||
// let category_assignments = match maybe_category_assignments {
|
||||
@@ -99,7 +76,7 @@ pub async fn list_trending_tts_models_handler(
|
||||
// server_state.caches.tts_model_category_assignments.store_copy(&category_assignments)
|
||||
// .map_err(|e| {
|
||||
// error!("Error storing cache: {:?}", e);
|
||||
// ListTrendingTtsModelsError::ServerError
|
||||
// CommonWebError::from_error(e)
|
||||
// })?;
|
||||
//
|
||||
// category_assignments
|
||||
@@ -109,7 +86,7 @@ pub async fn list_trending_tts_models_handler(
|
||||
let trending_models= list_trending_tts_models_with_pool(&server_state.mysql_pool).await
|
||||
.map_err(|e| {
|
||||
error!("Query error: {:?}", e);
|
||||
ListTrendingTtsModelsError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
// TODO: Actually generate the response body sensibly.
|
||||
@@ -136,7 +113,7 @@ pub async fn list_trending_tts_models_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| ListTrendingTtsModelsError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+12
-48
@@ -15,6 +15,7 @@ use mysql_queries::queries::tts::tts_models::delete_tts_model_various_scopes::un
|
||||
use mysql_queries::queries::tts::tts_models::get_tts_model::get_tts_model_by_token;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::response_success_helpers::simple_json_success;
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::util::delete_role_disambiguation::delete_role_disambiguation;
|
||||
@@ -32,54 +33,17 @@ pub struct DeleteTtsModelRequest {
|
||||
/// NB: this is only to disambiguate when a user is both a mod and an author.
|
||||
as_mod: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DeleteTtsModelError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
NotFound,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for DeleteTtsModelError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
DeleteTtsModelError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
DeleteTtsModelError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
DeleteTtsModelError::NotFound => StatusCode::NOT_FOUND,
|
||||
DeleteTtsModelError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
DeleteTtsModelError::BadInput(reason) => reason.to_string(),
|
||||
DeleteTtsModelError::NotAuthorized => "unauthorized".to_string(),
|
||||
DeleteTtsModelError::NotFound => "not found".to_string(),
|
||||
DeleteTtsModelError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for DeleteTtsModelError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn delete_tts_model_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<DeleteTtsModelPathInfo>,
|
||||
request: web::Json<DeleteTtsModelRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, DeleteTtsModelError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
// NB: Disable if we've migrated to model_weights
|
||||
if server_state.flags.switch_tts_to_model_weights {
|
||||
warn!("Migration to model_weights for tts. Cannot delete old model.");
|
||||
return Err(DeleteTtsModelError::ServerError);
|
||||
return Err(CommonWebError::server_error_with_message("uncaught server error"));
|
||||
}
|
||||
|
||||
let maybe_user_session = server_state
|
||||
@@ -88,14 +52,14 @@ pub async fn delete_tts_model_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
DeleteTtsModelError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(DeleteTtsModelError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -112,9 +76,9 @@ pub async fn delete_tts_model_handler(
|
||||
let tts_model = match model_query_result {
|
||||
Err(e) => {
|
||||
warn!("query error: {:?}", e);
|
||||
return Err(DeleteTtsModelError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(e));
|
||||
}
|
||||
Ok(None) => return Err(DeleteTtsModelError::NotFound),
|
||||
Ok(None) => return Err(CommonWebError::NotFound),
|
||||
Ok(Some(model)) => model,
|
||||
};
|
||||
|
||||
@@ -123,13 +87,13 @@ pub async fn delete_tts_model_handler(
|
||||
|
||||
if !is_author && !is_mod {
|
||||
warn!("user is not allowed to delete models: {:?}", user_session.user_token);
|
||||
return Err(DeleteTtsModelError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
if !is_mod {
|
||||
if tts_model.is_locked_from_user_modification || tts_model.is_locked_from_use {
|
||||
warn!("user is not allowed to delete models (locked): {:?}", user_session.user_token);
|
||||
return Err(DeleteTtsModelError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -141,7 +105,7 @@ pub async fn delete_tts_model_handler(
|
||||
match delete_role {
|
||||
DeleteRole::ErrorDoNotDelete => {
|
||||
warn!("user is not allowed to delete model: {:?}", user_session.user_token);
|
||||
return Err(DeleteTtsModelError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
DeleteRole::AsUser => {
|
||||
delete_tts_model_as_user(
|
||||
@@ -162,7 +126,7 @@ pub async fn delete_tts_model_handler(
|
||||
match delete_role {
|
||||
DeleteRole::ErrorDoNotDelete => {
|
||||
warn!("user is not allowed to undelete model: {:?}", user_session.user_token);
|
||||
return Err(DeleteTtsModelError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
DeleteRole::AsUser => {
|
||||
// NB: Technically only mods can see their own inference_results here
|
||||
@@ -186,7 +150,7 @@ pub async fn delete_tts_model_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Delete tts model DB error: {:?}", err);
|
||||
return Err(DeleteTtsModelError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+10
-46
@@ -14,6 +14,7 @@ use mysql_queries::queries::tts::tts_results::delete_tts_result_various_scopes::
|
||||
use mysql_queries::queries::tts::tts_results::query_tts_result::select_tts_result_by_token;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::response_success_helpers::simple_json_success;
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::util::delete_role_disambiguation::delete_role_disambiguation;
|
||||
@@ -31,64 +32,27 @@ pub struct DeleteTtsInferenceResultRequest {
|
||||
/// NB: this is only to disambiguate when a user is both a mod and an author.
|
||||
as_mod: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DeleteTtsInferenceResultError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
NotFound,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for DeleteTtsInferenceResultError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
DeleteTtsInferenceResultError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
DeleteTtsInferenceResultError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
DeleteTtsInferenceResultError::NotFound => StatusCode::NOT_FOUND,
|
||||
DeleteTtsInferenceResultError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
DeleteTtsInferenceResultError::BadInput(reason) => reason.to_string(),
|
||||
DeleteTtsInferenceResultError::NotAuthorized => "unauthorized".to_string(),
|
||||
DeleteTtsInferenceResultError::NotFound => "not found".to_string(),
|
||||
DeleteTtsInferenceResultError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for DeleteTtsInferenceResultError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn delete_tts_inference_result_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<DeleteTtsInferenceResultPathInfo>,
|
||||
request: web::Json<DeleteTtsInferenceResultRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, DeleteTtsInferenceResultError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
.maybe_get_user_session(&http_request, &server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
DeleteTtsInferenceResultError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(DeleteTtsInferenceResultError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -105,9 +69,9 @@ pub async fn delete_tts_inference_result_handler(
|
||||
let tts_inference_result = match inference_result_query_result {
|
||||
Err(e) => {
|
||||
warn!("query error: {:?}", e);
|
||||
return Err(DeleteTtsInferenceResultError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(e));
|
||||
}
|
||||
Ok(None) => return Err(DeleteTtsInferenceResultError::NotFound),
|
||||
Ok(None) => return Err(CommonWebError::NotFound),
|
||||
Ok(Some(inference_result)) => inference_result,
|
||||
};
|
||||
|
||||
@@ -121,7 +85,7 @@ pub async fn delete_tts_inference_result_handler(
|
||||
|
||||
if !is_author && !is_mod {
|
||||
warn!("user is not allowed to delete inference results: {:?}", user_session.user_token);
|
||||
return Err(DeleteTtsInferenceResultError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let delete_role = delete_role_disambiguation(is_mod, is_author, request.as_mod);
|
||||
@@ -130,7 +94,7 @@ pub async fn delete_tts_inference_result_handler(
|
||||
match delete_role {
|
||||
DeleteRole::ErrorDoNotDelete => {
|
||||
warn!("user is not allowed to delete inference results: {:?}", user_session.user_token);
|
||||
return Err(DeleteTtsInferenceResultError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
DeleteRole::AsUser => {
|
||||
delete_tts_inference_result_as_user(
|
||||
@@ -150,7 +114,7 @@ pub async fn delete_tts_inference_result_handler(
|
||||
match delete_role {
|
||||
DeleteRole::ErrorDoNotDelete => {
|
||||
warn!("user is not allowed to undelete inference results: {:?}", user_session.user_token);
|
||||
return Err(DeleteTtsInferenceResultError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
DeleteRole::AsUser => {
|
||||
// NB: Technically only mods can see their own inference_results here
|
||||
@@ -173,7 +137,7 @@ pub async fn delete_tts_inference_result_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Update tts mod approval status DB error: {:?}", err);
|
||||
return Err(DeleteTtsInferenceResultError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+10
-38
@@ -8,6 +8,7 @@ use log::{debug, error, warn};
|
||||
use mysql_queries::queries::tts::tts_inference_jobs::get_pending_tts_inference_job_count::get_pending_tts_inference_job_count;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Serialize)]
|
||||
@@ -20,40 +21,11 @@ pub struct Response {
|
||||
/// During an attack, we may want this to go extremely slow.
|
||||
pub refresh_interval_millis: u64,
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GetPendingTtsInferenceJobCountError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for GetPendingTtsInferenceJobCountError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetPendingTtsInferenceJobCountError::ServerError=> StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
GetPendingTtsInferenceJobCountError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for GetPendingTtsInferenceJobCountError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_pending_tts_inference_job_count_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, GetPendingTtsInferenceJobCountError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
if server_state.flags.disable_tts_queue_length_endpoint {
|
||||
// NB: Despite the cache being a powerful protector of the database (this is an expensive query),
|
||||
@@ -70,7 +42,7 @@ pub async fn get_pending_tts_inference_job_count_handler(
|
||||
let maybe_cached = server_state.caches.ephemeral.tts_queue_length.grab_copy_without_bump_if_unexpired()
|
||||
.map_err(|e| {
|
||||
error!("error consulting cache: {:?}", e);
|
||||
GetPendingTtsInferenceJobCountError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
let count_result = match maybe_cached {
|
||||
@@ -93,12 +65,12 @@ pub async fn get_pending_tts_inference_job_count_handler(
|
||||
let maybe_cached = server_state.caches.ephemeral.tts_queue_length.grab_even_expired_and_bump()
|
||||
.map_err(|err| {
|
||||
error!("error consulting cache (even expired): {:?}", err);
|
||||
GetPendingTtsInferenceJobCountError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
maybe_cached.ok_or_else(|| {
|
||||
error!("error querying database and subsequently reading cache: {:?}", err);
|
||||
GetPendingTtsInferenceJobCountError::ServerError
|
||||
CommonWebError::server_error_with_message("uncaught server error")
|
||||
})?
|
||||
}
|
||||
|
||||
@@ -107,7 +79,7 @@ pub async fn get_pending_tts_inference_job_count_handler(
|
||||
server_state.caches.ephemeral.tts_queue_length.store_copy(&count_result)
|
||||
.map_err(|e| {
|
||||
error!("error storing cache: {:?}", e);
|
||||
GetPendingTtsInferenceJobCountError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
count_result
|
||||
@@ -124,25 +96,25 @@ pub async fn get_pending_tts_inference_job_count_handler(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn render_response_busy(response: Response) -> Result<HttpResponse, GetPendingTtsInferenceJobCountError> {
|
||||
pub fn render_response_busy(response: Response) -> Result<HttpResponse, CommonWebError> {
|
||||
let body = render_response_payload(response)?;
|
||||
Ok(HttpResponse::TooManyRequests()
|
||||
.content_type("application/json")
|
||||
.body(body))
|
||||
}
|
||||
|
||||
pub fn render_response_ok(response: Response) -> Result<HttpResponse, GetPendingTtsInferenceJobCountError> {
|
||||
pub fn render_response_ok(response: Response) -> Result<HttpResponse, CommonWebError> {
|
||||
let body = render_response_payload(response)?;
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
.body(body))
|
||||
}
|
||||
|
||||
pub fn render_response_payload(response: Response) -> Result<String, GetPendingTtsInferenceJobCountError> {
|
||||
pub fn render_response_payload(response: Response) -> Result<String, CommonWebError> {
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| {
|
||||
error!("error returning response: {:?}", e);
|
||||
GetPendingTtsInferenceJobCountError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
Ok(body)
|
||||
}
|
||||
+12
-42
@@ -16,6 +16,7 @@ use redis_common::redis_keys::RedisKeys;
|
||||
use tokens::tokens::generic_inference_jobs::InferenceJobToken;
|
||||
|
||||
use crate::http_server::web_utils::filter_model_name::filter_model_name;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
@@ -56,49 +57,18 @@ pub struct GetTtsInferenceStatusSuccessResponse {
|
||||
pub success: bool,
|
||||
pub state: TtsInferenceJobStatusForResponse,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GetTtsInferenceStatusError {
|
||||
ServerError,
|
||||
NotFound,
|
||||
}
|
||||
|
||||
impl ResponseError for GetTtsInferenceStatusError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetTtsInferenceStatusError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
GetTtsInferenceStatusError::NotFound => StatusCode::NOT_FOUND,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
Self::ServerError => "server error".to_string(),
|
||||
Self::NotFound => "not found".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for GetTtsInferenceStatusError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_tts_inference_job_status_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<GetTtsInferenceStatusPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, GetTtsInferenceStatusError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let job_token = path.into_inner().token;
|
||||
|
||||
if job_token.trim() == "None" {
|
||||
// NB: A bunch of Python clients use our API and can fail in this manner.
|
||||
// This was a large traffic driver during the 2023-03-08 outage.
|
||||
return Err(GetTtsInferenceStatusError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
}
|
||||
|
||||
// NB(bt,2023-11-27): We're moving TT2 over to `inference-job` (from `tts-inference-job`), which
|
||||
@@ -118,7 +88,7 @@ pub async fn get_tts_inference_job_status_handler(
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| {
|
||||
error!("error returning response: {:?}", e);
|
||||
GetTtsInferenceStatusError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
@@ -127,7 +97,7 @@ pub async fn get_tts_inference_job_status_handler(
|
||||
}
|
||||
|
||||
async fn legacy_lookup(job_token: &str, server_state: &ServerState)
|
||||
-> Result<TtsInferenceJobStatusForResponse, GetTtsInferenceStatusError>
|
||||
-> Result<TtsInferenceJobStatusForResponse, CommonWebError>
|
||||
{
|
||||
// NB: Lookup failure is Err(RowNotFound).
|
||||
// NB: Since this is publicly exposed, we don't query sensitive data.
|
||||
@@ -136,10 +106,10 @@ async fn legacy_lookup(job_token: &str, server_state: &ServerState)
|
||||
|
||||
let record = match maybe_status {
|
||||
Ok(Some(record)) => record,
|
||||
Ok(None) => return Err(GetTtsInferenceStatusError::NotFound),
|
||||
Ok(None) => return Err(CommonWebError::NotFound),
|
||||
Err(err) => {
|
||||
error!("tts job query error: {:?}", err);
|
||||
return Err(GetTtsInferenceStatusError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -147,7 +117,7 @@ async fn legacy_lookup(job_token: &str, server_state: &ServerState)
|
||||
.get()
|
||||
.map_err(|e| {
|
||||
error!("redis error: {:?}", e);
|
||||
GetTtsInferenceStatusError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
// TODO(bt,2023-05-21): Make async.
|
||||
@@ -180,7 +150,7 @@ async fn legacy_lookup(job_token: &str, server_state: &ServerState)
|
||||
}
|
||||
|
||||
async fn modern_lookup(job_token: &str, server_state: &ServerState)
|
||||
-> Result<TtsInferenceJobStatusForResponse, GetTtsInferenceStatusError>
|
||||
-> Result<TtsInferenceJobStatusForResponse, CommonWebError>
|
||||
{
|
||||
// NB: Lookup failure is Err(RowNotFound).
|
||||
// NB: Since this is publicly exposed, we don't query sensitive data.
|
||||
@@ -193,10 +163,10 @@ async fn modern_lookup(job_token: &str, server_state: &ServerState)
|
||||
|
||||
let record = match maybe_status {
|
||||
Ok(Some(record)) => record,
|
||||
Ok(None) => return Err(GetTtsInferenceStatusError::NotFound),
|
||||
Ok(None) => return Err(CommonWebError::NotFound),
|
||||
Err(err) => {
|
||||
error!("tts job query error: {:?}", err);
|
||||
return Err(GetTtsInferenceStatusError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -204,7 +174,7 @@ async fn modern_lookup(job_token: &str, server_state: &ServerState)
|
||||
.get()
|
||||
.map_err(|e| {
|
||||
error!("redis error: {:?}", e);
|
||||
GetTtsInferenceStatusError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
// TODO(bt,2023-05-21): Make async.
|
||||
|
||||
@@ -3,21 +3,18 @@
|
||||
#![forbid(unused_mut)]
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::web::Path;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::warn;
|
||||
|
||||
use crate::http_server::common_responses::user_avatars::default_avatar_color_from_username::default_avatar_color_from_username;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::user_avatars::default_avatar_from_username::default_avatar_from_username;
|
||||
use enums::by_table::tts_models::tts_model_type::TtsModelType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use http_server_common::response::serialize_as_json_error::serialize_as_json_error;
|
||||
use migration::text_to_speech::get_tts_model_info_migration::get_tts_model_info_migration;
|
||||
use mysql_queries::column_types::vocoder_type::VocoderType;
|
||||
use redis_common::redis_cache_keys::RedisCacheKeys;
|
||||
@@ -149,45 +146,19 @@ pub struct TtsModelModeratorFieldInfo {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum GetTtsModelError {
|
||||
ServerError,
|
||||
NotFound,
|
||||
}
|
||||
|
||||
impl ResponseError for GetTtsModelError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetTtsModelError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
GetTtsModelError::NotFound => StatusCode::NOT_FOUND,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for GetTtsModelError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn get_tts_model_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<GetTtsModelPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, GetTtsModelError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let mut mysql_connection = server_state.mysql_pool.acquire()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Could not acquire DB pool: {:?}", e);
|
||||
GetTtsModelError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let maybe_user_session = server_state
|
||||
@@ -196,7 +167,7 @@ pub async fn get_tts_model_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
GetTtsModelError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let mut show_deleted_models = false;
|
||||
@@ -244,9 +215,9 @@ pub async fn get_tts_model_handler(
|
||||
let model = match model_query_result {
|
||||
Err(e) => {
|
||||
warn!("query error: {:?}", e);
|
||||
return Err(GetTtsModelError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(e));
|
||||
}
|
||||
Ok(None) => return Err(GetTtsModelError::NotFound),
|
||||
Ok(None) => return Err(CommonWebError::NotFound),
|
||||
Ok(Some(model)) => model,
|
||||
};
|
||||
|
||||
@@ -259,7 +230,7 @@ pub async fn get_tts_model_handler(
|
||||
// // NB: The moderator fields will always be present before removal
|
||||
// // We don't want non-mods seeing stuff made by banned users.
|
||||
// if moderator_fields.creator_is_banned && !is_moderator {
|
||||
// return Err(GetTtsModelError::NotFound);
|
||||
// return Err(CommonWebError::NotFound);
|
||||
// }
|
||||
//}
|
||||
|
||||
@@ -357,7 +328,7 @@ pub async fn get_tts_model_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| GetTtsModelError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
@@ -11,6 +11,7 @@ use mysql_queries::queries::tts::tts_results::query_tts_result::select_tts_resul
|
||||
use mysql_queries::queries::tts::tts_results::query_tts_result::TtsResultRecordForResponse;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
/// For the URL PathInfo
|
||||
@@ -24,42 +25,11 @@ pub struct GetTtsResultSuccessResponse {
|
||||
pub success: bool,
|
||||
pub result: TtsResultRecordForResponse,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GetTtsResultError {
|
||||
ServerError,
|
||||
NotFound,
|
||||
}
|
||||
|
||||
impl ResponseError for GetTtsResultError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetTtsResultError::ServerError=> StatusCode::INTERNAL_SERVER_ERROR,
|
||||
GetTtsResultError::NotFound=> StatusCode::NOT_FOUND,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
GetTtsResultError::ServerError => "server error".to_string(),
|
||||
GetTtsResultError::NotFound => "not found".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for GetTtsResultError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_tts_inference_result_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<GetTtsResultPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, GetTtsResultError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -67,7 +37,7 @@ pub async fn get_tts_inference_result_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
GetTtsResultError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let mut show_deleted_results = false;
|
||||
@@ -91,9 +61,9 @@ pub async fn get_tts_inference_result_handler(
|
||||
let mut inference_result = match inference_result_query_result {
|
||||
Err(e) => {
|
||||
warn!("query error: {:?}", e);
|
||||
return Err(GetTtsResultError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(e));
|
||||
}
|
||||
Ok(None) => return Err(GetTtsResultError::NotFound),
|
||||
Ok(None) => return Err(CommonWebError::NotFound),
|
||||
Ok(Some(inference_result)) => inference_result,
|
||||
};
|
||||
|
||||
@@ -102,7 +72,7 @@ pub async fn get_tts_inference_result_handler(
|
||||
// We don't want non-mods seeing stuff made by banned users.
|
||||
if (moderator_fields.model_creator_is_banned || moderator_fields.result_creator_is_banned_if_user)
|
||||
&& !is_moderator{
|
||||
return Err(GetTtsResultError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,7 +86,7 @@ pub async fn get_tts_inference_result_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| GetTtsResultError::ServerError)?;
|
||||
.map_err(|e| CommonWebError::from_error(e))?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+6
-27
@@ -13,6 +13,7 @@ use mysql_queries::queries::tts::tts_model_upload_jobs::get_tts_model_upload_job
|
||||
use redis_common::redis_keys::RedisKeys;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
/// For the URL PathInfo
|
||||
@@ -45,50 +46,28 @@ pub struct GetTtsUploadModelStatusSuccessResponse {
|
||||
pub success: bool,
|
||||
pub state: TtsUploadModelJobStatusForResponse,
|
||||
}
|
||||
|
||||
#[derive(Debug, Display)]
|
||||
pub enum GetTtsUploadModelStatusError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for GetTtsUploadModelStatusError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetTtsUploadModelStatusError::ServerError=> StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
GetTtsUploadModelStatusError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_tts_upload_model_job_status_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<GetTtsUploadModelStatusPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, GetTtsUploadModelStatusError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
// NB: Since this is publicly exposed, we don't query sensitive data.
|
||||
let record = get_tts_model_upload_job_status(&path.token, &server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("tts template query error: {:?}", err);
|
||||
GetTtsUploadModelStatusError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?
|
||||
.ok_or(
|
||||
// TODO: 404
|
||||
GetTtsUploadModelStatusError::ServerError
|
||||
CommonWebError::server_error_with_message("uncaught server error")
|
||||
)?;
|
||||
|
||||
let mut redis = server_state.redis_pool
|
||||
.get()
|
||||
.map_err(|e| {
|
||||
warn!("redis error: {:?}", e);
|
||||
GetTtsUploadModelStatusError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let extra_status_key = RedisKeys::tts_download_extra_status_info(&path.token);
|
||||
@@ -119,7 +98,7 @@ pub async fn get_tts_upload_model_job_status_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| GetTtsUploadModelStatusError::ServerError)?;
|
||||
.map_err(|e| CommonWebError::from_error(e))?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+11
-42
@@ -4,11 +4,8 @@
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
use lexical_sort::natural_lexical_cmp;
|
||||
@@ -23,7 +20,7 @@ use migration::text_to_speech::list_tts_models_for_migration::list_tts_models_fo
|
||||
use mysql_queries::queries::tts::tts_category_assignments::fetch_and_build_tts_model_category_map::fetch_and_build_tts_model_category_map_with_connection;
|
||||
use mysql_queries::queries::users::user_sessions::get_user_session_by_token::SessionUserRecord;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
@@ -66,38 +63,10 @@ pub struct ListTtsModelsSuccessResponse {
|
||||
pub success: bool,
|
||||
pub models: Vec<TtsModelRecordForResponse>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ListTtsModelsError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ListTtsModelsError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListTtsModelsError::ServerError=> StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
ListTtsModelsError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ListTtsModelsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_tts_models_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, ListTtsModelsError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
if server_state.flags.disable_tts_model_list_endpoint {
|
||||
// NB: Despite the cache being a powerful protector of the database (this is an expensive query),
|
||||
@@ -112,7 +81,7 @@ pub async fn list_tts_models_handler(
|
||||
let maybe_models = server_state.caches.ephemeral.tts_model_list.grab_copy_without_bump_if_unexpired()
|
||||
.map_err(|e| {
|
||||
error!("Error consulting cache: {:?}", e);
|
||||
ListTtsModelsError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
// NB: We don't know if we need a MySQL connection, so don't grab one unless we do.
|
||||
@@ -130,7 +99,7 @@ pub async fn list_tts_models_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Could not acquire DB pool: {:?}", e);
|
||||
ListTtsModelsError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
// TODO: Fail open in case the DB is down. Pull from expired cache if query fails.
|
||||
@@ -138,7 +107,7 @@ pub async fn list_tts_models_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Error querying database: {:?}", e);
|
||||
ListTtsModelsError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
maybe_mysql_connection = Some(mysql_connection);
|
||||
@@ -146,7 +115,7 @@ pub async fn list_tts_models_handler(
|
||||
server_state.caches.ephemeral.tts_model_list.store_copy(&models)
|
||||
.map_err(|e| {
|
||||
error!("Error storing cache: {:?}", e);
|
||||
ListTtsModelsError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
models
|
||||
@@ -166,7 +135,7 @@ pub async fn list_tts_models_handler(
|
||||
}
|
||||
}.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ListTtsModelsError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let maybe_session_user_token = maybe_user_session
|
||||
@@ -190,25 +159,25 @@ pub async fn list_tts_models_handler(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn render_response_busy(response: ListTtsModelsSuccessResponse) -> Result<HttpResponse, ListTtsModelsError> {
|
||||
pub fn render_response_busy(response: ListTtsModelsSuccessResponse) -> Result<HttpResponse, CommonWebError> {
|
||||
let body = render_response_payload(response)?;
|
||||
Ok(HttpResponse::TooManyRequests()
|
||||
.content_type("application/json")
|
||||
.body(body))
|
||||
}
|
||||
|
||||
pub fn render_response_ok(response: ListTtsModelsSuccessResponse) -> Result<HttpResponse, ListTtsModelsError> {
|
||||
pub fn render_response_ok(response: ListTtsModelsSuccessResponse) -> Result<HttpResponse, CommonWebError> {
|
||||
let body = render_response_payload(response)?;
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
.body(body))
|
||||
}
|
||||
|
||||
pub fn render_response_payload(response: ListTtsModelsSuccessResponse) -> Result<String, ListTtsModelsError> {
|
||||
pub fn render_response_payload(response: ListTtsModelsSuccessResponse) -> Result<String, CommonWebError> {
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| {
|
||||
error!("error returning response: {:?}", e);
|
||||
ListTtsModelsError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
Ok(body)
|
||||
}
|
||||
|
||||
+9
-36
@@ -11,6 +11,7 @@ use log::warn;
|
||||
use mysql_queries::queries::tts::tts_results::list_tts_results_query_builder::{ListTtsResultsQueryBuilder, TtsInferenceRecordForList};
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
/// For the URL PathInfo
|
||||
@@ -34,41 +35,13 @@ pub struct ListTtsInferenceResultsForUserSuccessResponse {
|
||||
pub cursor_next: Option<String>,
|
||||
pub cursor_previous: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ListTtsInferenceResultsForUserError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ListTtsInferenceResultsForUserError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListTtsInferenceResultsForUserError::ServerError=> StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
ListTtsInferenceResultsForUserError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ListTtsInferenceResultsForUserError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_user_tts_inference_results_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<ListTtsInferenceResultsForUserPathInfo>,
|
||||
query: Query<ListTtsInferenceResultsForUserQuery>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ListTtsInferenceResultsForUserError>
|
||||
) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
return Ok(HttpResponse::Gone()
|
||||
.content_type(ContentType::plaintext())
|
||||
@@ -80,7 +53,7 @@ pub async fn list_user_tts_inference_results_handler(
|
||||
path: Path<ListTtsInferenceResultsForUserPathInfo>,
|
||||
query: Query<ListTtsInferenceResultsForUserQuery>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ListTtsInferenceResultsForUserError>
|
||||
) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -88,7 +61,7 @@ pub async fn list_user_tts_inference_results_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ListTtsInferenceResultsForUserError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
// Permissions & ACLs
|
||||
@@ -114,7 +87,7 @@ pub async fn list_user_tts_inference_results_handler(
|
||||
let cursor = server_state.sort_key_crypto.decrypt_id(cursor)
|
||||
.map_err(|e| {
|
||||
warn!("crypto error: {:?}", e);
|
||||
ListTtsInferenceResultsForUserError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
Some(cursor)
|
||||
} else {
|
||||
@@ -139,7 +112,7 @@ pub async fn list_user_tts_inference_results_handler(
|
||||
Ok(results) => results,
|
||||
Err(e) => {
|
||||
warn!("Query error: {:?}", e);
|
||||
return Err(ListTtsInferenceResultsForUserError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(e));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -147,7 +120,7 @@ pub async fn list_user_tts_inference_results_handler(
|
||||
let cursor = server_state.sort_key_crypto.encrypt_id(id as u64)
|
||||
.map_err(|e| {
|
||||
warn!("crypto error: {:?}", e);
|
||||
ListTtsInferenceResultsForUserError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
Some(cursor)
|
||||
} else {
|
||||
@@ -158,7 +131,7 @@ pub async fn list_user_tts_inference_results_handler(
|
||||
let cursor = server_state.sort_key_crypto.encrypt_id(id as u64)
|
||||
.map_err(|e| {
|
||||
warn!("crypto error: {:?}", e);
|
||||
ListTtsInferenceResultsForUserError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
Some(cursor)
|
||||
} else {
|
||||
@@ -173,7 +146,7 @@ pub async fn list_user_tts_inference_results_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| ListTtsInferenceResultsForUserError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+5
-32
@@ -11,6 +11,7 @@ use log::{info, warn};
|
||||
use mysql_queries::queries::tts::tts_models::list_tts_models::{list_tts_models, TtsModelRecordForList};
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
/// For the URL PathInfo
|
||||
@@ -24,40 +25,12 @@ pub struct ListTtsModelsForUserSuccessResponse {
|
||||
pub success: bool,
|
||||
pub models: Vec<TtsModelRecordForList>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ListTtsModelsForUserError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ListTtsModelsForUserError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListTtsModelsForUserError::ServerError=> StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
ListTtsModelsForUserError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ListTtsModelsForUserError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_user_tts_models_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<GetProfilePathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ListTtsModelsForUserError>
|
||||
) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
return Ok(HttpResponse::Gone()
|
||||
.content_type(ContentType::plaintext())
|
||||
@@ -68,7 +41,7 @@ pub async fn original_list_user_tts_models_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<GetProfilePathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ListTtsModelsForUserError>
|
||||
) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
info!("Fetching templates for user: {}", &path.username);
|
||||
|
||||
@@ -82,7 +55,7 @@ pub async fn original_list_user_tts_models_handler(
|
||||
Ok(results) => results,
|
||||
Err(e) => {
|
||||
warn!("Query error: {:?}", e);
|
||||
return Err(ListTtsModelsForUserError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(e));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -92,7 +65,7 @@ pub async fn original_list_user_tts_models_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| ListTtsModelsForUserError::ServerError)?;
|
||||
.map_err(|e| CommonWebError::from_error(e))?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+4
-35
@@ -4,11 +4,8 @@
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
use std::collections::HashSet;
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
use log::error;
|
||||
@@ -18,7 +15,7 @@ use enums::common::visibility::Visibility;
|
||||
use tokens::tokens::tts_models::TtsModelToken;
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -66,39 +63,11 @@ pub struct SearchTtsModelsSuccessResponse {
|
||||
pub success: bool,
|
||||
pub models: Vec<TtsModel>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum SearchTtsModelsError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for SearchTtsModelsError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
SearchTtsModelsError::ServerError=> StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
SearchTtsModelsError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for SearchTtsModelsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn search_tts_models_handler(
|
||||
_http_request: HttpRequest,
|
||||
request: web::Json<SearchTtsModelsRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, SearchTtsModelsError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let results = search_tts_models(
|
||||
&server_state.elasticsearch,
|
||||
@@ -107,7 +76,7 @@ pub async fn search_tts_models_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("Searching error: {:?}", err);
|
||||
SearchTtsModelsError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let results = results.into_iter()
|
||||
@@ -146,7 +115,7 @@ pub async fn search_tts_models_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| SearchTtsModelsError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+8
-35
@@ -16,6 +16,7 @@ use tokens::tokens::model_weights::ModelWeightToken;
|
||||
use tokens::tokens::tts_models::TtsModelToken;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
const MAX_BATCH_SIZE : usize = 200;
|
||||
|
||||
@@ -55,35 +56,7 @@ pub struct RatingRow {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub enum BatchGetUserRatingError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for BatchGetUserRatingError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
BatchGetUserRatingError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
BatchGetUserRatingError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
BatchGetUserRatingError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl std::fmt::Display for BatchGetUserRatingError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
|
||||
@@ -96,21 +69,21 @@ impl std::fmt::Display for BatchGetUserRatingError {
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "List User Bookmarks", body = BatchGetUserRatingResponse),
|
||||
(status = 400, description = "Bad input", body = BatchGetUserRatingError),
|
||||
(status = 401, description = "Not authorized", body = BatchGetUserRatingError),
|
||||
(status = 500, description = "Server error", body = BatchGetUserRatingError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
)]
|
||||
pub async fn batch_get_user_rating_handler(
|
||||
http_request: HttpRequest,
|
||||
query: Query<BatchGetUserRatingQueryParams>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, BatchGetUserRatingError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let mut mysql_connection = server_state.mysql_pool.acquire()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Could not acquire DB pool: {:?}", e);
|
||||
BatchGetUserRatingError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let maybe_user_session = server_state
|
||||
@@ -119,7 +92,7 @@ pub async fn batch_get_user_rating_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Session checker error: {:?}", e);
|
||||
BatchGetUserRatingError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
// NB: Force move of tokens from the Query<T>.
|
||||
@@ -151,7 +124,7 @@ pub async fn batch_get_user_rating_handler(
|
||||
).await
|
||||
.map_err(|e| {
|
||||
error!("Batch get user ratings DB error: {:?}", e);
|
||||
BatchGetUserRatingError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})
|
||||
.map(|ratings| {
|
||||
HttpResponse::Ok()
|
||||
|
||||
+11
-38
@@ -16,6 +16,7 @@ use tokens::tokens::tts_models::TtsModelToken;
|
||||
use tokens::tokens::w2l_templates::W2lTemplateToken;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -41,35 +42,7 @@ pub struct GetUserRatingResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub enum GetUserRatingError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for GetUserRatingError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetUserRatingError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
GetUserRatingError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
GetUserRatingError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl std::fmt::Display for GetUserRatingError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
|
||||
@@ -83,21 +56,21 @@ impl std::fmt::Display for GetUserRatingError {
|
||||
),
|
||||
responses(
|
||||
(status = 200, description = "List User Bookmarks", body = GetUserRatingResponse),
|
||||
(status = 400, description = "Bad input", body = GetUserRatingError),
|
||||
(status = 401, description = "Not authorized", body = GetUserRatingError),
|
||||
(status = 500, description = "Server error", body = GetUserRatingError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
)]
|
||||
pub async fn get_user_rating_handler(
|
||||
http_request: HttpRequest,
|
||||
path: web::Path<GetUserRatingPath>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, GetUserRatingError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let mut mysql_connection = server_state.mysql_pool.acquire()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Could not acquire DB pool: {:?}", e);
|
||||
GetUserRatingError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let maybe_user_session = server_state
|
||||
@@ -106,14 +79,14 @@ pub async fn get_user_rating_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Session checker error: {:?}", e);
|
||||
GetUserRatingError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
info!("not logged in");
|
||||
return Err(GetUserRatingError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -129,7 +102,7 @@ pub async fn get_user_rating_handler(
|
||||
|
||||
// TODO: We'll handle ratings of more types in the future.
|
||||
UserRatingEntityType::W2lResult | UserRatingEntityType::TtsResult =>
|
||||
return Err(GetUserRatingError::BadInput("type not yet supported".to_string())),
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("type not yet supported".to_string())),
|
||||
};
|
||||
|
||||
let maybe_rating = get_user_rating(Args {
|
||||
@@ -140,7 +113,7 @@ pub async fn get_user_rating_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("Error fetching rating: {:?}", err);
|
||||
GetUserRatingError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let response = GetUserRatingResponse {
|
||||
@@ -149,7 +122,7 @@ pub async fn get_user_rating_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| GetUserRatingError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+18
-45
@@ -25,6 +25,7 @@ use tokens::tokens::w2l_results::W2lResultToken;
|
||||
use tokens::tokens::w2l_templates::W2lTemplateToken;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -51,35 +52,7 @@ pub struct SetUserRatingResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub enum SetUserRatingError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for SetUserRatingError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
SetUserRatingError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
SetUserRatingError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
SetUserRatingError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl std::fmt::Display for SetUserRatingError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
#[utoipa::path(
|
||||
@@ -89,15 +62,15 @@ impl std::fmt::Display for SetUserRatingError {
|
||||
request_body = SetUserRatingRequest,
|
||||
responses(
|
||||
(status = 200, description = "Set user rating", body = SetUserRatingResponse),
|
||||
(status = 400, description = "Bad input", body = SetUserRatingError),
|
||||
(status = 401, description = "Not authorized", body = SetUserRatingError),
|
||||
(status = 500, description = "Server error", body = SetUserRatingError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
)]
|
||||
pub async fn set_user_rating_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<SetUserRatingRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, SetUserRatingError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
// NB(bt,2023-12-14): Kasisnu found that we're getting entity type mismatches in production. Apart from
|
||||
// querying the database for entity existence, this is the next best way to prevent incorrect comment
|
||||
@@ -117,14 +90,14 @@ pub async fn set_user_rating_handler(
|
||||
|
||||
if !token_prefix_matches {
|
||||
warn!("invalid token prefix: {:?} for {:?}", request.entity_token, request.entity_type);
|
||||
return Err(SetUserRatingError::BadInput("invalid token prefix".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("invalid token prefix".to_string()));
|
||||
}
|
||||
|
||||
let mut mysql_connection = server_state.mysql_pool.acquire()
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Could not acquire DB pool: {:?}", e);
|
||||
SetUserRatingError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let maybe_user_session = server_state
|
||||
@@ -133,14 +106,14 @@ pub async fn set_user_rating_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Session checker error: {:?}", e);
|
||||
SetUserRatingError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
info!("not logged in");
|
||||
return Err(SetUserRatingError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -158,13 +131,13 @@ pub async fn set_user_rating_handler(
|
||||
|
||||
// TODO: We'll handle ratings of more types in the future.
|
||||
UserRatingEntityType::W2lResult | UserRatingEntityType::TtsResult =>
|
||||
return Err(SetUserRatingError::BadInput("type not yet supported".to_string())),
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("type not yet supported".to_string())),
|
||||
};
|
||||
|
||||
let mut transaction = mysql_connection.begin().await
|
||||
.map_err(|err| {
|
||||
error!("error creating transaction: {:?}", err);
|
||||
SetUserRatingError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
let maybe_existing_user_rating = get_user_rating_transactional_locking(
|
||||
@@ -174,7 +147,7 @@ pub async fn set_user_rating_handler(
|
||||
).await
|
||||
.map_err(|err| {
|
||||
error!("error getting user rating: {:?}", err);
|
||||
SetUserRatingError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let _r = upsert_user_rating(Args {
|
||||
@@ -188,7 +161,7 @@ pub async fn set_user_rating_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("Error upserting rating: {:?}", err);
|
||||
SetUserRatingError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let existing_rating_value = maybe_existing_user_rating
|
||||
@@ -224,7 +197,7 @@ pub async fn set_user_rating_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("Error upserting entity stats: {:?}", err);
|
||||
SetUserRatingError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
@@ -232,7 +205,7 @@ pub async fn set_user_rating_handler(
|
||||
transaction.commit().await
|
||||
.map_err(|err| {
|
||||
error!("error committing transaction: {:?}", err);
|
||||
SetUserRatingError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
// NB: Legacy
|
||||
@@ -243,7 +216,7 @@ pub async fn set_user_rating_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("Error updating TTS rating summary stats: {:?}", err);
|
||||
SetUserRatingError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
}
|
||||
_ => {
|
||||
@@ -258,7 +231,7 @@ pub async fn set_user_rating_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("Error getting total user rating count for entity: {:?}", err);
|
||||
SetUserRatingError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let response = SetUserRatingResponse {
|
||||
@@ -267,7 +240,7 @@ pub async fn set_user_rating_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| SetUserRatingError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+12
-51
@@ -3,60 +3,21 @@
|
||||
#![forbid(unused_mut)]
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::web::Json;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use actix_web::{web, HttpRequest};
|
||||
use log::warn;
|
||||
use utoipa::ToSchema;
|
||||
use artcraft_api_defs::users::change_password::{ChangePasswordRequest, ChangePasswordResponse};
|
||||
use crate::http_server::validations::validate_passwords::validate_passwords;
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::user_session::require_user_session_extended_using_connection::require_user_session_extended_using_connection;
|
||||
use crate::state::server_state::ServerState;
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
use mysql_queries::queries::users::user::update::update_password::{update_password, UpdatePasswordArgs};
|
||||
use mysql_queries::utils::transactor::Transactor;
|
||||
use password::bcrypt_hash_password::bcrypt_hash_password;
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum ChangePasswordError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ChangePasswordError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ChangePasswordError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
ChangePasswordError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
ChangePasswordError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
ChangePasswordError::BadInput(reason) => reason.to_string(),
|
||||
ChangePasswordError::NotAuthorized => "unauthorized".to_string(),
|
||||
ChangePasswordError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ChangePasswordError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Change password for the current user.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
@@ -64,9 +25,9 @@ impl fmt::Display for ChangePasswordError {
|
||||
path = "/v1/user/change_password",
|
||||
responses(
|
||||
(status = 200, description = "Success", body = ChangePasswordResponse),
|
||||
(status = 400, description = "Bad input", body = ChangePasswordError),
|
||||
(status = 401, description = "Not authorized", body = ChangePasswordError),
|
||||
(status = 500, description = "Server error", body = ChangePasswordError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = ChangePasswordRequest, description = "Payload for Request"),
|
||||
@@ -76,13 +37,13 @@ pub async fn change_password_handler(
|
||||
http_request: HttpRequest,
|
||||
request: Json<ChangePasswordRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<Json<ChangePasswordResponse>, ChangePasswordError>
|
||||
) -> Result<Json<ChangePasswordResponse>, CommonWebError>
|
||||
{
|
||||
let password = request.password.trim();
|
||||
let password_confirmation = request.password_confirmation.trim();
|
||||
|
||||
if let Err(reason) = validate_passwords(password, password_confirmation) {
|
||||
return Err(ChangePasswordError::BadInput(reason));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(reason));
|
||||
}
|
||||
|
||||
let mut mysql_connection = server_state.mysql_pool
|
||||
@@ -90,7 +51,7 @@ pub async fn change_password_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("MySql pool error: {:?}", err);
|
||||
ChangePasswordError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
let user_session = require_user_session_extended_using_connection(
|
||||
@@ -99,18 +60,18 @@ pub async fn change_password_handler(
|
||||
&mut mysql_connection)
|
||||
.await
|
||||
.map_err(|_err| {
|
||||
ChangePasswordError::NotAuthorized
|
||||
CommonWebError::NotAuthorized
|
||||
})?;
|
||||
|
||||
if user_session.role.is_banned {
|
||||
return Err(ChangePasswordError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let password_hash = match bcrypt_hash_password(password.to_string()) {
|
||||
Ok(hash) => hash,
|
||||
Err(err) => {
|
||||
warn!("Bcrypt error: {:?}", err);
|
||||
return Err(ChangePasswordError::ServerError);
|
||||
return Err(CommonWebError::from_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -127,7 +88,7 @@ pub async fn change_password_handler(
|
||||
Ok(()) => {},
|
||||
Err(err) => {
|
||||
warn!("Error updating password: {:?}", err);
|
||||
return Err(ChangePasswordError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+12
-51
@@ -3,17 +3,13 @@
|
||||
#![forbid(unused_mut)]
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::web::Json;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use actix_web::{web, HttpRequest};
|
||||
use log::warn;
|
||||
use utoipa::ToSchema;
|
||||
use artcraft_api_defs::users::edit_email::{EditEmailRequest, EditEmailResponse};
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::user_session::require_user_session_extended_using_connection::require_user_session_extended_using_connection;
|
||||
use crate::state::server_state::ServerState;
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
@@ -21,42 +17,7 @@ use mysql_queries::queries::users::user::update::update_email::{update_email, Up
|
||||
use mysql_queries::utils::transactor::Transactor;
|
||||
use users::email::email_to_gravatar_hash::email_to_gravatar_hash;
|
||||
use users::email::validate_email_address_format::validate_email_address_format;
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum EditEmailError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for EditEmailError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
EditEmailError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
EditEmailError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
EditEmailError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
EditEmailError::BadInput(reason) => reason.to_string(),
|
||||
EditEmailError::NotAuthorized => "unauthorized".to_string(),
|
||||
EditEmailError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for EditEmailError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Edit email address of the current user.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
@@ -64,9 +25,9 @@ impl fmt::Display for EditEmailError {
|
||||
path = "/v1/user/edit_email",
|
||||
responses(
|
||||
(status = 200, description = "Success", body = EditEmailResponse),
|
||||
(status = 400, description = "Bad input", body = EditEmailError),
|
||||
(status = 401, description = "Not authorized", body = EditEmailError),
|
||||
(status = 500, description = "Server error", body = EditEmailError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = EditEmailRequest, description = "Payload for Request"),
|
||||
@@ -76,12 +37,12 @@ pub async fn edit_email_handler(
|
||||
http_request: HttpRequest,
|
||||
request: Json<EditEmailRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<Json<EditEmailResponse>, EditEmailError>
|
||||
) -> Result<Json<EditEmailResponse>, CommonWebError>
|
||||
{
|
||||
let email_address = request.email_address.trim().to_lowercase();
|
||||
|
||||
if let Err(reason) = validate_email_address_format(&email_address) {
|
||||
return Err(EditEmailError::BadInput(format!("bad email: {}", &reason)));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(format!("bad email: {}", &reason)));
|
||||
}
|
||||
|
||||
let mut mysql_connection = server_state.mysql_pool
|
||||
@@ -89,7 +50,7 @@ pub async fn edit_email_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("MySql pool error: {:?}", err);
|
||||
EditEmailError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
let user_session = require_user_session_extended_using_connection(
|
||||
@@ -98,11 +59,11 @@ pub async fn edit_email_handler(
|
||||
&mut mysql_connection)
|
||||
.await
|
||||
.map_err(|_err| {
|
||||
EditEmailError::NotAuthorized
|
||||
CommonWebError::NotAuthorized
|
||||
})?;
|
||||
|
||||
if user_session.role.is_banned {
|
||||
return Err(EditEmailError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let ip_address = get_request_ip(&http_request);
|
||||
@@ -119,11 +80,11 @@ pub async fn edit_email_handler(
|
||||
match result {
|
||||
Ok(()) => {},
|
||||
Err(UpdateEmailError::EmailIsTaken) => {
|
||||
return Err(EditEmailError::BadInput("email address is already in use".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("email address is already in use".to_string()));
|
||||
}
|
||||
Err(UpdateEmailError::DatabaseError { source }) => {
|
||||
warn!("Error updating email: {:?}", source);
|
||||
return Err(EditEmailError::ServerError);
|
||||
return Err(CommonWebError::server_error_with_message("uncaught server error"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-53
@@ -3,61 +3,22 @@
|
||||
#![forbid(unused_mut)]
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::web::Json;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use actix_web::{web, HttpRequest};
|
||||
use log::warn;
|
||||
use utoipa::ToSchema;
|
||||
use artcraft_api_defs::users::edit_username::{EditUsernameRequest, EditUsernameResponse};
|
||||
use crate::http_server::validations::is_reserved_username::is_reserved_username;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::validations::validate_username::validate_username;
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::http_server::web_utils::user_session::require_user_session_extended_using_connection::require_user_session_extended_using_connection;
|
||||
use crate::state::server_state::ServerState;
|
||||
use http_server_common::request::get_request_ip::get_request_ip;
|
||||
use mysql_queries::queries::users::user::update::update_username::{update_username, UpdateUsernameArgs, UpdateUsernameError};
|
||||
use mysql_queries::utils::transactor::Transactor;
|
||||
use user_input_common::check_for_slurs::contains_slurs;
|
||||
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum EditUsernameError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for EditUsernameError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
EditUsernameError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
EditUsernameError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
EditUsernameError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
EditUsernameError::BadInput(reason) => reason.to_string(),
|
||||
EditUsernameError::NotAuthorized => "unauthorized".to_string(),
|
||||
EditUsernameError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for EditUsernameError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Edit username of the current user.
|
||||
#[utoipa::path(
|
||||
post,
|
||||
@@ -65,9 +26,9 @@ impl fmt::Display for EditUsernameError {
|
||||
path = "/v1/user/edit_username",
|
||||
responses(
|
||||
(status = 200, description = "Success", body = EditUsernameResponse),
|
||||
(status = 400, description = "Bad input", body = EditUsernameError),
|
||||
(status = 401, description = "Not authorized", body = EditUsernameError),
|
||||
(status = 500, description = "Server error", body = EditUsernameError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = EditUsernameRequest, description = "Payload for Request"),
|
||||
@@ -77,21 +38,21 @@ pub async fn edit_username_handler(
|
||||
http_request: HttpRequest,
|
||||
request: Json<EditUsernameRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<Json<EditUsernameResponse>, EditUsernameError>
|
||||
) -> Result<Json<EditUsernameResponse>, CommonWebError>
|
||||
{
|
||||
let username = request.display_name.trim().to_lowercase();
|
||||
let display_name = request.display_name.trim().to_string();
|
||||
|
||||
if let Err(reason) = validate_username(&display_name) {
|
||||
return Err(EditUsernameError::BadInput(format!("bad username: {}", &reason)));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage(format!("bad username: {}", &reason)));
|
||||
}
|
||||
|
||||
if contains_slurs(&username) {
|
||||
return Err(EditUsernameError::BadInput("username contains slurs".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("username contains slurs".to_string()));
|
||||
}
|
||||
|
||||
if is_reserved_username(&username) {
|
||||
return Err(EditUsernameError::BadInput("username is reserved".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("username is reserved".to_string()));
|
||||
}
|
||||
|
||||
let mut mysql_connection = server_state.mysql_pool
|
||||
@@ -99,7 +60,7 @@ pub async fn edit_username_handler(
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("MySql pool error: {:?}", err);
|
||||
EditUsernameError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
let user_session = require_user_session_extended_using_connection(
|
||||
@@ -108,11 +69,11 @@ pub async fn edit_username_handler(
|
||||
&mut mysql_connection)
|
||||
.await
|
||||
.map_err(|_err| {
|
||||
EditUsernameError::NotAuthorized
|
||||
CommonWebError::NotAuthorized
|
||||
})?;
|
||||
|
||||
if user_session.role.is_banned {
|
||||
return Err(EditUsernameError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let ip_address = get_request_ip(&http_request);
|
||||
@@ -129,11 +90,11 @@ pub async fn edit_username_handler(
|
||||
match result {
|
||||
Ok(()) => {},
|
||||
Err(UpdateUsernameError::UsernameIsTaken) => {
|
||||
return Err(EditUsernameError::BadInput("username is taken".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("username is taken".to_string()));
|
||||
}
|
||||
Err(UpdateUsernameError::DatabaseError { source }) => {
|
||||
warn!("Error updating username: {:?}", source);
|
||||
return Err(EditUsernameError::ServerError);
|
||||
return Err(CommonWebError::server_error_with_message("uncaught server error"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+11
-41
@@ -4,10 +4,7 @@
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
use std::collections::BTreeSet;
|
||||
use std::fmt;
|
||||
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::web::Path;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
@@ -20,7 +17,6 @@ use utoipa::ToSchema;
|
||||
use enums::by_table::users::user_feature_flag::UserFeatureFlag;
|
||||
use enums::common::visibility::Visibility;
|
||||
use http_server_common::request::get_request_header_optional::get_request_header_optional;
|
||||
use http_server_common::response::serialize_as_json_error::serialize_as_json_error;
|
||||
use http_server_common::util::timer::MultiBenchmarkingTimer;
|
||||
use mysql_queries::queries::users::user_badges::list_user_badges::list_user_badges;
|
||||
use mysql_queries::queries::users::user_badges::list_user_badges::UserBadgeForList;
|
||||
@@ -28,6 +24,7 @@ use mysql_queries::queries::users::user_profiles::get_user_profile_by_username::
|
||||
use tokens::tokens::users::UserToken;
|
||||
|
||||
use crate::http_server::common_responses::user_avatars::default_avatar_color_from_username::default_avatar_color_from_username;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::user_avatars::default_avatar_from_username::default_avatar_from_username;
|
||||
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
|
||||
use crate::http_server::session::lookup::user_session_feature_flags::UserSessionFeatureFlags;
|
||||
@@ -89,47 +86,20 @@ pub struct ProfileSuccessResponse {
|
||||
pub success: bool,
|
||||
pub user: Option<UserProfileRecordForResponse>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub enum ProfileError {
|
||||
ServerError,
|
||||
NotFound,
|
||||
}
|
||||
|
||||
/// For the URL PathInfo
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub struct GetProfilePathInfo {
|
||||
username: String,
|
||||
}
|
||||
|
||||
impl ResponseError for ProfileError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ProfileError::ServerError=> StatusCode::INTERNAL_SERVER_ERROR,
|
||||
ProfileError::NotFound => StatusCode::NOT_FOUND,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ProfileError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
tag = "Users",
|
||||
path = "/v1/user/{username}/profile",
|
||||
responses(
|
||||
(status = 200, description = "Get profile", body = UserProfileRecordForResponse),
|
||||
(status = 404, description = "Not found", body = ProfileError),
|
||||
(status = 500, description = "Server error", body = ProfileError),
|
||||
(status = 404, description = "Not found", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("path" = GetProfilePathInfo, description = "Path for Request")
|
||||
@@ -141,7 +111,7 @@ pub async fn get_profile_handler(
|
||||
mysql_pool: web::Data<MySqlPool>,
|
||||
redis_pool: web::Data<r2d2::Pool<Client>>,
|
||||
session_checker: web::Data<SessionChecker>,
|
||||
) -> Result<HttpResponse, ProfileError>
|
||||
) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let mut benchmark = MultiBenchmarkingTimer::new_started();
|
||||
|
||||
@@ -149,7 +119,7 @@ pub async fn get_profile_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Could not acquire DB pool: {:?}", e);
|
||||
ProfileError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let (pool_connection, maybe_user_session_fut) =
|
||||
@@ -159,7 +129,7 @@ pub async fn get_profile_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ProfileError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
});
|
||||
(pc, ret)
|
||||
}
|
||||
@@ -198,10 +168,10 @@ pub async fn get_profile_handler(
|
||||
|
||||
let user_profile = match maybe_user_profile {
|
||||
Ok(Some(user_profile)) => user_profile,
|
||||
Ok(None) => return Err(ProfileError::NotFound),
|
||||
Ok(None) => return Err(CommonWebError::NotFound),
|
||||
Err(err) => {
|
||||
error!("User profile query error: {:?}", err);
|
||||
return Err(ProfileError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -227,7 +197,7 @@ pub async fn get_profile_handler(
|
||||
}
|
||||
|
||||
let user_data = match maybe_user_data {
|
||||
None => return Err(ProfileError::NotFound),
|
||||
None => return Err(CommonWebError::NotFound),
|
||||
Some(user_data) => user_data,
|
||||
};
|
||||
|
||||
@@ -238,7 +208,7 @@ pub async fn get_profile_handler(
|
||||
|
||||
if is_banned && !is_mod {
|
||||
// Can't see banned users.
|
||||
return Err(ProfileError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
}
|
||||
|
||||
if store_in_cache {
|
||||
@@ -312,7 +282,7 @@ pub async fn get_profile_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| ProfileError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
let mut http_response = HttpResponse::Ok();
|
||||
|
||||
|
||||
+5
-36
@@ -3,13 +3,10 @@
|
||||
#![forbid(unused_mut)]
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
use std::fmt;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
use actix_artcraft::sessions::user_sessions::http_user_session_manager::HttpUserSessionManager;
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use http_server_common::response::response_error_helpers::to_simple_json_error;
|
||||
use log::warn;
|
||||
use mysql_queries::queries::users::user_sessions::delete_user_session::delete_user_session;
|
||||
use sqlx::MySqlPool;
|
||||
@@ -20,42 +17,14 @@ use utoipa::ToSchema;
|
||||
pub struct LogoutSuccessResponse {
|
||||
pub success: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum LogoutError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for LogoutError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
LogoutError::ServerError=> StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
LogoutError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for LogoutError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
post,
|
||||
tag = "Users",
|
||||
path = "/v1/logout",
|
||||
responses(
|
||||
(status = 200, description = "Found", body = LogoutSuccessResponse),
|
||||
(status = 500, description = "Server error", body = LogoutError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
)]
|
||||
pub async fn logout_handler(
|
||||
@@ -63,7 +32,7 @@ pub async fn logout_handler(
|
||||
session_cookie_manager: web::Data<HttpUserSessionManager>,
|
||||
mysql_pool: web::Data<MySqlPool>,
|
||||
internal_session_cache_purge: web::Data<dyn InternalSessionCachePurge>,
|
||||
) -> Result<HttpResponse, LogoutError>
|
||||
) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
// Best effort to delete Redis session cache
|
||||
internal_session_cache_purge.best_effort_purge_session_cache(&http_request);
|
||||
@@ -72,7 +41,7 @@ pub async fn logout_handler(
|
||||
.decode_session_payload_from_request(&http_request)
|
||||
.map_err(|e| {
|
||||
warn!("Session cookie decode error: {:?}", e);
|
||||
LogoutError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
if let Some(session) = maybe_session {
|
||||
@@ -93,7 +62,7 @@ pub async fn logout_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|_e| LogoutError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
// Mark cookie for deletion
|
||||
delete_cookie.make_removal();
|
||||
|
||||
+4
-34
@@ -11,6 +11,7 @@ use utoipa::ToSchema;
|
||||
use http_server_common::response::response_error_helpers::to_simple_json_error;
|
||||
|
||||
use crate::http_server::session::session_checker::SessionChecker;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Serialize, ToSchema)]
|
||||
@@ -21,38 +22,7 @@ pub struct SessionTokenInfoSuccessResponse {
|
||||
/// Send this as the "Session:" header.
|
||||
pub maybe_signed_session: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum SessionTokenInfoError {
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for SessionTokenInfoError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
SessionTokenInfoError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
SessionTokenInfoError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
SessionTokenInfoError::ServerError => "server error".to_string(),
|
||||
SessionTokenInfoError::NotAuthorized => "not authorized".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for SessionTokenInfoError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
/// Hack to bypass CORS. !!!!!!!!!!!DO NOT USE THIS!!!!!!!!!!!!!!
|
||||
///
|
||||
/// Seriously do not use this unless you okay it with Brandon, Kasisnu, or Michael.
|
||||
@@ -63,21 +33,21 @@ impl fmt::Display for SessionTokenInfoError {
|
||||
path = "/v1/session_token",
|
||||
responses(
|
||||
(status = 200, description = "Success response", body = SessionTokenInfoSuccessResponse),
|
||||
(status = 500, description = "Server error", body = SessionTokenInfoError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
)]
|
||||
pub async fn session_token_info_handler(
|
||||
http_request: HttpRequest,
|
||||
session_checker: web::Data<SessionChecker>,
|
||||
server_state: web::Data<Arc<ServerState>>,
|
||||
) -> Result<Json<SessionTokenInfoSuccessResponse>, SessionTokenInfoError>
|
||||
) -> Result<Json<SessionTokenInfoSuccessResponse>, CommonWebError>
|
||||
{
|
||||
let maybe_session_payload = server_state
|
||||
.session_cookie_manager
|
||||
.check_and_return_session_token_decodes(&http_request)
|
||||
.map_err(|e| {
|
||||
warn!("Session cookie decode error: {:?}", e);
|
||||
SessionTokenInfoError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
Ok(Json(SessionTokenInfoSuccessResponse {
|
||||
|
||||
+6
-33
@@ -10,6 +10,7 @@ use http_server_common::response::serialize_as_json_error::serialize_as_json_err
|
||||
use mysql_queries::queries::voice_clone_requests::get_voice_clone_request::{get_voice_clone_request_by_token, get_voice_clone_request_by_user_token};
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -29,41 +30,13 @@ pub struct CheckIfVoiceRequestSubmittedResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum CheckIfVoiceRequestSubmittedError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for CheckIfVoiceRequestSubmittedError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
CheckIfVoiceRequestSubmittedError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
CheckIfVoiceRequestSubmittedError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
CheckIfVoiceRequestSubmittedError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl fmt::Display for CheckIfVoiceRequestSubmittedError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn check_if_voice_clone_request_submitted_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<CheckIfVoiceRequestSubmittedRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CheckIfVoiceRequestSubmittedError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -71,7 +44,7 @@ pub async fn check_if_voice_clone_request_submitted_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
CheckIfVoiceRequestSubmittedError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let mut submitted_by_token = false;
|
||||
@@ -84,7 +57,7 @@ pub async fn check_if_voice_clone_request_submitted_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Database error: {:?}", e);
|
||||
CheckIfVoiceRequestSubmittedError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
submitted_by_token = request.is_some();
|
||||
@@ -97,7 +70,7 @@ pub async fn check_if_voice_clone_request_submitted_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Database error: {:?}", e);
|
||||
CheckIfVoiceRequestSubmittedError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
submitted_by_user = request.is_some();
|
||||
@@ -111,7 +84,7 @@ pub async fn check_if_voice_clone_request_submitted_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| CheckIfVoiceRequestSubmittedError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+5
-32
@@ -11,6 +11,7 @@ use http_server_common::response::serialize_as_json_error::serialize_as_json_err
|
||||
use mysql_queries::queries::voice_clone_requests::insert_voice_clone_requests_builder::InsertVoiceCloneRequestBuilder;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
// =============== Request ===============
|
||||
|
||||
@@ -58,41 +59,13 @@ pub struct CreateVoiceRequestResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum CreateVoiceRequestError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for CreateVoiceRequestError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
CreateVoiceRequestError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
CreateVoiceRequestError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
CreateVoiceRequestError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl fmt::Display for CreateVoiceRequestError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn create_voice_clone_request_handler(
|
||||
http_request: HttpRequest,
|
||||
request: web::Json<CreateVoiceRequestRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CreateVoiceRequestError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -100,7 +73,7 @@ pub async fn create_voice_clone_request_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
CreateVoiceRequestError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let creator_ip_address = get_request_ip(&http_request);
|
||||
@@ -133,7 +106,7 @@ pub async fn create_voice_clone_request_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("creation error: {:?}", e);
|
||||
CreateVoiceRequestError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
let response = CreateVoiceRequestResponse {
|
||||
@@ -141,7 +114,7 @@ pub async fn create_voice_clone_request_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| CreateVoiceRequestError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+11
-42
@@ -3,11 +3,8 @@
|
||||
#![forbid(unused_mut)]
|
||||
#![forbid(unused_variables)]
|
||||
|
||||
use std::fmt;
|
||||
use std::sync::Arc;
|
||||
|
||||
use actix_web::error::ResponseError;
|
||||
use actix_web::http::StatusCode;
|
||||
use actix_web::{web, HttpRequest, HttpResponse};
|
||||
use chrono::{DateTime, Utc};
|
||||
use lexical_sort::natural_lexical_cmp;
|
||||
@@ -16,13 +13,13 @@ use sqlx::pool::PoolConnection;
|
||||
use sqlx::MySql;
|
||||
|
||||
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use enums::by_table::voice_conversion_models::voice_conversion_model_type::VoiceConversionModelType;
|
||||
use enums::common::visibility::Visibility;
|
||||
use errors::AnyhowResult;
|
||||
use migration::voice_conversion::list_vc_models_for_migration::list_vc_models_for_migration;
|
||||
use mysql_queries::queries::users::user_sessions::get_user_session_by_token::SessionUserRecord;
|
||||
|
||||
use crate::http_server::web_utils::response_error_helpers::to_simple_json_error;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
@@ -67,38 +64,10 @@ pub struct ListVoiceConversionModelsSuccessResponse {
|
||||
pub success: bool,
|
||||
pub models: Vec<VoiceConversionModel>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ListVoiceConversionModelsError {
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for ListVoiceConversionModelsError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListVoiceConversionModelsError::ServerError=> StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
ListVoiceConversionModelsError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for ListVoiceConversionModelsError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_voice_conversion_models_handler(
|
||||
http_request: HttpRequest,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, ListVoiceConversionModelsError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
if server_state.flags.disable_voice_conversion_model_list_endpoint {
|
||||
// NB: Despite the cache being a powerful protector of the database (this is an expensive query),
|
||||
@@ -113,7 +82,7 @@ pub async fn list_voice_conversion_models_handler(
|
||||
let maybe_models = server_state.caches.ephemeral.voice_conversion_model_list.grab_copy_without_bump_if_unexpired()
|
||||
.map_err(|e| {
|
||||
error!("Error consulting cache: {:?}", e);
|
||||
ListVoiceConversionModelsError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
// NB: We don't know if we need a MySQL connection, so don't grab one unless we do.
|
||||
@@ -130,7 +99,7 @@ pub async fn list_voice_conversion_models_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Could not acquire DB pool: {:?}", e);
|
||||
ListVoiceConversionModelsError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
// TODO: Fail open in case the DB is down. Pull from expired cache if query fails.
|
||||
@@ -138,7 +107,7 @@ pub async fn list_voice_conversion_models_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
error!("Error querying database: {:?}", e);
|
||||
ListVoiceConversionModelsError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
maybe_mysql_connection = Some(mysql_connection);
|
||||
@@ -146,7 +115,7 @@ pub async fn list_voice_conversion_models_handler(
|
||||
server_state.caches.ephemeral.voice_conversion_model_list.store_copy(&models)
|
||||
.map_err(|e| {
|
||||
error!("Error storing cache: {:?}", e);
|
||||
ListVoiceConversionModelsError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
|
||||
models
|
||||
@@ -166,7 +135,7 @@ pub async fn list_voice_conversion_models_handler(
|
||||
}
|
||||
}.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ListVoiceConversionModelsError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let maybe_session_user_token = maybe_user_session
|
||||
@@ -190,25 +159,25 @@ pub async fn list_voice_conversion_models_handler(
|
||||
})
|
||||
}
|
||||
|
||||
pub fn render_response_busy(response: ListVoiceConversionModelsSuccessResponse) -> Result<HttpResponse, ListVoiceConversionModelsError> {
|
||||
pub fn render_response_busy(response: ListVoiceConversionModelsSuccessResponse) -> Result<HttpResponse, CommonWebError> {
|
||||
let body = render_response_payload(response)?;
|
||||
Ok(HttpResponse::TooManyRequests()
|
||||
.content_type("application/json")
|
||||
.body(body))
|
||||
}
|
||||
|
||||
pub fn render_response_ok(response: ListVoiceConversionModelsSuccessResponse) -> Result<HttpResponse, ListVoiceConversionModelsError> {
|
||||
pub fn render_response_ok(response: ListVoiceConversionModelsSuccessResponse) -> Result<HttpResponse, CommonWebError> {
|
||||
let body = render_response_payload(response)?;
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
.body(body))
|
||||
}
|
||||
|
||||
pub fn render_response_payload(response: ListVoiceConversionModelsSuccessResponse) -> Result<String, ListVoiceConversionModelsError> {
|
||||
pub fn render_response_payload(response: ListVoiceConversionModelsSuccessResponse) -> Result<String, CommonWebError> {
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| {
|
||||
error!("error returning response: {:?}", e);
|
||||
ListVoiceConversionModelsError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
Ok(body)
|
||||
}
|
||||
|
||||
+10
-45
@@ -12,6 +12,7 @@ use mysql_queries::queries::voice_designer::voice_samples::get_dataset_sample::g
|
||||
use tokens::tokens::zs_voice_dataset_samples::ZsVoiceDatasetSampleToken;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::util::delete_role_disambiguation::{delete_role_disambiguation, DeleteRole};
|
||||
|
||||
// TODO(bt,2023-10-10): This is way too much boilerplate.
|
||||
@@ -28,49 +29,13 @@ pub struct DeleteSampleRequest {
|
||||
/// NB: this is only to disambiguate when a user is both a mod and an author.
|
||||
as_mod: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum DeleteSampleError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
NotFound,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for DeleteSampleError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
DeleteSampleError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
DeleteSampleError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
DeleteSampleError::NotFound => StatusCode::NOT_FOUND,
|
||||
DeleteSampleError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
let error_reason = match self {
|
||||
DeleteSampleError::BadInput(reason) => reason.to_string(),
|
||||
DeleteSampleError::NotAuthorized => "unauthorized".to_string(),
|
||||
DeleteSampleError::NotFound => "not found".to_string(),
|
||||
DeleteSampleError::ServerError => "server error".to_string(),
|
||||
};
|
||||
|
||||
to_simple_json_error(&error_reason, self.status_code())
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl std::fmt::Display for DeleteSampleError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
pub async fn delete_sample_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<DeleteSamplePathInfo>,
|
||||
request: web::Json<DeleteSampleRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, DeleteSampleError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -78,14 +43,14 @@ pub async fn delete_sample_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
DeleteSampleError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(DeleteSampleError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -102,9 +67,9 @@ pub async fn delete_sample_handler(
|
||||
let dataset_sample = match inference_result_query_result {
|
||||
Err(e) => {
|
||||
warn!("query error: {:?}", e);
|
||||
return Err(DeleteSampleError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(e));
|
||||
}
|
||||
Ok(None) => return Err(DeleteSampleError::NotFound),
|
||||
Ok(None) => return Err(CommonWebError::NotFound),
|
||||
Ok(Some(sample)) => sample,
|
||||
};
|
||||
|
||||
@@ -118,7 +83,7 @@ pub async fn delete_sample_handler(
|
||||
|
||||
if !is_author && !is_mod {
|
||||
warn!("user is not allowed to delete samples: {:?}", user_session.user_token);
|
||||
return Err(DeleteSampleError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let delete_role = delete_role_disambiguation(is_mod, is_author, request.as_mod);
|
||||
@@ -126,7 +91,7 @@ pub async fn delete_sample_handler(
|
||||
let query_result = if request.set_delete {
|
||||
match delete_role {
|
||||
DeleteRole::ErrorDoNotDelete => {
|
||||
return Err(DeleteSampleError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
DeleteRole::AsUser => {
|
||||
delete_sample_as_user(&path.sample_token, &server_state.mysql_pool).await
|
||||
@@ -138,7 +103,7 @@ pub async fn delete_sample_handler(
|
||||
} else {
|
||||
match delete_role {
|
||||
DeleteRole::ErrorDoNotDelete => {
|
||||
return Err(DeleteSampleError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
DeleteRole::AsUser => {
|
||||
undelete_sample_as_user(&path.sample_token, &server_state.mysql_pool).await
|
||||
@@ -153,7 +118,7 @@ pub async fn delete_sample_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Delete DB error: {:?}", err);
|
||||
return Err(DeleteSampleError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+7
-28
@@ -14,6 +14,7 @@ use tokens::tokens::zs_voice_dataset_samples::ZsVoiceDatasetSampleToken;
|
||||
use tokens::tokens::zs_voice_datasets::ZsVoiceDatasetToken;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
#[derive(Serialize, Clone)]
|
||||
pub struct ZsSampleRecordForResponse {
|
||||
@@ -42,46 +43,24 @@ pub struct ListSamplesByDatasetSuccessResponse {
|
||||
pub struct ListSamplesByDatasetPathInfo {
|
||||
dataset_token: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ListSamplesByDatasetError {
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ListSamplesByDatasetError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ResponseError for ListSamplesByDatasetError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListSamplesByDatasetError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
ListSamplesByDatasetError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_samples_by_dataset_handler(
|
||||
http_request: HttpRequest,
|
||||
path: web::Path<ListSamplesByDatasetPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ListSamplesByDatasetError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
let maybe_user_session = server_state.session_checker.maybe_get_user_session(
|
||||
&http_request,
|
||||
&server_state.mysql_pool
|
||||
).await.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ListSamplesByDatasetError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(ListSamplesByDatasetError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
},
|
||||
};
|
||||
|
||||
@@ -98,14 +77,14 @@ pub async fn list_samples_by_dataset_handler(
|
||||
&server_state.mysql_pool
|
||||
).await.map_err(|e| {
|
||||
warn!("list_samples error: {:?}", e);
|
||||
ListSamplesByDatasetError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
});
|
||||
|
||||
let samples = match query_results {
|
||||
Ok(samples) => samples,
|
||||
Err(e) => {
|
||||
warn!("list_samples error: {:?}", e);
|
||||
return Err(ListSamplesByDatasetError::ServerError);
|
||||
return Err(CommonWebError::from_error(e));
|
||||
},
|
||||
};
|
||||
|
||||
@@ -131,7 +110,7 @@ pub async fn list_samples_by_dataset_handler(
|
||||
|
||||
let body = serde_json::to_string(&response).map_err(|e| {
|
||||
warn!("json serialization error: {:?}", e);
|
||||
ListSamplesByDatasetError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
Ok(HttpResponse::Ok().content_type("application/json").body(body))
|
||||
|
||||
+7
-34
@@ -13,6 +13,7 @@ use mysql_queries::queries::voice_designer::datasets::create_dataset::{create_da
|
||||
use tokens::tokens::zs_voice_datasets::ZsVoiceDatasetToken;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct CreateDatasetRequest {
|
||||
@@ -30,52 +31,24 @@ pub struct CreateDatasetResponse {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum CreateDatasetError {
|
||||
BadInput(String),
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for CreateDatasetError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
CreateDatasetError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
CreateDatasetError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
CreateDatasetError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using DeriveMore since Clion doesn't understand it.
|
||||
impl fmt::Display for CreateDatasetError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn create_dataset_handler(http_request: HttpRequest, request: web::Json<CreateDatasetRequest>, server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CreateDatasetError> {
|
||||
pub async fn create_dataset_handler(http_request: HttpRequest, request: web::Json<CreateDatasetRequest>, server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError> {
|
||||
let maybe_user_session = server_state.session_checker.maybe_get_user_session(&http_request, &server_state.mysql_pool).await.map_err(|e| {
|
||||
error!("Error getting user session: {:?}", e);
|
||||
CreateDatasetError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(CreateDatasetError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
},
|
||||
};
|
||||
|
||||
let idempotency_token = request.idempotency_token.clone().ok_or(CreateDatasetError::BadInput("no idempotency token provided".to_string()))?;
|
||||
let idempotency_token = request.idempotency_token.clone().ok_or(CommonWebError::BadInputWithSimpleMessage("no idempotency token provided".to_string()))?;
|
||||
|
||||
let title = request.title.clone();
|
||||
|
||||
@@ -95,7 +68,7 @@ pub async fn create_dataset_handler(http_request: HttpRequest, request: web::Jso
|
||||
Ok(token) => token,
|
||||
Err(e) => {
|
||||
error!("Error creating dataset: {:?}", e);
|
||||
return Err(CreateDatasetError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(e));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -106,7 +79,7 @@ pub async fn create_dataset_handler(http_request: HttpRequest, request: web::Jso
|
||||
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| CreateDatasetError::ServerError)?;
|
||||
.map_err(|e| CommonWebError::from_error(e))?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+10
-39
@@ -13,6 +13,7 @@ use mysql_queries::queries::voice_designer::datasets::get_dataset::get_dataset_b
|
||||
use tokens::tokens::zs_voice_datasets::ZsVoiceDatasetToken;
|
||||
|
||||
use crate::http_server::web_utils::response_success_helpers::simple_json_success;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::util::delete_role_disambiguation::{delete_role_disambiguation, DeleteRole};
|
||||
|
||||
@@ -30,37 +31,7 @@ pub struct DeleteDatasetPathInfo {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum DeleteDatasetError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for DeleteDatasetError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
DeleteDatasetError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
DeleteDatasetError::NotFound => StatusCode::NOT_FOUND,
|
||||
DeleteDatasetError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
DeleteDatasetError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for DeleteDatasetError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn delete_dataset_handler(
|
||||
@@ -68,21 +39,21 @@ pub async fn delete_dataset_handler(
|
||||
path: Path<DeleteDatasetPathInfo>,
|
||||
request: web::Json<DeleteDatasetRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, DeleteDatasetError>{
|
||||
) -> Result<HttpResponse, CommonWebError>{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
.maybe_get_user_session(&http_request, &server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
DeleteDatasetError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(DeleteDatasetError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -99,11 +70,11 @@ pub async fn delete_dataset_handler(
|
||||
Ok(Some(dataset)) => dataset,
|
||||
Ok(None) => {
|
||||
warn!("Dataset not found: {:?}", dataset_token);
|
||||
return Err(DeleteDatasetError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up dataset: {:?}", err);
|
||||
return Err(DeleteDatasetError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -113,7 +84,7 @@ pub async fn delete_dataset_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to delete this dataset: {:?}", user_session.user_token);
|
||||
return Err(DeleteDatasetError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let delete_role = delete_role_disambiguation(is_mod, is_creator, request.as_mod);
|
||||
@@ -122,7 +93,7 @@ pub async fn delete_dataset_handler(
|
||||
match delete_role {
|
||||
DeleteRole::ErrorDoNotDelete => {
|
||||
warn!("user is not allowed to delete datasets: {:?}", user_session.user_token);
|
||||
return Err(DeleteDatasetError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
DeleteRole::AsUser => {
|
||||
delete_dataset_as_user(
|
||||
@@ -142,7 +113,7 @@ pub async fn delete_dataset_handler(
|
||||
match delete_role {
|
||||
DeleteRole::ErrorDoNotDelete => {
|
||||
warn!("user is not allowed to undelete voices: {:?}", user_session.user_token);
|
||||
return Err(DeleteDatasetError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
DeleteRole::AsUser => {
|
||||
// NB: Technically only mods can see their own datasets
|
||||
@@ -165,7 +136,7 @@ pub async fn delete_dataset_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Update dataset mod approval status DB error: {:?}", err);
|
||||
return Err(DeleteDatasetError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+8
-31
@@ -9,6 +9,7 @@ use chrono::{DateTime, Utc};
|
||||
use log::warn;
|
||||
|
||||
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use enums::common::visibility::Visibility;
|
||||
use mysql_queries::queries::voice_designer::datasets::get_dataset::get_dataset_by_token;
|
||||
use tokens::tokens::zs_voice_datasets::ZsVoiceDatasetToken;
|
||||
@@ -37,35 +38,11 @@ pub struct GetDatasetResponse {
|
||||
pub struct GetDatasetPathInfo {
|
||||
dataset_token: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GetDatasetError {
|
||||
NotAuthorized,
|
||||
NotFound,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl fmt::Display for GetDatasetError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ResponseError for GetDatasetError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetDatasetError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
GetDatasetError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
GetDatasetError::NotFound => StatusCode::NOT_FOUND,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_dataset_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<GetDatasetPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, GetDatasetError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -73,14 +50,14 @@ pub async fn get_dataset_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
GetDatasetError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(GetDatasetError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -98,11 +75,11 @@ pub async fn get_dataset_handler(
|
||||
Ok(Some(dataset)) => dataset,
|
||||
Ok(None) => {
|
||||
warn!("Dataset not found: {:?}", dataset_token);
|
||||
return Err(GetDatasetError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up dataset: {:?}", err);
|
||||
return Err(GetDatasetError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -112,7 +89,7 @@ pub async fn get_dataset_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to view this dataset: {:?}", user_session.user_token);
|
||||
return Err(GetDatasetError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let response = GetDatasetResponse {
|
||||
@@ -133,7 +110,7 @@ pub async fn get_dataset_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| GetDatasetError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+11
-40
@@ -16,6 +16,7 @@ use mysql_queries::queries::voice_designer::datasets::update_dataset::{update_da
|
||||
use tokens::tokens::zs_voice_datasets::ZsVoiceDatasetToken;
|
||||
|
||||
use crate::configs::supported_languages_for_models::get_canonicalized_language_tag_for_model;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -41,44 +42,14 @@ pub struct UpdateDatasetPathInfo {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum UpdateDatasetError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for UpdateDatasetError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
UpdateDatasetError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
UpdateDatasetError::NotFound => StatusCode::NOT_FOUND,
|
||||
UpdateDatasetError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
UpdateDatasetError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for UpdateDatasetError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn update_dataset_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<UpdateDatasetPathInfo>,
|
||||
request: web::Json<UpdateDatasetRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, UpdateDatasetError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -86,14 +57,14 @@ pub async fn update_dataset_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
UpdateDatasetError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(UpdateDatasetError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -110,11 +81,11 @@ pub async fn update_dataset_handler(
|
||||
Ok(Some(dataset)) => dataset,
|
||||
Ok(None) => {
|
||||
warn!("Dataset not found: {:?}", dataset_token);
|
||||
return Err(UpdateDatasetError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up dataset: {:?}", err);
|
||||
return Err(UpdateDatasetError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -125,7 +96,7 @@ pub async fn update_dataset_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to edit this dataset: {:?}", user_session.user_token);
|
||||
return Err(UpdateDatasetError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let mut title = None;
|
||||
@@ -135,7 +106,7 @@ pub async fn update_dataset_handler(
|
||||
|
||||
if let Some(payload) = request.title.as_deref() {
|
||||
if user_input_common::check_for_slurs::contains_slurs(payload) {
|
||||
return Err(UpdateDatasetError::BadInput("title contains slurs".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("title contains slurs".to_string()));
|
||||
}
|
||||
|
||||
title = Some(payload.trim().to_string());
|
||||
@@ -153,7 +124,7 @@ pub async fn update_dataset_handler(
|
||||
.transpose()
|
||||
.map_err(|e| {
|
||||
error!("Error parsing language tag '{}': {:?}", tag, e);
|
||||
UpdateDatasetError::BadInput("bad locale string".to_string())
|
||||
CommonWebError::BadInputWithSimpleMessage("bad locale string".to_string())
|
||||
})?;
|
||||
|
||||
if let Some(full_tag) = maybe_full_canonical_tag {
|
||||
@@ -166,7 +137,7 @@ pub async fn update_dataset_handler(
|
||||
|
||||
if let Some(visibility) = request.creator_set_visibility.as_deref() {
|
||||
creator_set_visibility = Visibility::from_str(visibility)
|
||||
.map_err(|_| UpdateDatasetError::BadInput("bad record visibility".to_string()))?;
|
||||
.map_err(|_| CommonWebError::BadInputWithSimpleMessage("bad record visibility".to_string()))?;
|
||||
}
|
||||
|
||||
|
||||
@@ -194,7 +165,7 @@ pub async fn update_dataset_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Update Dataset DB error: {:?}", err);
|
||||
return Err(UpdateDatasetError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+10
-39
@@ -13,6 +13,7 @@ use mysql_queries::queries::voice_designer::voices::get_voice::get_voice_by_toke
|
||||
use tokens::tokens::zs_voices::ZsVoiceToken;
|
||||
|
||||
use crate::http_server::web_utils::response_success_helpers::simple_json_success;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::util::delete_role_disambiguation::{delete_role_disambiguation, DeleteRole};
|
||||
|
||||
@@ -30,37 +31,7 @@ pub struct DeleteVoicePathInfo {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum DeleteVoiceError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for DeleteVoiceError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
DeleteVoiceError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
DeleteVoiceError::NotFound => StatusCode::NOT_FOUND,
|
||||
DeleteVoiceError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
DeleteVoiceError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for DeleteVoiceError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn delete_voice_handler(
|
||||
@@ -68,21 +39,21 @@ pub async fn delete_voice_handler(
|
||||
path: Path<DeleteVoicePathInfo>,
|
||||
request: web::Json<DeleteVoiceRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, DeleteVoiceError>{
|
||||
) -> Result<HttpResponse, CommonWebError>{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
.maybe_get_user_session(&http_request, &server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
DeleteVoiceError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(DeleteVoiceError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -99,11 +70,11 @@ pub async fn delete_voice_handler(
|
||||
Ok(Some(voice)) => voice,
|
||||
Ok(None) => {
|
||||
warn!("Voice not found: {:?}", voice_token);
|
||||
return Err(DeleteVoiceError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up voice: {:?}", err);
|
||||
return Err(DeleteVoiceError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -113,7 +84,7 @@ pub async fn delete_voice_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to delete this voice: {:?}", user_session.user_token);
|
||||
return Err(DeleteVoiceError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let delete_role = delete_role_disambiguation(is_mod, is_creator, request.as_mod);
|
||||
@@ -122,7 +93,7 @@ pub async fn delete_voice_handler(
|
||||
match delete_role {
|
||||
DeleteRole::ErrorDoNotDelete => {
|
||||
warn!("user is not allowed to delete voices: {:?}", user_session.user_token);
|
||||
return Err(DeleteVoiceError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
DeleteRole::AsUser => {
|
||||
delete_voice_as_user(
|
||||
@@ -142,7 +113,7 @@ pub async fn delete_voice_handler(
|
||||
match delete_role {
|
||||
DeleteRole::ErrorDoNotDelete => {
|
||||
warn!("user is not allowed to undelete voices: {:?}", user_session.user_token);
|
||||
return Err(DeleteVoiceError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
DeleteRole::AsUser => {
|
||||
undelete_voice_as_user(
|
||||
@@ -164,7 +135,7 @@ pub async fn delete_voice_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Update voice mod approval status DB error: {:?}", err);
|
||||
return Err(DeleteVoiceError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+8
-31
@@ -9,6 +9,7 @@ use chrono::{DateTime, Utc};
|
||||
use log::warn;
|
||||
|
||||
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use enums::common::visibility::Visibility;
|
||||
use mysql_queries::queries::voice_designer::voices::get_voice::get_voice_by_token;
|
||||
use tokens::tokens::zs_voices::ZsVoiceToken;
|
||||
@@ -37,35 +38,11 @@ pub struct GetVoiceResponse {
|
||||
pub struct GetVoicePathInfo {
|
||||
voice_token: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GetVoiceError {
|
||||
NotAuthorized,
|
||||
NotFound,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl fmt::Display for GetVoiceError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ResponseError for GetVoiceError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetVoiceError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
GetVoiceError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
GetVoiceError::NotFound => StatusCode::NOT_FOUND,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_voice_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<GetVoicePathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, GetVoiceError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -73,14 +50,14 @@ pub async fn get_voice_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
GetVoiceError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(GetVoiceError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -98,11 +75,11 @@ pub async fn get_voice_handler(
|
||||
Ok(Some(voice)) => voice,
|
||||
Ok(None) => {
|
||||
warn!("Voice not found: {:?}", voice_token);
|
||||
return Err(GetVoiceError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up voice: {:?}", err);
|
||||
return Err(GetVoiceError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -112,7 +89,7 @@ pub async fn get_voice_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to view this voice: {:?}", user_session.user_token);
|
||||
return Err(GetVoiceError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let response = GetVoiceResponse {
|
||||
@@ -133,7 +110,7 @@ pub async fn get_voice_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| GetVoiceError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+9
-30
@@ -7,6 +7,7 @@ use chrono::{DateTime, Utc};
|
||||
use log::{info, warn};
|
||||
|
||||
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use enums::common::visibility::Visibility;
|
||||
use mysql_queries::queries::voice_designer::voices::list_voices_query_builder::ListVoicesQueryBuilder;
|
||||
use tokens::tokens::zs_voices::ZsVoiceToken;
|
||||
@@ -43,40 +44,18 @@ pub struct ZsVoiceForList {
|
||||
pub created_at: DateTime<Utc>,
|
||||
pub updated_at: DateTime<Utc>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ListZsVoicesError {
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ListZsVoicesError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ResponseError for ListZsVoicesError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListZsVoicesError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
ListZsVoicesError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list_available_voices_handler(
|
||||
http_request: HttpRequest,
|
||||
query: web::Query<ListZsVoicesQuery>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ListZsVoicesError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let maybe_user_session = server_state.session_checker.maybe_get_user_session(
|
||||
&http_request,
|
||||
&server_state.mysql_pool
|
||||
).await.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ListZsVoicesError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let mut is_mod = false;
|
||||
@@ -87,7 +66,7 @@ pub async fn list_available_voices_handler(
|
||||
}
|
||||
None => {
|
||||
info!("not logged in");
|
||||
return Err(ListZsVoicesError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -101,7 +80,7 @@ pub async fn list_available_voices_handler(
|
||||
let cursor = server_state.sort_key_crypto.decrypt_id(cursor)
|
||||
.map_err(|e| {
|
||||
warn!("crypto error: {:?}", e);
|
||||
ListZsVoicesError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
Some(cursor)
|
||||
} else {
|
||||
@@ -130,7 +109,7 @@ pub async fn list_available_voices_handler(
|
||||
Ok(results) => results,
|
||||
Err(e) => {
|
||||
warn!("Query error: {:?}", e);
|
||||
return Err(ListZsVoicesError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(e));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -138,7 +117,7 @@ pub async fn list_available_voices_handler(
|
||||
let cursor = server_state.sort_key_crypto.encrypt_id(id as u64)
|
||||
.map_err(|e| {
|
||||
warn!("crypto error: {:?}", e);
|
||||
ListZsVoicesError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
Some(cursor)
|
||||
} else {
|
||||
@@ -149,7 +128,7 @@ pub async fn list_available_voices_handler(
|
||||
let cursor = server_state.sort_key_crypto.encrypt_id(id as u64)
|
||||
.map_err(|e| {
|
||||
warn!("crypto error: {:?}", e);
|
||||
ListZsVoicesError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
})?;
|
||||
Some(cursor)
|
||||
} else {
|
||||
@@ -180,7 +159,7 @@ pub async fn list_available_voices_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| ListZsVoicesError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+11
-40
@@ -15,6 +15,7 @@ use mysql_queries::queries::voice_designer::voices::update_voice::{update_voice,
|
||||
use tokens::tokens::zs_voices::ZsVoiceToken;
|
||||
|
||||
use crate::configs::supported_languages_for_models::get_canonicalized_language_tag_for_model;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -40,44 +41,14 @@ pub struct UpdateVoicePathInfo {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub enum UpdateVoiceError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for UpdateVoiceError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
UpdateVoiceError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
UpdateVoiceError::NotFound => StatusCode::NOT_FOUND,
|
||||
UpdateVoiceError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
UpdateVoiceError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for UpdateVoiceError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
pub async fn update_voice_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<UpdateVoicePathInfo>,
|
||||
request: web::Json<UpdateVoiceRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, UpdateVoiceError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -85,14 +56,14 @@ pub async fn update_voice_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
UpdateVoiceError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(UpdateVoiceError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -109,11 +80,11 @@ pub async fn update_voice_handler(
|
||||
Ok(Some(voice)) => voice,
|
||||
Ok(None) => {
|
||||
warn!("Voice not found: {:?}", voice_token);
|
||||
return Err(UpdateVoiceError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up voice: {:?}", err);
|
||||
return Err(UpdateVoiceError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -124,7 +95,7 @@ pub async fn update_voice_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to edit this voice: {:?}", user_session.user_token);
|
||||
return Err(UpdateVoiceError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let mut title = None;
|
||||
@@ -134,7 +105,7 @@ pub async fn update_voice_handler(
|
||||
|
||||
if let Some(payload) = request.title.as_deref() {
|
||||
if user_input_common::check_for_slurs::contains_slurs(payload) {
|
||||
return Err(UpdateVoiceError::BadInput("title contains slurs".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("title contains slurs".to_string()));
|
||||
}
|
||||
|
||||
title = Some(payload.trim().to_string());
|
||||
@@ -152,7 +123,7 @@ pub async fn update_voice_handler(
|
||||
.transpose()
|
||||
.map_err(|e| {
|
||||
error!("Error parsing language tag '{}': {:?}", tag, e);
|
||||
UpdateVoiceError::BadInput("bad locale string".to_string())
|
||||
CommonWebError::BadInputWithSimpleMessage("bad locale string".to_string())
|
||||
})?;
|
||||
|
||||
if let Some(full_tag) = maybe_full_canonical_tag {
|
||||
@@ -165,7 +136,7 @@ pub async fn update_voice_handler(
|
||||
|
||||
if let Some(visibility) = request.creator_set_visibility.as_deref() {
|
||||
creator_set_visibility = Visibility::from_str(visibility)
|
||||
.map_err(|_| UpdateVoiceError::BadInput("bad record visibility".to_string()))?;
|
||||
.map_err(|_| CommonWebError::BadInputWithSimpleMessage("bad record visibility".to_string()))?;
|
||||
}
|
||||
|
||||
|
||||
@@ -191,7 +162,7 @@ pub async fn update_voice_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Update Voice DB error: {:?}", err);
|
||||
return Err(UpdateVoiceError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+13
-43
@@ -19,6 +19,7 @@ use tokens::tokens::model_weights::ModelWeightToken;
|
||||
|
||||
use artcraft_api_defs::common::responses::simple_generic_json_success::SimpleGenericJsonSuccess;
|
||||
use crate::http_server::web_utils::response_success_helpers::simple_json_success;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::util::delete_role_disambiguation::{delete_role_disambiguation, DeleteRole};
|
||||
|
||||
@@ -35,47 +36,16 @@ pub struct DeleteWeightRequest {
|
||||
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize,ToSchema)]
|
||||
pub enum DeleteWeightError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for DeleteWeightError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
DeleteWeightError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
DeleteWeightError::NotFound => StatusCode::NOT_FOUND,
|
||||
DeleteWeightError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
DeleteWeightError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for DeleteWeightError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[utoipa::path(
|
||||
delete,
|
||||
tag = "Model Weights",
|
||||
path = "/v1/weights/weight/{weight_token}",
|
||||
responses(
|
||||
(status = 200, description = "Success Delete", body = SimpleGenericJsonSuccess),
|
||||
(status = 400, description = "Bad input", body = DeleteWeightError),
|
||||
(status = 401, description = "Not authorized", body = DeleteWeightError),
|
||||
(status = 500, description = "Server error", body = DeleteWeightError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = DeleteWeightRequest, description = "Payload for Request"),
|
||||
@@ -87,21 +57,21 @@ pub async fn delete_weight_handler(
|
||||
path: Path<DeleteWeightPathInfo>,
|
||||
request: web::Json<DeleteWeightRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, DeleteWeightError>{
|
||||
) -> Result<HttpResponse, CommonWebError>{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
.maybe_get_user_session(&http_request, &server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
DeleteWeightError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(DeleteWeightError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -118,11 +88,11 @@ pub async fn delete_weight_handler(
|
||||
Ok(Some(weight)) => weight,
|
||||
Ok(None) => {
|
||||
warn!("Weight not found: {:?}", weight_token);
|
||||
return Err(DeleteWeightError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up weight: {:?}", err);
|
||||
return Err(DeleteWeightError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -132,7 +102,7 @@ pub async fn delete_weight_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to delete this weight: {:?}", user_session.user_token);
|
||||
return Err(DeleteWeightError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let delete_role = delete_role_disambiguation(is_mod, is_creator, Some(request.as_mod));
|
||||
@@ -141,7 +111,7 @@ pub async fn delete_weight_handler(
|
||||
match delete_role {
|
||||
DeleteRole::ErrorDoNotDelete => {
|
||||
warn!("user is not allowed to delete weights: {:?}", user_session.user_token);
|
||||
return Err(DeleteWeightError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
DeleteRole::AsUser => {
|
||||
delete_weights_as_user(
|
||||
@@ -160,7 +130,7 @@ pub async fn delete_weight_handler(
|
||||
match delete_role {
|
||||
DeleteRole::ErrorDoNotDelete => {
|
||||
warn!("user is not allowed to undelete weights: {:?}", user_session.user_token);
|
||||
return Err(DeleteWeightError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
DeleteRole::AsUser => {
|
||||
undelete_weights_as_user(
|
||||
@@ -181,7 +151,7 @@ pub async fn delete_weight_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Update weight mod approval status DB error: {:?}", err);
|
||||
return Err(DeleteWeightError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+11
-33
@@ -18,6 +18,7 @@ use primitives::numerics::u64_to_u32_saturating::u64_to_u32_saturating;
|
||||
use tokens::tokens::model_weights::ModelWeightToken;
|
||||
|
||||
use crate::http_server::common_responses::media::weights_cover_image_details::WeightsCoverImageDetails;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::simple_entity_stats::SimpleEntityStats;
|
||||
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
|
||||
use crate::http_server::endpoints::media_files::helpers::get_media_domain::get_media_domain;
|
||||
@@ -86,38 +87,15 @@ pub struct GetWeightResponse {
|
||||
pub struct GetWeightPathInfo {
|
||||
weight_token: ModelWeightToken,
|
||||
}
|
||||
|
||||
#[derive(Debug, ToSchema)]
|
||||
pub enum GetWeightError {
|
||||
NotAuthorized,
|
||||
NotFound,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl fmt::Display for GetWeightError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ResponseError for GetWeightError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
GetWeightError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
GetWeightError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
GetWeightError::NotFound => StatusCode::NOT_FOUND,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[utoipa::path(
|
||||
get,
|
||||
tag = "Model Weights",
|
||||
path = "/v1/weights/weight/{weight_token}",
|
||||
responses(
|
||||
(status = 200, description = "Success Update", body = GetWeightResponse),
|
||||
(status = 400, description = "Bad input", body = GetWeightError),
|
||||
(status = 401, description = "Not authorized", body = GetWeightError),
|
||||
(status = 500, description = "Server error", body = GetWeightError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("path" = GetWeightPathInfo, description = "Path for Request")
|
||||
@@ -127,14 +105,14 @@ pub async fn get_weight_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<GetWeightPathInfo>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, GetWeightError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
.maybe_get_user_session(&http_request, &server_state.mysql_pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
GetWeightError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let is_mod = maybe_user_session
|
||||
@@ -152,11 +130,11 @@ pub async fn get_weight_handler(
|
||||
Ok(Some(weight)) => weight,
|
||||
Ok(None) => {
|
||||
warn!("Weight not found: {:?}", &path.weight_token);
|
||||
return Err(GetWeightError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up weight: {:?}", err);
|
||||
return Err(GetWeightError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -168,7 +146,7 @@ pub async fn get_weight_handler(
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(GetWeightError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -176,7 +154,7 @@ pub async fn get_weight_handler(
|
||||
|
||||
if !is_mod && session_user_token.as_str() != user_session.user_token.as_str() {
|
||||
warn!("user is not allowed to view this weight: {:?}", user_session.user_token.as_str());
|
||||
return Err(GetWeightError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,7 +217,7 @@ pub async fn get_weight_handler(
|
||||
};
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| GetWeightError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+8
-29
@@ -19,6 +19,7 @@ use primitives::numerics::u64_to_u32_saturating::u64_to_u32_saturating;
|
||||
use tokens::tokens::model_weights::ModelWeightToken;
|
||||
|
||||
use crate::http_server::common_responses::media::weights_cover_image_details::WeightsCoverImageDetails;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::common_responses::pagination_page::PaginationPage;
|
||||
use crate::http_server::common_responses::simple_entity_stats::SimpleEntityStats;
|
||||
use crate::http_server::common_responses::user_details_lite::UserDetailsLight;
|
||||
@@ -104,36 +105,14 @@ pub struct ListWeightsForUserQueryParams {
|
||||
pub struct ListWeightsByUserPathInfo {
|
||||
username: String,
|
||||
}
|
||||
|
||||
#[derive(Debug,ToSchema)]
|
||||
pub enum ListWeightsByUserError {
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl fmt::Display for ListWeightsByUserError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
impl ResponseError for ListWeightsByUserError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
ListWeightsByUserError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
ListWeightsByUserError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[utoipa::path(
|
||||
get,
|
||||
tag = "Model Weights",
|
||||
path = "/v1/weights/by_user/{username}",
|
||||
responses(
|
||||
(status = 200, description = "List Weights by user", body = ListWeightsByUserSuccessResponse),
|
||||
(status = 401, description = "Not authorized", body = ListWeightsByUserError),
|
||||
(status = 500, description = "Server error", body = ListWeightsByUserError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("path" = ListWeightsByUserPathInfo, description = "Payload for Request"),
|
||||
@@ -145,7 +124,7 @@ pub async fn list_weights_by_user_handler(
|
||||
path: Path<ListWeightsByUserPathInfo>,
|
||||
query: Query<ListWeightsForUserQueryParams>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, ListWeightsByUserError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -153,7 +132,7 @@ pub async fn list_weights_by_user_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
ListWeightsByUserError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let mut is_author = false;
|
||||
@@ -195,14 +174,14 @@ pub async fn list_weights_by_user_handler(
|
||||
}
|
||||
).await.map_err(|e| {
|
||||
warn!("Error querying for weights: {:?}", e);
|
||||
ListWeightsByUserError::ServerError
|
||||
CommonWebError::from_anyhow_error(e)
|
||||
});
|
||||
|
||||
let results_page = match query_results {
|
||||
Ok(results) => results,
|
||||
Err(e) => {
|
||||
warn!("Error querying for weights: {:?}", e);
|
||||
return Err(ListWeightsByUserError::ServerError);
|
||||
return Err(CommonWebError::from_error(e));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -270,7 +249,7 @@ pub async fn list_weights_by_user_handler(
|
||||
|
||||
|
||||
let body = serde_json::to_string(&response)
|
||||
.map_err(|e| ListWeightsByUserError::ServerError)?;
|
||||
.map_err(CommonWebError::from_error)?;
|
||||
|
||||
Ok(HttpResponse::Ok()
|
||||
.content_type("application/json")
|
||||
|
||||
+14
-43
@@ -19,6 +19,7 @@ use tokens::tokens::media_files::MediaFileToken;
|
||||
use tokens::tokens::model_weights::ModelWeightToken;
|
||||
|
||||
use crate::state::server_state::ServerState;
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
|
||||
#[derive(Deserialize, ToSchema)]
|
||||
pub struct SetModelWeightCoverImageRequest {
|
||||
@@ -37,37 +38,7 @@ pub struct SetModelWeightCoverImagePathInfo {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub enum SetModelWeightCoverImageError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for SetModelWeightCoverImageError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
SetModelWeightCoverImageError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
SetModelWeightCoverImageError::NotFound => StatusCode::NOT_FOUND,
|
||||
SetModelWeightCoverImageError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
SetModelWeightCoverImageError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for SetModelWeightCoverImageError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
#[utoipa::path(
|
||||
@@ -76,9 +47,9 @@ impl fmt::Display for SetModelWeightCoverImageError {
|
||||
path = "/v1/weights/weight/{weight_token}/cover_image",
|
||||
responses(
|
||||
(status = 200, description = "Success Update", body = SetModelWeightCoverImageResponse),
|
||||
(status = 400, description = "Bad input", body = SetModelWeightCoverImageError),
|
||||
(status = 401, description = "Not authorized", body = SetModelWeightCoverImageError),
|
||||
(status = 500, description = "Server error", body = SetModelWeightCoverImageError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = SetModelWeightCoverImageRequest, description = "Payload for Request"),
|
||||
@@ -89,7 +60,7 @@ pub async fn set_model_weight_cover_image_handler(
|
||||
http_request: HttpRequest,
|
||||
path: Path<SetModelWeightCoverImagePathInfo>,
|
||||
request: web::Json<SetModelWeightCoverImageRequest>,
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, SetModelWeightCoverImageError>
|
||||
server_state: web::Data<Arc<ServerState>>) -> Result<HttpResponse, CommonWebError>
|
||||
{
|
||||
let maybe_user_session = server_state
|
||||
.session_checker
|
||||
@@ -97,14 +68,14 @@ pub async fn set_model_weight_cover_image_handler(
|
||||
.await
|
||||
.map_err(|e| {
|
||||
warn!("Session checker error: {:?}", e);
|
||||
SetModelWeightCoverImageError::ServerError
|
||||
CommonWebError::from_error(e)
|
||||
})?;
|
||||
|
||||
let user_session = match maybe_user_session {
|
||||
Some(session) => session,
|
||||
None => {
|
||||
warn!("not logged in");
|
||||
return Err(SetModelWeightCoverImageError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -122,11 +93,11 @@ pub async fn set_model_weight_cover_image_handler(
|
||||
Ok(Some(model_weight)) => model_weight,
|
||||
Ok(None) => {
|
||||
warn!("Model weight not found: {:?}", &path.token);
|
||||
return Err(SetModelWeightCoverImageError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up model_weights : {:?}", err);
|
||||
return Err(SetModelWeightCoverImageError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -134,7 +105,7 @@ pub async fn set_model_weight_cover_image_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to edit this media_file: {:?}", user_session.user_token);
|
||||
return Err(SetModelWeightCoverImageError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let mut maybe_set_media_file_token = None;
|
||||
@@ -156,11 +127,11 @@ pub async fn set_model_weight_cover_image_handler(
|
||||
Ok(Some(media_file)) => media_file,
|
||||
Ok(None) => {
|
||||
warn!("Media file not found: {:?}", media_file_token);
|
||||
return Err(SetModelWeightCoverImageError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
},
|
||||
Err(err) => {
|
||||
warn!("Error looking up model_weights : {:?}", err);
|
||||
return Err(SetModelWeightCoverImageError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -170,7 +141,7 @@ pub async fn set_model_weight_cover_image_handler(
|
||||
let can_use_image = media_file.media_type == MediaFileType::Image;
|
||||
|
||||
if !can_use_image {
|
||||
return Err(SetModelWeightCoverImageError::BadInput("Invalid media file token.".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("Invalid media file token.".to_string()));
|
||||
}
|
||||
|
||||
maybe_set_media_file_token = Some(media_file.token);
|
||||
@@ -190,7 +161,7 @@ pub async fn set_model_weight_cover_image_handler(
|
||||
Ok(_) => {},
|
||||
Err(err) => {
|
||||
warn!("Update MediaFile DB error: {:?}", err);
|
||||
return Err(SetModelWeightCoverImageError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
+18
-47
@@ -10,6 +10,7 @@ use sqlx::MySqlPool;
|
||||
use utoipa::ToSchema;
|
||||
|
||||
use crate::configs::supported_languages_for_models::{get_canonicalized_language_tag_for_model, get_primary_language_subtag};
|
||||
use crate::http_server::common_responses::common_web_error::CommonWebError;
|
||||
use crate::http_server::web_utils::user_session::require_user_session::RequireUserSessionError;
|
||||
use crate::http_server::web_utils::user_session::require_user_session_extended_using_connection::require_user_session_extended_using_connection;
|
||||
use crate::state::server_state::ServerState;
|
||||
@@ -60,37 +61,7 @@ pub struct UpdateWeightPathInfo {
|
||||
}
|
||||
|
||||
// =============== Error Response ===============
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub enum UpdateWeightError {
|
||||
BadInput(String),
|
||||
NotFound,
|
||||
NotAuthorized,
|
||||
ServerError,
|
||||
}
|
||||
|
||||
impl ResponseError for UpdateWeightError {
|
||||
fn status_code(&self) -> StatusCode {
|
||||
match *self {
|
||||
UpdateWeightError::BadInput(_) => StatusCode::BAD_REQUEST,
|
||||
UpdateWeightError::NotFound => StatusCode::NOT_FOUND,
|
||||
UpdateWeightError::NotAuthorized => StatusCode::UNAUTHORIZED,
|
||||
UpdateWeightError::ServerError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
}
|
||||
}
|
||||
|
||||
fn error_response(&self) -> HttpResponse {
|
||||
serialize_as_json_error(self)
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Not using derive_more::Display since Clion doesn't understand it.
|
||||
impl fmt::Display for UpdateWeightError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
// =============== Handler ===============
|
||||
|
||||
/// Handle updates to model weight metadata (using sparse field updates!)
|
||||
@@ -100,9 +71,9 @@ impl fmt::Display for UpdateWeightError {
|
||||
path = "/v1/weights/weight/{weight_token}",
|
||||
responses(
|
||||
(status = 200, description = "Success Update", body = SimpleGenericJsonSuccess),
|
||||
(status = 400, description = "Bad input", body = UpdateWeightError),
|
||||
(status = 401, description = "Not authorized", body = UpdateWeightError),
|
||||
(status = 500, description = "Server error", body = UpdateWeightError),
|
||||
(status = 400, description = "Bad input", body = CommonWebError),
|
||||
(status = 401, description = "Not authorized", body = CommonWebError),
|
||||
(status = 500, description = "Server error", body = CommonWebError),
|
||||
),
|
||||
params(
|
||||
("request" = UpdateWeightRequest, description = "Payload for Request"),
|
||||
@@ -115,13 +86,13 @@ pub async fn update_weight_handler(
|
||||
request: web::Json<UpdateWeightRequest>,
|
||||
mysql_pool: web::Data<MySqlPool>,
|
||||
server_state: web::Data<Arc<ServerState>>
|
||||
) -> Result<HttpResponse, UpdateWeightError> {
|
||||
) -> Result<HttpResponse, CommonWebError> {
|
||||
let mut mysql_connection = mysql_pool
|
||||
.acquire()
|
||||
.await
|
||||
.map_err(|err| {
|
||||
warn!("could not acquire mysql connection: {:?}", err);
|
||||
UpdateWeightError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
})?;
|
||||
|
||||
let user_session = require_user_session_extended_using_connection(
|
||||
@@ -130,10 +101,10 @@ pub async fn update_weight_handler(
|
||||
&mut mysql_connection)
|
||||
.await
|
||||
.map_err(|err| match err {
|
||||
RequireUserSessionError::NotAuthorized => UpdateWeightError::NotAuthorized,
|
||||
RequireUserSessionError::NotAuthorized => CommonWebError::NotAuthorized,
|
||||
_ => {
|
||||
warn!("get user session error: {:?}", err);
|
||||
UpdateWeightError::ServerError
|
||||
CommonWebError::from_error(err)
|
||||
},
|
||||
})?;
|
||||
|
||||
@@ -152,11 +123,11 @@ pub async fn update_weight_handler(
|
||||
Ok(Some(weight)) => weight,
|
||||
Ok(None) => {
|
||||
warn!("Weight not found: {:?}", weight_token);
|
||||
return Err(UpdateWeightError::NotFound);
|
||||
return Err(CommonWebError::NotFound);
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("Error looking up weight: {:?}", err);
|
||||
return Err(UpdateWeightError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -166,7 +137,7 @@ pub async fn update_weight_handler(
|
||||
|
||||
if !is_creator && !is_mod {
|
||||
warn!("user is not allowed to edit this weight: {:?}", user_session.user_token);
|
||||
return Err(UpdateWeightError::NotAuthorized);
|
||||
return Err(CommonWebError::NotAuthorized);
|
||||
}
|
||||
|
||||
let mut weight_title = None;
|
||||
@@ -178,7 +149,7 @@ pub async fn update_weight_handler(
|
||||
|
||||
if let Some(title) = &request.title {
|
||||
if contains_slurs(title) {
|
||||
return Err(UpdateWeightError::BadInput("Title contains slurs".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("Title contains slurs".to_string()));
|
||||
}
|
||||
weight_title = Some(title.trim().to_string());
|
||||
}
|
||||
@@ -193,22 +164,22 @@ pub async fn update_weight_handler(
|
||||
&server_state.mysql_pool
|
||||
).await.map_err(|err| {
|
||||
warn!("Error looking up media file: {:?}", err);
|
||||
UpdateWeightError::ServerError
|
||||
CommonWebError::from_anyhow_error(err)
|
||||
})?;
|
||||
|
||||
let maybe_media_file_type = maybe_media_file.map(|media_file| media_file.media_type);
|
||||
|
||||
match maybe_media_file_type {
|
||||
Some(MediaFileType::Image) => cover_image = Some(CoverImageOption::SetCoverImage(media_file_token)),
|
||||
None => return Err(UpdateWeightError::BadInput("Media file does not exist".to_string())),
|
||||
_ => return Err(UpdateWeightError::BadInput("Media file is the wrong type".to_string())),
|
||||
None => return Err(CommonWebError::BadInputWithSimpleMessage("Media file does not exist".to_string())),
|
||||
_ => return Err(CommonWebError::BadInputWithSimpleMessage("Media file is the wrong type".to_string())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(markdown) = &request.description_markdown {
|
||||
if contains_slurs(markdown) {
|
||||
return Err(UpdateWeightError::BadInput("Description contains slurs".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("Description contains slurs".to_string()));
|
||||
}
|
||||
let markdown = markdown.trim().to_string();
|
||||
let html = simple_markdown_to_html(&markdown);
|
||||
@@ -226,7 +197,7 @@ pub async fn update_weight_handler(
|
||||
WeightsType::HifiganTacotron2 => {}
|
||||
WeightsType::VallE => {}
|
||||
_ => {
|
||||
return Err(UpdateWeightError::BadInput("Language tag is not applicable to this model type".to_string()));
|
||||
return Err(CommonWebError::BadInputWithSimpleMessage("Language tag is not applicable to this model type".to_string()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,7 +227,7 @@ pub async fn update_weight_handler(
|
||||
Ok(()) => {}
|
||||
Err(err) => {
|
||||
warn!("Update Weight DB error: {:?}", err);
|
||||
return Err(UpdateWeightError::ServerError);
|
||||
return Err(CommonWebError::from_anyhow_error(err));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user