From 5eda3a9ed39c2c7ffdfe36671ca122fedf2fc2a0 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Thu, 27 May 2021 19:14:41 -0400 Subject: [PATCH] list models --- .../endpoints/tts/list_tts_models.rs | 169 ++++++++++++++++++ src/http_server/endpoints/tts/mod.rs | 3 +- .../endpoints/w2l/get_w2l_template.rs | 16 +- .../endpoints/w2l/list_w2l_templates.rs | 16 +- src/main.rs | 6 + 5 files changed, 193 insertions(+), 17 deletions(-) create mode 100644 src/http_server/endpoints/tts/list_tts_models.rs diff --git a/src/http_server/endpoints/tts/list_tts_models.rs b/src/http_server/endpoints/tts/list_tts_models.rs new file mode 100644 index 0000000000..338b573f29 --- /dev/null +++ b/src/http_server/endpoints/tts/list_tts_models.rs @@ -0,0 +1,169 @@ +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::{Responder, web, HttpResponse, error, HttpRequest, HttpMessage}; +use crate::AnyhowResult; +use crate::common_queries::sessions::create_session_for_user; +use crate::http_server::endpoints::users::create_account::CreateAccountError::{BadInput, ServerError, UsernameTaken, EmailTaken}; +use crate::http_server::endpoints::users::login::LoginSuccessResponse; +use crate::http_server::web_utils::ip_address::get_request_ip; +use crate::http_server::web_utils::session_checker::SessionRecord; +use crate::server_state::ServerState; +use crate::util::random_token::random_token; +use crate::validations::passwords::validate_passwords; +use crate::validations::username::validate_username; +use derive_more::{Display, Error}; +use log::{info, warn, log}; +use regex::Regex; +use sqlx::MySqlPool; +use sqlx::error::DatabaseError; +use sqlx::error::Error::Database; +use sqlx::mysql::MySqlDatabaseError; +use std::sync::Arc; +use chrono::{DateTime, Utc}; + +#[derive(Serialize)] +pub struct TtsModelRecordForResponse { + pub model_token: String, + pub tts_model_type: String, + pub creator_user_token: String, + pub creator_username: String, + pub creator_display_name: String, + pub updatable_slug: String, + pub title: String, + pub created_at: DateTime, + pub updated_at: DateTime, +} + +#[derive(Serialize)] +pub struct ListTtsModelsSuccessResponse { + pub success: bool, + pub templates: Vec, +} + +#[derive(Serialize)] +pub struct ErrorResponse { + pub success: bool, + pub error_reason: String, +} + +#[derive(Debug, Display)] +pub enum ListTtsModelsError { + ServerError, +} + +#[derive(Serialize)] +pub struct TtsModelRecord { + pub model_token: String, + pub tts_model_type: String, + pub creator_user_token: String, + pub creator_username: String, + pub creator_display_name: String, + pub updatable_slug: String, + pub title: String, + pub created_at: DateTime, + pub updated_at: DateTime, +} + +impl ResponseError for ListTtsModelsError { + fn status_code(&self) -> StatusCode { + match *self { + ListTtsModelsError::ServerError=> StatusCode::INTERNAL_SERVER_ERROR, + } + } + + fn error_response(&self) -> HttpResponse { + let error_reason = match self { + ListTtsModelsError::ServerError => "server error".to_string(), + }; + + let response = ErrorResponse { + success: false, + error_reason, + }; + + let body = match serde_json::to_string(&response) { + Ok(json) => json, + Err(_) => "{}".to_string(), + }; + + HttpResponseBuilder::new(self.status_code()) + .set_header(header::CONTENT_TYPE, "application/json") + .body(body) + } +} + +pub async fn list_tts_models_handler( + http_request: HttpRequest, + server_state: web::Data>) -> Result +{ + // NB: Lookup failure is Err(RowNotFound). + // NB: Since this is publicly exposed, we don't query sensitive data. + let maybe_templates = sqlx::query_as!( + TtsModelRecord, + r#" +SELECT + tts.token as model_token, + tts.tts_model_type, + tts.creator_user_token, + users.username as creator_username, + users.display_name as creator_display_name, + tts.updatable_slug, + tts.title, + tts.created_at, + tts.updated_at +FROM tts_models as tts +JOIN users +ON users.token = tts.creator_user_token +WHERE tts.deleted_at IS NULL + "#, + ) + .fetch_all(&server_state.mysql_pool) + .await; // TODO: This will return error if it doesn't exist + + let templates : Vec = match maybe_templates { + Ok(templates) => templates, + Err(err) => { + match err { + RowNotFound => { + return Err(ListTtsModelsError::ServerError); + }, + _ => { + warn!("w2l template list query error: {:?}", err); + return Err(ListTtsModelsError::ServerError); + } + } + } + }; + + let templates_for_response = templates.into_iter() + .map(|template| { + TtsModelRecordForResponse { + model_token: template.model_token.clone(), + tts_model_type: template.tts_model_type.clone(), + creator_user_token: template.creator_user_token.clone(), + creator_username: template.creator_username.clone(), + creator_display_name: template.creator_display_name.clone(), + updatable_slug: template.updatable_slug.clone(), + title: template.title.clone(), + created_at: template.created_at.clone(), + updated_at: template.updated_at.clone(), + } + }) + .collect::>(); + + let response = ListTtsModelsSuccessResponse { + success: true, + templates: templates_for_response, + }; + + let body = serde_json::to_string(&response) + .map_err(|e| ListTtsModelsError::ServerError)?; + + Ok(HttpResponse::Ok() + .content_type("application/json") + .body(body)) +} diff --git a/src/http_server/endpoints/tts/mod.rs b/src/http_server/endpoints/tts/mod.rs index 371b17ad4d..e0e4f48731 100644 --- a/src/http_server/endpoints/tts/mod.rs +++ b/src/http_server/endpoints/tts/mod.rs @@ -1,2 +1,3 @@ pub mod enqueue_infer_tts; -pub mod enqueue_upload_tts_model; \ No newline at end of file +pub mod enqueue_upload_tts_model; +pub mod list_tts_models; \ No newline at end of file diff --git a/src/http_server/endpoints/w2l/get_w2l_template.rs b/src/http_server/endpoints/w2l/get_w2l_template.rs index 455c1670b6..8a332cc10b 100644 --- a/src/http_server/endpoints/w2l/get_w2l_template.rs +++ b/src/http_server/endpoints/w2l/get_w2l_template.rs @@ -37,8 +37,8 @@ pub struct W2lTemplateRecordForResponse { pub template_token: String, pub template_type: String, pub creator_user_token: String, - pub username: String, - pub display_name: String, + pub creator_username: String, + pub creator_display_name: String, pub updatable_slug: String, pub title: String, pub frame_width: u32, @@ -72,8 +72,8 @@ pub struct W2lTemplateRecord { pub template_token: String, pub template_type: String, pub creator_user_token: String, - pub username: String, - pub display_name: String, + pub creator_username: String, + pub creator_display_name: String, pub updatable_slug: String, pub title: String, pub frame_width: i32, @@ -127,8 +127,8 @@ SELECT w2l.token as template_token, w2l.template_type, w2l.creator_user_token, - users.username, - users.display_name, + users.username as creator_username, + users.display_name as creator_display_name, w2l.updatable_slug, w2l.title, w2l.frame_width, @@ -168,8 +168,8 @@ AND w2l.deleted_at IS NULL template_token: template.template_token.clone(), template_type: template.template_type.clone(), creator_user_token: template.creator_user_token.clone(), - username: template.username.clone(), - display_name: template.display_name.clone(), + creator_username: template.creator_username.clone(), + creator_display_name: template.creator_display_name.clone(), updatable_slug: template.updatable_slug.clone(), title: template.title.clone(), frame_width: if template.frame_width > 0 { template.frame_width as u32 } else { 0 }, diff --git a/src/http_server/endpoints/w2l/list_w2l_templates.rs b/src/http_server/endpoints/w2l/list_w2l_templates.rs index 0b55d5865a..849f96a1fc 100644 --- a/src/http_server/endpoints/w2l/list_w2l_templates.rs +++ b/src/http_server/endpoints/w2l/list_w2l_templates.rs @@ -30,8 +30,8 @@ pub struct W2lTemplateRecordForResponse { pub template_token: String, pub template_type: String, pub creator_user_token: String, - pub username: String, - pub display_name: String, + pub creator_username: String, + pub creator_display_name: String, pub updatable_slug: String, pub title: String, pub frame_width: u32, @@ -65,8 +65,8 @@ pub struct W2lTemplateRecord { pub template_token: String, pub template_type: String, pub creator_user_token: String, - pub username: String, - pub display_name: String, + pub creator_username: String, + pub creator_display_name: String, pub updatable_slug: String, pub title: String, pub frame_width: i32, @@ -119,8 +119,8 @@ SELECT w2l.token as template_token, w2l.template_type, w2l.creator_user_token, - users.username, - users.display_name, + users.username as creator_username, + users.display_name as creator_display_name, w2l.updatable_slug, w2l.title, w2l.frame_width, @@ -160,8 +160,8 @@ WHERE w2l.deleted_at IS NULL template_token: template.template_token.clone(), template_type: template.template_type.clone(), creator_user_token: template.creator_user_token.clone(), - username: template.username.clone(), - display_name: template.display_name.clone(), + creator_username: template.creator_username.clone(), + creator_display_name: template.creator_display_name.clone(), updatable_slug: template.updatable_slug.clone(), title: template.title.clone(), frame_width: if template.frame_width > 0 { template.frame_width as u32 } else { 0 }, diff --git a/src/main.rs b/src/main.rs index fe1326742e..ca2100b514 100644 --- a/src/main.rs +++ b/src/main.rs @@ -46,6 +46,7 @@ use std::sync::Arc; use crate::http_server::endpoints::users::get_profile::get_profile_handler; use crate::http_server::endpoints::w2l::list_w2l_templates::list_w2l_templates_handler; use crate::http_server::endpoints::w2l::get_w2l_template::get_w2l_template_handler; +use crate::http_server::endpoints::tts::list_tts_models::list_tts_models_handler; const DEFAULT_BIND_ADDRESS : &'static str = "0.0.0.0:12345"; @@ -195,6 +196,11 @@ pub async fn serve(server_state: ServerState) -> AnyhowResult<()> .route(web::post().to(infer_tts_handler)) .route(web::head().to(|| HttpResponse::Ok())) ) + .service( + web::resource("/list") + .route(web::get().to(list_tts_models_handler)) + .route(web::head().to(|| HttpResponse::Ok())) + ) ) .service( web::scope("/w2l")