From 347fe685cd31abb363c2d7bbbf85b8505a53a604 Mon Sep 17 00:00:00 2001 From: Michael Chung Date: Wed, 29 Nov 2023 23:11:47 -0500 Subject: [PATCH] List list_availible_weights needs testing but is written. --- .../weights/list_availible_weights.rs | 244 ++++++++++++++++++ .../src/http_server/endpoints/weights/mod.rs | 4 +- 2 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 crates/service/web/storyteller_web/src/http_server/endpoints/weights/list_availible_weights.rs diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/weights/list_availible_weights.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/weights/list_availible_weights.rs new file mode 100644 index 0000000000..3e134413d1 --- /dev/null +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/weights/list_availible_weights.rs @@ -0,0 +1,244 @@ +use std::sync::Arc; + +use actix_web::{ HttpRequest, HttpResponse, web }; +use actix_web::error::ResponseError; +use actix_web::http::StatusCode; +use chrono::{ DateTime, Utc }; +use log::{ info, warn }; + +use enums::common::visibility::Visibility; +use mysql_queries::queries::model_weights::list_weights_query_builder::ListWeightsQueryBuilder; +use mysql_queries::queries::model_weights::update_weight::{ update_weights, UpdateWeightArgs }; +use tokens::tokens::model_weights::ModelWeightToken; + +use crate::http_server::common_responses::user_details_lite::UserDetailsLight; +use crate::server_state::ServerState; + +#[derive(Deserialize)] +pub struct ListAvailibleWeightsQuery { + pub sort_ascending: Option, + pub limit: Option, + pub cursor: Option, + pub cursor_is_reversed: Option, +} + +#[derive(Serialize)] +pub struct ListAvailibleWeightsSuccessResponse { + pub success: bool, + pub weights: Vec, + pub cursor_next: Option, + pub cursor_previous: Option, +} + +#[derive(Serialize)] +pub struct ModelWeightForList { + pub weight_token: ModelWeightToken, + pub title: String, + + + pub weights_type: WeightsType, + pub weights_category: WeightsCategory, + + pub title: String, + + pub maybe_thumbnail_token: Option, + + pub description_markdown: String, + pub description_rendered_html: String, + + pub creator_user_token: UserToken, + pub creator_ip_address: String, + pub creator_set_visibility: Visibility, + + pub maybe_last_update_user_token: Option, + + pub file_size_bytes: i32, + pub file_checksum_sha2: String, + + pub cached_user_ratings_total_count: u32, + pub cached_user_ratings_positive_count: u32, + pub cached_user_ratings_negative_count: u32, + pub maybe_cached_user_ratings_ratio: Option, + pub cached_user_ratings_last_updated_at: DateTime, + + pub version: i32, + + pub created_at: DateTime, + pub updated_at: DateTime, + + pub creator_username: String, + pub creator_display_name: String, + pub creator_email_gravatar_hash: String, +} + +#[derive(Debug)] +pub enum ListWeightError { + NotAuthorized, + ServerError, +} + +impl std::fmt::Display for ListWeightError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self) + } +} + +impl ResponseError for ListWeightError { + fn status_code(&self) -> StatusCode { + match *self { + ListWeightError::NotAuthorized => StatusCode::UNAUTHORIZED, + ListWeightError::ServerError => StatusCode::INTERNAL_SERVER_ERROR, + } + } +} + +pub async fn list_availible_weights_handler( + http_request: HttpRequest, + query: web::Query, + 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); + ListWeightError::ServerError + })?; + + let mut is_mod = false; + let user_session = match maybe_user_session { + Some(session) => { + is_mod = session.can_ban_users; + session + } + None => { + info!("not logged in"); + return Err(ListWeightError::NotAuthorized); + } + }; + + let limit = query.limit.unwrap_or(25); + + let sort_ascending = query.sort_ascending.unwrap_or(false); + let cursor_is_reversed = query.cursor_is_reversed.unwrap_or(false); + + let cursor = if let Some(cursor) = query.cursor.as_deref() { + let cursor = server_state.sort_key_crypto.decrypt_id(cursor) + .map_err(|e| { + warn!("crypto error: {:?}", e); + ListWeightError::ServerError + })?; + Some(cursor) + } else { + None + }; + + let include_user_hidden = is_mod; + + let mut query_builder = ListWeightsQueryBuilder::new() + .sort_ascending(sort_ascending) + .scope_creator_username(None) + .include_user_hidden(include_user_hidden) + .include_user_deleted_results(is_mod) + .include_mod_deleted_results(is_mod) + .limit(limit) + .cursor_is_reversed(cursor_is_reversed) + .offset(cursor); + + let query_results = query_builder.perform_query_for_page(&server_state.mysql_pool).await; + + + let weights_page = match query_results { + Ok(results) => results, + Err(e) => { + warn!("Query error: {:?}", e); + return Err(ListWeightError::ServerError); + } + }; + + let cursor_next = if let Some(id) = weights_page.last_id { + let cursor = server_state.sort_key_crypto.encrypt_id(id as u64) + .map_err(|e| { + warn!("crypto error: {:?}", e); + ListWeightError::ServerError + })?; + Some(cursor) + } else { + None + }; + + let cursor_previous = if let Some(id) = weights_page.first_id { + let cursor = server_state.sort_key_crypto.encrypt_id(id as u64) + .map_err(|e| { + warn!("crypto error: {:?}", e); + ListWeightError::ServerError + })?; + Some(cursor) + } else { + None + }; + + + // generate parse a response + let response = ListAvailibleWeightsSuccessResponse { + success: true, + weights: weights_page.weights.into_iter() + .map(|weights| ModelWeightForList { + weight_token: weights.token, + title: weights.title, + + weights_type: WeightsType, + weights_category: WeightsCategory, + + title: String, + + maybe_thumbnail_token: Option, + + description_markdown: String, + description_rendered_html: String, + + creator_user_token: UserToken, + creator_ip_address: String, + creator_set_visibility: Visibility, + + maybe_last_update_user_token: Option, + + original_download_url: Option, + original_filename: Option, + + file_size_bytes: i32, + file_checksum_sha2: String, + + private_bucket_hash: String, + + maybe_private_bucket_prefix: Option, + maybe_private_bucket_extension: Option, + + cached_user_ratings_total_count: u32, + cached_user_ratings_positive_count: u32, + cached_user_ratings_negative_count: u32, + maybe_cached_user_ratings_ratio: Option, + cached_user_ratings_last_updated_at: DateTime, + + version: i32, + + created_at: DateTime, + updated_at: DateTime, + + user_deleted_at: Option>, + mod_deleted_at: Option>, + + creator_username: String, + creator_display_name: String, + creator_email_gravatar_hash: String, + }).collect::>(), + cursor_next, + cursor_previous, + }; + + let body = serde_json::to_string(&response) + .map_err(|e| ListWeightError::ServerError)?; + + + Ok(HttpResponse::Ok().content_type("application/json").body(body)) +} diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/weights/mod.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/weights/mod.rs index afc73c47a8..66601e374d 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/weights/mod.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/weights/mod.rs @@ -1,3 +1,5 @@ pub mod get_weight; pub mod delete_weight; -pub mod update_weight; \ No newline at end of file +pub mod update_weight; +pub mod list_weights_by_user; +pub mod list_availible_weights; \ No newline at end of file