From 133ccff348ba127ca52f7300b4107f105148722f Mon Sep 17 00:00:00 2001 From: kasisnu <5044120+kasisnu@users.noreply.github.com> Date: Wed, 29 Nov 2023 17:12:22 +0530 Subject: [PATCH] update media file visibilty handler --- .../http_server/endpoints/media_files/mod.rs | 1 + .../media_files/update_media_file.rs | 154 ++++++++++++++++++ .../service/web/storyteller_web/src/routes.rs | 5 + 3 files changed, 160 insertions(+) create mode 100644 crates/service/web/storyteller_web/src/http_server/endpoints/media_files/update_media_file.rs diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/mod.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/mod.rs index 014fa68854..4f010c38fe 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/mod.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/mod.rs @@ -1,3 +1,4 @@ pub mod drain_multipart_request; pub mod get_media_file; pub mod delete_media_file; +pub mod update_media_file; diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/update_media_file.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/update_media_file.rs new file mode 100644 index 0000000000..4d099b8bbf --- /dev/null +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/media_files/update_media_file.rs @@ -0,0 +1,154 @@ +use std::fmt; +use std::sync::Arc; + +use actix_web::{HttpRequest, HttpResponse, web}; +use actix_web::error::ResponseError; +use actix_web::http::StatusCode; +use actix_web::web::Path; +use log::{error, log, warn}; +use enums::common::visibility::Visibility; + +use http_server_common::request::get_request_ip::get_request_ip; +use http_server_common::response::response_success_helpers::simple_json_success; +use http_server_common::response::serialize_as_json_error::serialize_as_json_error; +use mysql_queries::queries::media_files::get_media_file::get_media_file; +use mysql_queries::queries::media_files::update_media_file::{update_media_file, UpdateMediaFileArgs}; +use tokens::tokens::media_files::MediaFileToken; + +use crate::server_state::ServerState; + +#[derive(Deserialize)] +pub struct UpdateMediaFileRequest { + pub creator_set_visibility: Option, +} + +#[derive(Serialize)] +pub struct UpdateMediaFileResponse { + pub success: bool, +} + +/// For the URL PathInfo +#[derive(Deserialize)] +pub struct UpdateMediaFilePathInfo { + token: MediaFileToken, +} + +// =============== 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, + request: web::Json, + server_state: web::Data>) -> Result +{ + 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); + UpdateMediaFileError::ServerError + })?; + + let user_session = match maybe_user_session { + Some(session) => session, + None => { + warn!("not logged in"); + return Err(UpdateMediaFileError::NotAuthorized); + } + }; + + let media_file_token = path.token.clone(); + let is_mod = user_session.can_ban_users; + + let media_file_lookup_result = get_media_file( + &path.token, + is_mod, + &server_state.mysql_pool, + ).await; + + let media_file = match media_file_lookup_result { + Ok(Some(media_file)) => media_file, + Ok(None) => { + warn!("MediaFile not found: {:?}", media_file_token); + return Err(UpdateMediaFileError::NotFound); + }, + Err(err) => { + warn!("Error looking up media_file: {:?}", err); + return Err(UpdateMediaFileError::ServerError); + } + }; + + let is_creator = media_file.maybe_creator_user_token + .is_some_and(|t| t.as_str() == &user_session.user_token); + + if !is_creator && !is_mod { + warn!("user is not allowed to edit this media_file: {}", user_session.user_token); + return Err(UpdateMediaFileError::NotAuthorized); + } + + let mut creator_set_visibility = Visibility::Public; + + + 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()))?; + } + + let ip_address = get_request_ip(&http_request); + let mut maybe_mod_user_token = None; + + if is_mod { + maybe_mod_user_token = Some(user_session.user_token.clone()); + } + let query_result = update_media_file( + UpdateMediaFileArgs { + media_file_token: &media_file_token.clone(), + creator_set_visibility: &creator_set_visibility, + maybe_mod_user_token: maybe_mod_user_token.as_deref(), + mysql_pool: &server_state.mysql_pool + } + ).await; + + match query_result { + Ok(_) => {}, + Err(err) => { + warn!("Update MediaFile DB error: {:?}", err); + return Err(UpdateMediaFileError::ServerError); + } + }; + + Ok(simple_json_success()) +} diff --git a/crates/service/web/storyteller_web/src/routes.rs b/crates/service/web/storyteller_web/src/routes.rs index 9b6f920061..c1cdc543eb 100644 --- a/crates/service/web/storyteller_web/src/routes.rs +++ b/crates/service/web/storyteller_web/src/routes.rs @@ -43,6 +43,7 @@ use crate::http_server::endpoints::investor_demo::enable_demo_mode_handler::enab use crate::http_server::endpoints::leaderboard::get_leaderboard::leaderboard_handler; use crate::http_server::endpoints::media_files::delete_media_file::delete_media_file_handler; use crate::http_server::endpoints::media_files::get_media_file::get_media_file_handler; +use crate::http_server::endpoints::media_files::update_media_file::update_media_file_handler; use crate::http_server::endpoints::media_uploads::list_user_media_uploads_of_type::list_user_media_uploads_of_type_handler; use crate::http_server::endpoints::media_uploads::upload_audio::upload_audio_handler; use crate::http_server::endpoints::media_uploads::upload_image::upload_image_handler; @@ -1000,6 +1001,10 @@ fn add_media_file_routes (app: App) -> App .route(web::delete().to(delete_media_file_handler)) .route(web::head().to(|| HttpResponse::Ok())) ) + .service(web::resource("/file/{token}/update") + .route(web::post().to(update_media_file_handler)) + .route(web::head().to(|| HttpResponse::Ok())) + ) ) }