From 5a57e48fcbc45abeaa6b35b404da83dc911d56ce Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Thu, 5 Mar 2026 09:38:00 -0500 Subject: [PATCH] Bt modify mod user lookup (#1101) --- ...59ccdd66bc8b096547e89c68b58b04dd44e4.json} | 6 ++--- ...457c26d93c3be52921ad9b3531fd88498194.json} | 26 +++++++++++++++++-- ...dbb730244bbd764a49d519473e50751a3ddc.json} | 26 +++++++++++++++++-- ...a98688fec46bb1cba20d005bc8dad4d1c093.json} | 26 +++++++++++++++++-- .../src/moderation/user/user_lookup.rs | 7 ++++- .../user/user_lookup_by_stripe_customer_id.rs | 3 ++- .../user/get/lookup_user_for_moderation.rs | 14 +++++++--- .../lookup_users_by_stripe_customer_id.rs | 5 ++-- .../user/moderator_user_lookup_handler.rs | 5 +++- 9 files changed, 101 insertions(+), 17 deletions(-) rename .sqlx/{query-5ac058d9ebc84ffbd94e0997522f794aadaea55400527bcfe99f0a5e9678fcf7.json => query-3390084f700ef2444691a02c691a59ccdd66bc8b096547e89c68b58b04dd44e4.json} (69%) rename .sqlx/{query-d7980481552925c47afb4a2a94ad34a24f845b0b7395483b316e22dc8ccda3e0.json => query-97599bdc5467b8750d2546cc6f78457c26d93c3be52921ad9b3531fd88498194.json} (85%) rename .sqlx/{query-ed1ef2c6aeaaf33053807758524bb9cb4672a0c19e58723964eb265d3187751a.json => query-d023eb33c9a06f8b07b1e5d1e255dbb730244bbd764a49d519473e50751a3ddc.json} (85%) rename .sqlx/{query-c59b2997ec10c611ce6ebe4ee813145ea297dd9dfebef64c4359cf68e720760f.json => query-fd92483d9f1849d5b7f04076446fa98688fec46bb1cba20d005bc8dad4d1c093.json} (85%) diff --git a/.sqlx/query-5ac058d9ebc84ffbd94e0997522f794aadaea55400527bcfe99f0a5e9678fcf7.json b/.sqlx/query-3390084f700ef2444691a02c691a59ccdd66bc8b096547e89c68b58b04dd44e4.json similarity index 69% rename from .sqlx/query-5ac058d9ebc84ffbd94e0997522f794aadaea55400527bcfe99f0a5e9678fcf7.json rename to .sqlx/query-3390084f700ef2444691a02c691a59ccdd66bc8b096547e89c68b58b04dd44e4.json index 2c735a8213..6487817971 100644 --- a/.sqlx/query-5ac058d9ebc84ffbd94e0997522f794aadaea55400527bcfe99f0a5e9678fcf7.json +++ b/.sqlx/query-3390084f700ef2444691a02c691a59ccdd66bc8b096547e89c68b58b04dd44e4.json @@ -1,11 +1,11 @@ { "db_name": "MySQL", - "query": "\nSELECT\n user_subscriptions.subscription_namespace,\n user_subscriptions.maybe_stripe_subscription_id,\n users.token as `user_token: tokens::tokens::users::UserToken`,\n users.email_address,\n users.username,\n users.display_name\nFROM user_subscriptions\nINNER JOIN users ON users.token = user_subscriptions.user_token\nWHERE\n user_subscriptions.maybe_stripe_customer_id = ?\n AND user_subscriptions.deleted_at IS NULL\n AND users.user_deleted_at IS NULL\n AND users.mod_deleted_at IS NULL\nORDER BY user_subscriptions.created_at DESC\n ", + "query": "\nSELECT\n user_subscriptions.subscription_namespace as `subscription_namespace: enums::common::payments_namespace::PaymentsNamespace`,\n user_subscriptions.maybe_stripe_subscription_id,\n users.token as `user_token: tokens::tokens::users::UserToken`,\n users.email_address,\n users.username,\n users.display_name\nFROM user_subscriptions\nINNER JOIN users ON users.token = user_subscriptions.user_token\nWHERE\n user_subscriptions.maybe_stripe_customer_id = ?\n AND user_subscriptions.deleted_at IS NULL\n AND users.user_deleted_at IS NULL\n AND users.mod_deleted_at IS NULL\nORDER BY user_subscriptions.created_at DESC\n ", "describe": { "columns": [ { "ordinal": 0, - "name": "subscription_namespace", + "name": "subscription_namespace: enums::common::payments_namespace::PaymentsNamespace", "type_info": { "type": "VarString", "flags": "NOT_NULL | MULTIPLE_KEY | BINARY | NO_DEFAULT_VALUE", @@ -76,5 +76,5 @@ false ] }, - "hash": "5ac058d9ebc84ffbd94e0997522f794aadaea55400527bcfe99f0a5e9678fcf7" + "hash": "3390084f700ef2444691a02c691a59ccdd66bc8b096547e89c68b58b04dd44e4" } diff --git a/.sqlx/query-d7980481552925c47afb4a2a94ad34a24f845b0b7395483b316e22dc8ccda3e0.json b/.sqlx/query-97599bdc5467b8750d2546cc6f78457c26d93c3be52921ad9b3531fd88498194.json similarity index 85% rename from .sqlx/query-d7980481552925c47afb4a2a94ad34a24f845b0b7395483b316e22dc8ccda3e0.json rename to .sqlx/query-97599bdc5467b8750d2546cc6f78457c26d93c3be52921ad9b3531fd88498194.json index 5ddc9b3840..148749417a 100644 --- a/.sqlx/query-d7980481552925c47afb4a2a94ad34a24f845b0b7395483b316e22dc8ccda3e0.json +++ b/.sqlx/query-97599bdc5467b8750d2546cc6f78457c26d93c3be52921ad9b3531fd88498194.json @@ -1,6 +1,6 @@ { "db_name": "MySQL", - "query": "\nSELECT\n users.token as `user_token: tokens::tokens::users::UserToken`,\n username,\n display_name,\n username_is_generated as `username_is_generated: bool`,\n is_temporary as `is_temporary: bool`,\n username_is_not_customized as `username_is_not_customized: bool`,\n email_address,\n email_confirmed as `email_confirmed: bool`,\n email_is_synthetic as `email_is_synthetic: bool`,\n is_without_password as `is_without_password: bool`,\n ip_address_creation,\n ip_address_last_login,\n maybe_avatar_media_file_token as `maybe_avatar_media_file_token: tokens::tokens::media_files::MediaFileToken`,\n email_gravatar_hash,\n created_at\nFROM users\nWHERE\n users.username = ?\n AND users.user_deleted_at IS NULL\n AND users.mod_deleted_at IS NULL\nLIMIT 1\n ", + "query": "\nSELECT\n users.token as `user_token: tokens::tokens::users::UserToken`,\n username,\n display_name,\n username_is_generated as `username_is_generated: bool`,\n is_temporary as `is_temporary: bool`,\n username_is_not_customized as `username_is_not_customized: bool`,\n email_address,\n email_confirmed as `email_confirmed: bool`,\n email_is_synthetic as `email_is_synthetic: bool`,\n is_without_password as `is_without_password: bool`,\n ip_address_creation,\n ip_address_last_login,\n maybe_avatar_media_file_token as `maybe_avatar_media_file_token: tokens::tokens::media_files::MediaFileToken`,\n email_gravatar_hash,\n is_banned as `is_banned: bool`,\n created_at,\n updated_at\nFROM users\nWHERE\n users.username = ?\n AND users.user_deleted_at IS NULL\n AND users.mod_deleted_at IS NULL\nLIMIT 1\n ", "describe": { "columns": [ { @@ -145,6 +145,16 @@ }, { "ordinal": 14, + "name": "is_banned: bool", + "type_info": { + "type": "Tiny", + "flags": "NOT_NULL", + "char_set": 63, + "max_size": 1 + } + }, + { + "ordinal": 15, "name": "created_at", "type_info": { "type": "Timestamp", @@ -152,6 +162,16 @@ "char_set": 63, "max_size": 19 } + }, + { + "ordinal": 16, + "name": "updated_at", + "type_info": { + "type": "Timestamp", + "flags": "NOT_NULL | BINARY | TIMESTAMP | ON_UPDATE_NOW", + "char_set": 63, + "max_size": 19 + } } ], "parameters": { @@ -172,8 +192,10 @@ false, true, false, + false, + false, false ] }, - "hash": "d7980481552925c47afb4a2a94ad34a24f845b0b7395483b316e22dc8ccda3e0" + "hash": "97599bdc5467b8750d2546cc6f78457c26d93c3be52921ad9b3531fd88498194" } diff --git a/.sqlx/query-ed1ef2c6aeaaf33053807758524bb9cb4672a0c19e58723964eb265d3187751a.json b/.sqlx/query-d023eb33c9a06f8b07b1e5d1e255dbb730244bbd764a49d519473e50751a3ddc.json similarity index 85% rename from .sqlx/query-ed1ef2c6aeaaf33053807758524bb9cb4672a0c19e58723964eb265d3187751a.json rename to .sqlx/query-d023eb33c9a06f8b07b1e5d1e255dbb730244bbd764a49d519473e50751a3ddc.json index 8bad48be8d..7cc415a1b6 100644 --- a/.sqlx/query-ed1ef2c6aeaaf33053807758524bb9cb4672a0c19e58723964eb265d3187751a.json +++ b/.sqlx/query-d023eb33c9a06f8b07b1e5d1e255dbb730244bbd764a49d519473e50751a3ddc.json @@ -1,6 +1,6 @@ { "db_name": "MySQL", - "query": "\nSELECT\n users.token as `user_token: tokens::tokens::users::UserToken`,\n username,\n display_name,\n username_is_generated as `username_is_generated: bool`,\n is_temporary as `is_temporary: bool`,\n username_is_not_customized as `username_is_not_customized: bool`,\n email_address,\n email_confirmed as `email_confirmed: bool`,\n email_is_synthetic as `email_is_synthetic: bool`,\n is_without_password as `is_without_password: bool`,\n ip_address_creation,\n ip_address_last_login,\n maybe_avatar_media_file_token as `maybe_avatar_media_file_token: tokens::tokens::media_files::MediaFileToken`,\n email_gravatar_hash,\n created_at\nFROM users\nWHERE\n users.email_address = ?\n AND users.user_deleted_at IS NULL\n AND users.mod_deleted_at IS NULL\nLIMIT 1\n ", + "query": "\nSELECT\n users.token as `user_token: tokens::tokens::users::UserToken`,\n username,\n display_name,\n username_is_generated as `username_is_generated: bool`,\n is_temporary as `is_temporary: bool`,\n username_is_not_customized as `username_is_not_customized: bool`,\n email_address,\n email_confirmed as `email_confirmed: bool`,\n email_is_synthetic as `email_is_synthetic: bool`,\n is_without_password as `is_without_password: bool`,\n ip_address_creation,\n ip_address_last_login,\n maybe_avatar_media_file_token as `maybe_avatar_media_file_token: tokens::tokens::media_files::MediaFileToken`,\n email_gravatar_hash,\n is_banned as `is_banned: bool`,\n created_at,\n updated_at\nFROM users\nWHERE\n users.email_address = ?\n AND users.user_deleted_at IS NULL\n AND users.mod_deleted_at IS NULL\nLIMIT 1\n ", "describe": { "columns": [ { @@ -145,6 +145,16 @@ }, { "ordinal": 14, + "name": "is_banned: bool", + "type_info": { + "type": "Tiny", + "flags": "NOT_NULL", + "char_set": 63, + "max_size": 1 + } + }, + { + "ordinal": 15, "name": "created_at", "type_info": { "type": "Timestamp", @@ -152,6 +162,16 @@ "char_set": 63, "max_size": 19 } + }, + { + "ordinal": 16, + "name": "updated_at", + "type_info": { + "type": "Timestamp", + "flags": "NOT_NULL | BINARY | TIMESTAMP | ON_UPDATE_NOW", + "char_set": 63, + "max_size": 19 + } } ], "parameters": { @@ -172,8 +192,10 @@ false, true, false, + false, + false, false ] }, - "hash": "ed1ef2c6aeaaf33053807758524bb9cb4672a0c19e58723964eb265d3187751a" + "hash": "d023eb33c9a06f8b07b1e5d1e255dbb730244bbd764a49d519473e50751a3ddc" } diff --git a/.sqlx/query-c59b2997ec10c611ce6ebe4ee813145ea297dd9dfebef64c4359cf68e720760f.json b/.sqlx/query-fd92483d9f1849d5b7f04076446fa98688fec46bb1cba20d005bc8dad4d1c093.json similarity index 85% rename from .sqlx/query-c59b2997ec10c611ce6ebe4ee813145ea297dd9dfebef64c4359cf68e720760f.json rename to .sqlx/query-fd92483d9f1849d5b7f04076446fa98688fec46bb1cba20d005bc8dad4d1c093.json index bf4accb88b..b032332c01 100644 --- a/.sqlx/query-c59b2997ec10c611ce6ebe4ee813145ea297dd9dfebef64c4359cf68e720760f.json +++ b/.sqlx/query-fd92483d9f1849d5b7f04076446fa98688fec46bb1cba20d005bc8dad4d1c093.json @@ -1,6 +1,6 @@ { "db_name": "MySQL", - "query": "\nSELECT\n users.token as `user_token: tokens::tokens::users::UserToken`,\n username,\n display_name,\n username_is_generated as `username_is_generated: bool`,\n is_temporary as `is_temporary: bool`,\n username_is_not_customized as `username_is_not_customized: bool`,\n email_address,\n email_confirmed as `email_confirmed: bool`,\n email_is_synthetic as `email_is_synthetic: bool`,\n is_without_password as `is_without_password: bool`,\n ip_address_creation,\n ip_address_last_login,\n maybe_avatar_media_file_token as `maybe_avatar_media_file_token: tokens::tokens::media_files::MediaFileToken`,\n email_gravatar_hash,\n created_at\nFROM users\nWHERE\n users.token = ?\n AND users.user_deleted_at IS NULL\n AND users.mod_deleted_at IS NULL\nLIMIT 1\n ", + "query": "\nSELECT\n users.token as `user_token: tokens::tokens::users::UserToken`,\n username,\n display_name,\n username_is_generated as `username_is_generated: bool`,\n is_temporary as `is_temporary: bool`,\n username_is_not_customized as `username_is_not_customized: bool`,\n email_address,\n email_confirmed as `email_confirmed: bool`,\n email_is_synthetic as `email_is_synthetic: bool`,\n is_without_password as `is_without_password: bool`,\n ip_address_creation,\n ip_address_last_login,\n maybe_avatar_media_file_token as `maybe_avatar_media_file_token: tokens::tokens::media_files::MediaFileToken`,\n email_gravatar_hash,\n is_banned as `is_banned: bool`,\n created_at,\n updated_at\nFROM users\nWHERE\n users.token = ?\n AND users.user_deleted_at IS NULL\n AND users.mod_deleted_at IS NULL\nLIMIT 1\n ", "describe": { "columns": [ { @@ -145,6 +145,16 @@ }, { "ordinal": 14, + "name": "is_banned: bool", + "type_info": { + "type": "Tiny", + "flags": "NOT_NULL", + "char_set": 63, + "max_size": 1 + } + }, + { + "ordinal": 15, "name": "created_at", "type_info": { "type": "Timestamp", @@ -152,6 +162,16 @@ "char_set": 63, "max_size": 19 } + }, + { + "ordinal": 16, + "name": "updated_at", + "type_info": { + "type": "Timestamp", + "flags": "NOT_NULL | BINARY | TIMESTAMP | ON_UPDATE_NOW", + "char_set": 63, + "max_size": 19 + } } ], "parameters": { @@ -172,8 +192,10 @@ false, true, false, + false, + false, false ] }, - "hash": "c59b2997ec10c611ce6ebe4ee813145ea297dd9dfebef64c4359cf68e720760f" + "hash": "fd92483d9f1849d5b7f04076446fa98688fec46bb1cba20d005bc8dad4d1c093" } diff --git a/crates/api_clients/artcraft/artcraft_api_defs/src/moderation/user/user_lookup.rs b/crates/api_clients/artcraft/artcraft_api_defs/src/moderation/user/user_lookup.rs index d9956df1f9..f06766b118 100644 --- a/crates/api_clients/artcraft/artcraft_api_defs/src/moderation/user/user_lookup.rs +++ b/crates/api_clients/artcraft/artcraft_api_defs/src/moderation/user/user_lookup.rs @@ -1,5 +1,7 @@ +use chrono::{DateTime, Utc}; use serde_derive::{Deserialize, Serialize}; use tokens::tokens::media_files::MediaFileToken; +use tokens::tokens::users::UserToken; use utoipa::ToSchema; pub const MODERATOR_USER_LOOKUP_PATH: &str = "/v1/moderation/users/lookup"; @@ -17,7 +19,7 @@ pub struct ModeratorUserLookupSuccessResponse { #[derive(Serialize, ToSchema)] pub struct ModeratorUserLookupUserDetails { - pub token: String, + pub token: UserToken, pub username: String, pub display_name: String, pub username_is_generated: bool, @@ -31,4 +33,7 @@ pub struct ModeratorUserLookupUserDetails { pub ip_address_last_login: String, pub maybe_avatar_media_file_token: Option, pub email_gravatar_hash: String, + pub is_banned: bool, + pub created_at: DateTime, + pub updated_at: DateTime, } diff --git a/crates/api_clients/artcraft/artcraft_api_defs/src/moderation/user/user_lookup_by_stripe_customer_id.rs b/crates/api_clients/artcraft/artcraft_api_defs/src/moderation/user/user_lookup_by_stripe_customer_id.rs index 7cae29b8ce..46636aa2a1 100644 --- a/crates/api_clients/artcraft/artcraft_api_defs/src/moderation/user/user_lookup_by_stripe_customer_id.rs +++ b/crates/api_clients/artcraft/artcraft_api_defs/src/moderation/user/user_lookup_by_stripe_customer_id.rs @@ -1,3 +1,4 @@ +use enums::common::payments_namespace::PaymentsNamespace; use serde_derive::{Deserialize, Serialize}; use tokens::tokens::users::UserToken; use utoipa::ToSchema; @@ -17,7 +18,7 @@ pub struct ModeratorUserLookupByStripeCustomerIdResponse { #[derive(Serialize, ToSchema)] pub struct ModeratorUserLookupByStripeCustomerIdEntry { - pub subscription_namespace: String, + pub subscription_namespace: PaymentsNamespace, pub maybe_stripe_subscription_id: Option, pub token: UserToken, pub email_address: String, diff --git a/crates/schema/database/mysql_queries/src/queries/users/user/get/lookup_user_for_moderation.rs b/crates/schema/database/mysql_queries/src/queries/users/user/get/lookup_user_for_moderation.rs index 675cae3be0..1b9f12f067 100644 --- a/crates/schema/database/mysql_queries/src/queries/users/user/get/lookup_user_for_moderation.rs +++ b/crates/schema/database/mysql_queries/src/queries/users/user/get/lookup_user_for_moderation.rs @@ -22,7 +22,9 @@ pub struct LookupUserForModerationResult { pub ip_address_last_login: String, pub maybe_avatar_media_file_token: Option, pub email_gravatar_hash: String, + pub is_banned: bool, pub created_at: DateTime, + pub updated_at: DateTime, } pub async fn lookup_user_for_moderation_by_token( @@ -47,7 +49,9 @@ SELECT ip_address_last_login, maybe_avatar_media_file_token as `maybe_avatar_media_file_token: tokens::tokens::media_files::MediaFileToken`, email_gravatar_hash, - created_at + is_banned as `is_banned: bool`, + created_at, + updated_at FROM users WHERE users.token = ? @@ -94,7 +98,9 @@ SELECT ip_address_last_login, maybe_avatar_media_file_token as `maybe_avatar_media_file_token: tokens::tokens::media_files::MediaFileToken`, email_gravatar_hash, - created_at + is_banned as `is_banned: bool`, + created_at, + updated_at FROM users WHERE users.email_address = ? @@ -141,7 +147,9 @@ SELECT ip_address_last_login, maybe_avatar_media_file_token as `maybe_avatar_media_file_token: tokens::tokens::media_files::MediaFileToken`, email_gravatar_hash, - created_at + is_banned as `is_banned: bool`, + created_at, + updated_at FROM users WHERE users.username = ? diff --git a/crates/schema/database/mysql_queries/src/queries/users/user_subscriptions/lookup_users_by_stripe_customer_id.rs b/crates/schema/database/mysql_queries/src/queries/users/user_subscriptions/lookup_users_by_stripe_customer_id.rs index 60c327d3c7..e3a57fae54 100644 --- a/crates/schema/database/mysql_queries/src/queries/users/user_subscriptions/lookup_users_by_stripe_customer_id.rs +++ b/crates/schema/database/mysql_queries/src/queries/users/user_subscriptions/lookup_users_by_stripe_customer_id.rs @@ -2,11 +2,12 @@ use anyhow::anyhow; use log::warn; use sqlx::MySqlPool; +use enums::common::payments_namespace::PaymentsNamespace; use errors::AnyhowResult; use tokens::tokens::users::UserToken; pub struct UserByStripeCustomerIdResult { - pub subscription_namespace: String, + pub subscription_namespace: PaymentsNamespace, pub maybe_stripe_subscription_id: Option, pub user_token: UserToken, pub email_address: String, @@ -22,7 +23,7 @@ pub async fn lookup_users_by_stripe_customer_id( UserByStripeCustomerIdResult, r#" SELECT - user_subscriptions.subscription_namespace, + user_subscriptions.subscription_namespace as `subscription_namespace: enums::common::payments_namespace::PaymentsNamespace`, user_subscriptions.maybe_stripe_subscription_id, users.token as `user_token: tokens::tokens::users::UserToken`, users.email_address, diff --git a/crates/service/web/storyteller_web/src/http_server/endpoints/moderation/user/moderator_user_lookup_handler.rs b/crates/service/web/storyteller_web/src/http_server/endpoints/moderation/user/moderator_user_lookup_handler.rs index a3fba4a7dc..59de640b32 100644 --- a/crates/service/web/storyteller_web/src/http_server/endpoints/moderation/user/moderator_user_lookup_handler.rs +++ b/crates/service/web/storyteller_web/src/http_server/endpoints/moderation/user/moderator_user_lookup_handler.rs @@ -68,7 +68,7 @@ pub async fn moderator_user_lookup_handler( })?; let maybe_user_details = maybe_user.map(|user| ModeratorUserLookupUserDetails { - token: user.user_token.to_string(), + token: user.user_token, username: user.username, display_name: user.display_name, username_is_generated: user.username_is_generated, @@ -82,6 +82,9 @@ pub async fn moderator_user_lookup_handler( ip_address_last_login: user.ip_address_last_login, maybe_avatar_media_file_token: user.maybe_avatar_media_file_token, email_gravatar_hash: user.email_gravatar_hash, + is_banned: user.is_banned, + created_at: user.created_at, + updated_at: user.updated_at, }); Ok(Json(ModeratorUserLookupSuccessResponse {