From 4fbe9f54e0bca4090a9028b61fdab67adb4e386a Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Sat, 4 Jul 2026 11:53:00 -0400 Subject: [PATCH] more cleanup (#1734) --- ...t_assigned_tts_categories_query_builder.rs | 279 ------------------ .../tts/tts_category_assignments/mod.rs | 1 - .../tts/list_tts_model_assigned_categories.rs | 143 --------- .../categories/tts/mod.rs | 1 - .../routes/legacy_routes/add_legacy_routes.rs | 9 - 5 files changed, 433 deletions(-) delete mode 100644 crates/schema/database/mysql_queries/src/queries/tts/tts_category_assignments/list_assigned_tts_categories_query_builder.rs delete mode 100644 crates/service/web/storyteller_web/src/http_server/deprecated_endpoints/categories/tts/list_tts_model_assigned_categories.rs diff --git a/crates/schema/database/mysql_queries/src/queries/tts/tts_category_assignments/list_assigned_tts_categories_query_builder.rs b/crates/schema/database/mysql_queries/src/queries/tts/tts_category_assignments/list_assigned_tts_categories_query_builder.rs deleted file mode 100644 index f5bd643639..0000000000 --- a/crates/schema/database/mysql_queries/src/queries/tts/tts_category_assignments/list_assigned_tts_categories_query_builder.rs +++ /dev/null @@ -1,279 +0,0 @@ -use chrono::{DateTime, Utc}; -use sqlx::{MySql, MySqlPool}; -use sqlx::pool::PoolConnection; - -use errors::AnyhowResult; - -use crate::helpers::boolean_converters::{i8_to_bool, nullable_i8_to_optional_bool}; - -/// List of assigned categories for a TTS model -/// This is *NOT* paginated, as that defeats the purpose of having a category system. -#[derive(Serialize)] -pub struct AssignedCategoryList { - pub categories: Vec, -} - -#[derive(Serialize)] -pub struct AssignedCategory { - pub category_token: String, - - pub model_type: String, // TODO: ENUM - - pub maybe_super_category_token: Option, - - pub can_directly_have_models: bool, - pub can_have_subcategories: bool, - pub can_only_mods_apply: bool, - - pub name: String, - pub maybe_dropdown_name: Option, - - pub category_creator_user_token: Option, - pub category_creator_username: Option, - pub category_creator_display_name: Option, - pub category_creator_gravatar_hash: Option, - - // Moderator fields - pub is_mod_approved: Option, - pub maybe_mod_comments: Option, - //pub maybe_mod_user_token: Option, - //pub maybe_mod_username: Option, - //pub maybe_mod_display_name: Option, - - pub category_created_at: DateTime, - pub category_updated_at: DateTime, - pub category_deleted_at: Option>, - - pub category_assignment_created_at: DateTime, - pub category_assignment_updated_at: DateTime, - pub category_assignment_deleted_at: Option>, -} - -/// Query Builder for listing categories -/// These are very difficult queries, so the builder helps for -/// testability, construction, and correctness. -pub struct ListAssignedTtsCategoriesQueryBuilder { - // REQUIRED. - scope_tts_model_token: String, - - // Sometimes "can_directly_have_models" categories change state. - // Mods will want to see invalid uses. - show_invalid_model_not_allowed_categories: bool, - - // The public lists won't include unapproved, but mod views - // will want to see them. - show_unapproved: bool, - - // The public lists won't include deleted models, but mod views - // will want to see them. - show_deleted: bool, -} - -impl ListAssignedTtsCategoriesQueryBuilder { - pub fn for_model_token(model_token: &str) -> Self { - Self { - scope_tts_model_token: model_token.to_string(), - show_invalid_model_not_allowed_categories: false, - show_unapproved: false, - show_deleted: false, - } - } - - pub fn show_invalid_model_not_allowed_categories(mut self, show_invalid_model_not_allowed_categories: bool) -> Self { - self.show_invalid_model_not_allowed_categories = show_invalid_model_not_allowed_categories; - self - } - - pub fn show_unapproved(mut self, show_unapproved: bool) -> Self { - self.show_unapproved = show_unapproved; - self - } - - pub fn show_deleted(mut self, show_deleted: bool) -> Self { - self.show_deleted = show_deleted; - self - } - - /// Perform the query based on the set predicates. - #[deprecated = "Use the PoolConnection method instead of the MySqlPool one."] - pub async fn perform_query( - &self, - mysql_pool: &MySqlPool - ) -> AnyhowResult { - let mut mysql_connection = mysql_pool.acquire().await?; - self.perform_query_by_connection(&mut mysql_connection).await - } - - /// Perform the query based on the set predicates. - pub async fn perform_query_by_connection( - &self, - mysql_connection: &mut PoolConnection - ) -> AnyhowResult { - - let internal_results = self.perform_internal_query(mysql_connection).await?; - - let categories = internal_results - .into_iter() - .map(|c| { - AssignedCategory { - category_token: c.category_token, - model_type: c.model_type, - maybe_super_category_token: c.maybe_super_category_token, - can_directly_have_models: i8_to_bool(c.can_directly_have_models), - can_have_subcategories: i8_to_bool(c.can_have_subcategories), - can_only_mods_apply: i8_to_bool(c.can_only_mods_apply), - name: c.name, - maybe_dropdown_name: c.maybe_dropdown_name, - category_creator_user_token: c.category_creator_user_token, - category_creator_username: c.category_creator_username, - category_creator_display_name: c.category_creator_display_name, - category_creator_gravatar_hash: c.category_creator_gravatar_hash, - is_mod_approved: nullable_i8_to_optional_bool(c.is_mod_approved), - maybe_mod_comments: c.maybe_mod_comments, - category_created_at: c.category_created_at, - category_updated_at: c.category_updated_at, - category_deleted_at: c.category_deleted_at, - category_assignment_created_at: c.category_assignment_created_at, - category_assignment_updated_at: c.category_assignment_updated_at, - category_assignment_deleted_at: c.category_assignment_deleted_at, - } - }) - .collect::>(); - - Ok(AssignedCategoryList { - categories, - }) - } - - /// Perform the query based on the set predicates. - async fn perform_internal_query( - &self, - mysql_connection: &mut PoolConnection - ) -> AnyhowResult> { - - let query = self.build_query_string(); - let mut query = sqlx::query_as::<_, RawInternalCategoryRecord>(&query); - - // NB: The following bindings must match the order of the query builder !! - - // NB: Model token is always used for scoping. - query = query.bind(&self.scope_tts_model_token); - - let results = query.fetch_all(&mut **mysql_connection) - .await?; - - Ok(results) - } - - fn build_query_string(&self) -> String { - // TODO: I haven't figured out how to get field name disambiguation and type coercion working here. - // (1) tts_results.creator_set_visibility `creator_set_visibility: crate::database::enums::record_visibility::RecordVisibility`, - // Query error: no column found for name: creator_set_visibility - // (2) creator_set_visibility `creator_set_visibility: crate::database::enums::record_visibility::RecordVisibility`, - // Column 'creator_set_visibility' in field list is ambiguous - - // TODO/NB: Unfortunately SQLx can't statically typecheck this query - let mut query = r#" -SELECT - model_categories.token as category_token, - - model_categories.model_type, - - model_categories.maybe_super_category_token, - - model_categories.can_directly_have_models, - model_categories.can_have_subcategories, - model_categories.can_only_mods_apply, - - model_categories.name, - model_categories.maybe_dropdown_name, - - users.token as category_creator_user_token, - users.username as category_creator_username, - users.display_name as category_creator_display_name, - users.email_gravatar_hash as category_creator_gravatar_hash, - - model_categories.is_mod_approved, - model_categories.maybe_mod_comments, - - model_categories.created_at as category_created_at, - model_categories.updated_at as category_updated_at, - model_categories.deleted_at as category_deleted_at, - - tts_category_assignments.created_at as category_assignment_created_at, - tts_category_assignments.updated_at as category_assignment_updated_at, - tts_category_assignments.deleted_at as category_assignment_deleted_at - -FROM model_categories -JOIN tts_category_assignments - ON tts_category_assignments.category_token = model_categories.token -LEFT OUTER JOIN users - ON model_categories.creator_user_token = users.token - "#.to_string(); - - query.push_str(&self.build_predicates()); - query - } - - pub fn build_predicates(&self) -> String { - let mut query = "".to_string(); - - // Scoping to tts model is required. - query.push_str(" WHERE tts_category_assignments.model_token = ?"); - query.push_str(" AND model_categories.model_type = 'tts'"); - - // We also don't care to ever show soft-deleted assignments - query.push_str(" AND tts_category_assignments.deleted_at IS NULL"); - - if !self.show_invalid_model_not_allowed_categories { - query.push_str(" AND model_categories.can_directly_have_models IS TRUE"); - } - - if !self.show_unapproved { - query.push_str(" AND model_categories.is_mod_approved IS TRUE"); - } - - if !self.show_deleted { - query.push_str(" AND model_categories.deleted_at IS NULL"); - } - - query - } -} - -#[derive(sqlx::FromRow)] -pub struct RawInternalCategoryRecord { - pub category_token: String, - - pub model_type: String, // TODO: ENUM - - pub maybe_super_category_token: Option, - - pub can_directly_have_models: i8, - pub can_have_subcategories: i8, - pub can_only_mods_apply: i8, - - pub name: String, - pub maybe_dropdown_name: Option, - - pub category_creator_user_token: Option, - pub category_creator_username: Option, - pub category_creator_display_name: Option, - pub category_creator_gravatar_hash: Option, - - // Moderator fields - pub is_mod_approved: Option, - pub maybe_mod_comments: Option, - - pub category_created_at: DateTime, - pub category_updated_at: DateTime, - pub category_deleted_at: Option>, - - pub category_assignment_created_at: DateTime, - pub category_assignment_updated_at: DateTime, - pub category_assignment_deleted_at: Option>, -} - -#[cfg(test)] -mod tests { -} diff --git a/crates/schema/database/mysql_queries/src/queries/tts/tts_category_assignments/mod.rs b/crates/schema/database/mysql_queries/src/queries/tts/tts_category_assignments/mod.rs index dc821db4fb..3665334833 100644 --- a/crates/schema/database/mysql_queries/src/queries/tts/tts_category_assignments/mod.rs +++ b/crates/schema/database/mysql_queries/src/queries/tts/tts_category_assignments/mod.rs @@ -1,2 +1 @@ pub mod fetch_and_build_tts_model_category_map; -pub mod list_assigned_tts_categories_query_builder; \ No newline at end of file diff --git a/crates/service/web/storyteller_web/src/http_server/deprecated_endpoints/categories/tts/list_tts_model_assigned_categories.rs b/crates/service/web/storyteller_web/src/http_server/deprecated_endpoints/categories/tts/list_tts_model_assigned_categories.rs deleted file mode 100644 index 3c79f43985..0000000000 --- a/crates/service/web/storyteller_web/src/http_server/deprecated_endpoints/categories/tts/list_tts_model_assigned_categories.rs +++ /dev/null @@ -1,143 +0,0 @@ -// NB: Incrementally getting rid of build warnings... -#![forbid(unused_imports)] -#![forbid(unused_mut)] -#![forbid(unused_variables)] - -use std::sync::Arc; - -use actix_web::web::Path; -use actix_web::{web, HttpRequest, HttpResponse}; -use chrono::{DateTime, Utc}; -use log::warn; - -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 =============== - -/// For the URL PathInfo -#[derive(Deserialize)] -pub struct ListTtsModelAssignedCategoriesPathInfo { - /// TTS model token - token: String, -} - -// =============== Success Response =============== - -#[derive(Serialize)] -pub struct ListTtsModelAssignedCategoriesResponse { - pub success: bool, - pub categories: Vec, -} - -/// Public-facing and optimized (non-irrelevant fields) category list -/// Used for the main TTS dropdown as well as the TTS edit/tagging UI -#[derive(Serialize)] -pub struct DisplayCategory { - pub category_token: String, - - pub model_type: String, // TODO: ENUM - - pub maybe_super_category_token: Option, - - pub can_directly_have_models: bool, - pub can_have_subcategories: bool, - pub can_only_mods_apply: bool, - - pub name: String, - pub maybe_dropdown_name: Option, - - // NB: It's okay for non-mods to see this. - pub is_mod_approved: Option, - - pub category_created_at: DateTime, - pub category_updated_at: DateTime, - pub category_deleted_at: Option>, - - //pub creator_user_token: Option, - //pub creator_username: Option, - //pub creator_display_name: Option, -} - -// =============== Error Response =============== -// NB: Not using derive_more::Display since Clion doesn't understand it. -// =============== Handler =============== - -pub async fn list_tts_model_assigned_categories_handler( - http_request: HttpRequest, - path: Path, - server_state: web::Data>) -> Result -{ - let mut mysql_connection = server_state.mysql_pool.acquire() - .await - .map_err(|e| { - warn!("Could not acquire DB pool: {:?}", e); - CommonWebError::from_error(e) - })?; - - let maybe_user_session = server_state - .session_checker - .maybe_get_user_session_from_connection(&http_request, &mut mysql_connection) - .await - .map_err(|e| { - warn!("Session checker error: {:?}", e); - CommonWebError::from_error(e) - })?; - - // TODO: We don't have any permissions for categories. This is a proxy. - let is_mod = maybe_user_session - .map(|session| session.can_ban_users) - .unwrap_or(false); - - let query_builder = ListAssignedTtsCategoriesQueryBuilder::for_model_token(&path.token) - .show_invalid_model_not_allowed_categories(is_mod) - .show_deleted(is_mod) - .show_unapproved(is_mod); - - let query_result = - query_builder.perform_query_by_connection(&mut mysql_connection).await; - - let results = match query_result { - Ok(results) => results, - Err(err) => { - warn!("DB error: {:?}", err); - return Err(CommonWebError::from_anyhow_error(err)); - } - }; - - let mut categories = results.categories.into_iter() - .map(|c| { - DisplayCategory { - category_token: c.category_token, - model_type: c.model_type, - maybe_super_category_token: c.maybe_super_category_token, - can_directly_have_models: c.can_directly_have_models, - can_have_subcategories: c.can_have_subcategories, - can_only_mods_apply: c.can_only_mods_apply, - name: c.name.clone(), - maybe_dropdown_name:c.maybe_dropdown_name, - is_mod_approved: c.is_mod_approved, - category_created_at: c.category_created_at, - category_updated_at: c.category_updated_at, - category_deleted_at: c.category_deleted_at, - } - }) - .collect::>(); - - // TODO: Sort by dropdown name too. - categories.sort_by(|c1, c2| c1.name.cmp(&c2.name)); - - let response = ListTtsModelAssignedCategoriesResponse { - success: true, - categories, - }; - - let body = serde_json::to_string(&response) - .map_err(CommonWebError::from_error)?; - - Ok(HttpResponse::Ok() - .content_type("application/json") - .body(body)) -} diff --git a/crates/service/web/storyteller_web/src/http_server/deprecated_endpoints/categories/tts/mod.rs b/crates/service/web/storyteller_web/src/http_server/deprecated_endpoints/categories/tts/mod.rs index 3e88b8a42f..e6d3e24374 100644 --- a/crates/service/web/storyteller_web/src/http_server/deprecated_endpoints/categories/tts/mod.rs +++ b/crates/service/web/storyteller_web/src/http_server/deprecated_endpoints/categories/tts/mod.rs @@ -1,4 +1,3 @@ pub mod assign_tts_category; pub mod list_fully_computed_assigned_tts_categories; pub mod list_tts_categories; -pub mod list_tts_model_assigned_categories; diff --git a/crates/service/web/storyteller_web/src/http_server/routes/legacy_routes/add_legacy_routes.rs b/crates/service/web/storyteller_web/src/http_server/routes/legacy_routes/add_legacy_routes.rs index 793ae56bd9..79239f8e29 100644 --- a/crates/service/web/storyteller_web/src/http_server/routes/legacy_routes/add_legacy_routes.rs +++ b/crates/service/web/storyteller_web/src/http_server/routes/legacy_routes/add_legacy_routes.rs @@ -9,7 +9,6 @@ use crate::http_server::deprecated_endpoints::categories::get_category::get_cate use crate::http_server::deprecated_endpoints::categories::tts::assign_tts_category::assign_tts_category_handler; use crate::http_server::deprecated_endpoints::categories::tts::list_fully_computed_assigned_tts_categories::list_fully_computed_assigned_tts_categories::list_fully_computed_assigned_tts_categories_handler; use crate::http_server::deprecated_endpoints::categories::tts::list_tts_categories::list_tts_categories_handler; -use crate::http_server::deprecated_endpoints::categories::tts::list_tts_model_assigned_categories::list_tts_model_assigned_categories_handler; use crate::http_server::deprecated_endpoints::conversion::enqueue_fbx_to_gltf_handler::enqueue_fbx_to_gltf_handler; use crate::http_server::deprecated_endpoints::conversion::enqueue_render_engine_scene_to_video_handler::enqueue_render_engine_scene_to_video_handler; use crate::http_server::deprecated_endpoints::engine::create_scene_handler::create_scene_handler; @@ -233,14 +232,6 @@ where .route(web::head().to(|| HttpResponse::Ok())) ) ) - .service( - web::scope("/assignments") - .service( - web::resource("/tts/{token}") - .route(web::get().to(list_tts_model_assigned_categories_handler)) - .route(web::head().to(|| HttpResponse::Ok())) - ) - ) ) }