From ab974cecb2e8404d5f82f7bb5acd3da5e9c9291c Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Sun, 12 Sep 2021 01:12:56 -0400 Subject: [PATCH] add new pending w2l templates endpoint --- src/http_server/endpoints/moderation/mod.rs | 1 + .../endpoints/moderation/pending/mod.rs | 1 + .../pending/pending_w2l_templates.rs | 182 ++++++++++++++++++ src/main.rs | 14 ++ 4 files changed, 198 insertions(+) create mode 100644 src/http_server/endpoints/moderation/pending/mod.rs create mode 100644 src/http_server/endpoints/moderation/pending/pending_w2l_templates.rs diff --git a/src/http_server/endpoints/moderation/mod.rs b/src/http_server/endpoints/moderation/mod.rs index bddfab2dcb..bb4c0313a2 100644 --- a/src/http_server/endpoints/moderation/mod.rs +++ b/src/http_server/endpoints/moderation/mod.rs @@ -1,5 +1,6 @@ pub mod ip_bans; pub mod jobs; +pub mod pending; pub mod user_bans; pub mod user_roles; pub mod users; \ No newline at end of file diff --git a/src/http_server/endpoints/moderation/pending/mod.rs b/src/http_server/endpoints/moderation/pending/mod.rs new file mode 100644 index 0000000000..9f34ef78bf --- /dev/null +++ b/src/http_server/endpoints/moderation/pending/mod.rs @@ -0,0 +1 @@ +pub mod pending_w2l_templates; \ No newline at end of file diff --git a/src/http_server/endpoints/moderation/pending/pending_w2l_templates.rs b/src/http_server/endpoints/moderation/pending/pending_w2l_templates.rs new file mode 100644 index 0000000000..e502cea6b9 --- /dev/null +++ b/src/http_server/endpoints/moderation/pending/pending_w2l_templates.rs @@ -0,0 +1,182 @@ +use actix_http::Error; +use actix_http::http::header; +use actix_web::cookie::Cookie; +use actix_web::dev::HttpResponseBuilder; +use actix_web::error::ResponseError; +use actix_web::http::StatusCode; +use actix_web::web::Path; +use actix_web::{Responder, web, HttpResponse, error, HttpRequest}; +use chrono::{DateTime, Utc}; +use crate::http_server::web_utils::serialize_as_json_error::serialize_as_json_error; +use crate::server_state::ServerState; +use log::{info, warn, log}; +use sqlx::error::DatabaseError; +use sqlx::error::Error::Database; +use sqlx::mysql::MySqlDatabaseError; +use std::fmt; +use std::sync::Arc; + +#[derive(Serialize)] +pub struct GetPendingW2lTemplatesResponse { + pub success: bool, + pub templates: Vec, +} + +#[derive(Serialize)] +pub struct PendingW2lTemplate { + pub template_token: String, + pub title: String, + pub template_type: String, + pub duration_millis: i32, + pub frame_width: i32, + pub frame_height: i32, + pub creator_user_token: String, + pub creator_username: String, + pub creator_display_name: String, + pub creator_gravatar_hash: String, + pub created_at: DateTime, +} + +#[derive(Debug, Serialize)] +pub enum GetPendingW2lTemplatesError { + ServerError, + Unauthorized, +} + +impl ResponseError for GetPendingW2lTemplatesError { + fn status_code(&self) -> StatusCode { + match *self { + GetPendingW2lTemplatesError::ServerError => StatusCode::INTERNAL_SERVER_ERROR, + GetPendingW2lTemplatesError::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 GetPendingW2lTemplatesError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +pub async fn get_pending_w2l_templates_handler( + http_request: HttpRequest, + 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); + GetPendingW2lTemplatesError::ServerError + })?; + + let user_session = match maybe_user_session { + Some(session) => session, + None => { + warn!("not logged in"); + return Err(GetPendingW2lTemplatesError::Unauthorized); + } + }; + + if !user_session.can_approve_w2l_templates { + warn!("user is not allowed to approve w2l templates: {}", user_session.user_token); + return Err(GetPendingW2lTemplatesError::Unauthorized); + } + + // NB: Lookup failure is Err(RowNotFound). + let maybe_results = sqlx::query_as!( + PendingW2lTemplatesRaw, + r#" +SELECT + w2l_templates.token as template_token, + w2l_templates.title, + w2l_templates.template_type, + w2l_templates.duration_millis, + w2l_templates.frame_width, + w2l_templates.frame_height, + w2l_templates.creator_user_token, + users.username AS creator_username, + users.display_name AS creator_display_name, + users.email_gravatar_hash AS creator_gravatar_hash, + w2l_templates.created_at +FROM + w2l_templates +JOIN + users +ON + users.token = w2l_templates.creator_user_token +WHERE + w2l_templates.is_public_listing_approved IS NULL + AND w2l_templates.user_deleted_at IS NULL + AND w2l_templates.mod_deleted_at IS NULL + AND w2l_templates.is_locked_from_use IS FALSE + "#, + ) + .fetch_all(&server_state.mysql_pool) + .await; + + let results : Vec = match maybe_results { + Ok(results) => results, + Err(err) => { + match err { + RowNotFound => { + Vec::new() + }, + _ => { + warn!("list pending w2l db error: {:?}", err); + return Err(GetPendingW2lTemplatesError::ServerError) + } + } + } + }; + + let results = results.iter().map(|r| { + PendingW2lTemplate { + template_token: r.template_token.clone(), + title: r.title.clone(), + template_type: r.template_type.clone(), + duration_millis: r.duration_millis, + frame_width: r.frame_width, + frame_height: r.frame_height, + creator_user_token: r.creator_user_token.clone(), + creator_username: r.creator_username.clone(), + creator_display_name: r.creator_display_name.clone(), + creator_gravatar_hash: r.creator_gravatar_hash.clone(), + created_at: r.created_at.clone(), + } + }).collect::>(); + + let response = GetPendingW2lTemplatesResponse { + success: true, + templates: results, + }; + + let body = serde_json::to_string(&response) + .map_err(|e| GetPendingW2lTemplatesError::ServerError)?; + + Ok(HttpResponse::Ok() + .content_type("application/json") + .body(body)) +} + +#[derive(Serialize)] +pub struct PendingW2lTemplatesRaw { + pub template_token: String, + pub title: String, + pub template_type: String, + pub duration_millis: i32, + pub frame_width: i32, + pub frame_height: i32, + pub creator_user_token: String, + pub creator_username: String, + pub creator_display_name: String, + pub creator_gravatar_hash: String, + pub created_at: DateTime, +} diff --git a/src/main.rs b/src/main.rs index f0fd377d17..092c7fcaaf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,6 +45,7 @@ use crate::http_server::endpoints::moderation::ip_bans::get_ip_ban::get_ip_ban_h use crate::http_server::endpoints::moderation::ip_bans::list_ip_bans::list_ip_bans_handler; use crate::http_server::endpoints::moderation::jobs::get_tts_inference_queue_count::get_tts_inference_queue_count_handler; use crate::http_server::endpoints::moderation::jobs::get_w2l_inference_queue_count::get_w2l_inference_queue_count_handler; +use crate::http_server::endpoints::moderation::pending::pending_w2l_templates::get_pending_w2l_templates_handler; use crate::http_server::endpoints::moderation::user_bans::ban_user::ban_user_handler; use crate::http_server::endpoints::moderation::user_bans::list_banned_users::list_banned_users_handler; use crate::http_server::endpoints::moderation::user_roles::list_roles::list_user_roles_handler; @@ -448,6 +449,19 @@ pub async fn serve(server_state: ServerState) -> AnyhowResult<()> .route(web::head().to(|| HttpResponse::Ok())) ) ) + .service( + web::scope("/pending") + .service( + web::resource("/w2l_templates") + .route(web::get().to(get_pending_w2l_templates_handler)) + .route(web::head().to(|| HttpResponse::Ok())) + ) + .service( + web::resource("/w2l_inference_queue_stats") + .route(web::get().to(get_w2l_inference_queue_count_handler)) + .route(web::head().to(|| HttpResponse::Ok())) + ) + ) ) // ==================== TTS ==================== .service(