From c9852699535bcccc39ba1932001b95d2c19c7ab5 Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Fri, 11 Jun 2021 00:11:21 -0400 Subject: [PATCH] list bans endpoint (not tested) --- migrations/2021-06-09-010200_ip_bans/up.sql | 4 +- .../endpoints/moderation/list_ip_bans.rs | 155 ++++++++++++++++++ src/main.rs | 6 + 3 files changed, 163 insertions(+), 2 deletions(-) diff --git a/migrations/2021-06-09-010200_ip_bans/up.sql b/migrations/2021-06-09-010200_ip_bans/up.sql index ae200476df..6c71635b98 100644 --- a/migrations/2021-06-09-010200_ip_bans/up.sql +++ b/migrations/2021-06-09-010200_ip_bans/up.sql @@ -7,7 +7,7 @@ CREATE TABLE ip_address_bans ( id BIGINT(20) NOT NULL AUTO_INCREMENT, -- The IP address to ban - ip_address VARCHAR(40) DEFAULT NULL, + ip_address VARCHAR(40) NOT NULL, -- Maybe the target user. maybe_target_user_token VARCHAR(32) DEFAULT NULL, @@ -16,7 +16,7 @@ CREATE TABLE ip_address_bans ( mod_user_token VARCHAR(32) NOT NULL, -- Optional notes about the ban. - mod_notes TEXT DEFAULT NULL, + mod_notes TEXT NOT NULL, -- Moderator can set an expire time (optional). -- If not set, the ban is indefinite diff --git a/src/http_server/endpoints/moderation/list_ip_bans.rs b/src/http_server/endpoints/moderation/list_ip_bans.rs index e69de29bb2..d34a68d096 100644 --- a/src/http_server/endpoints/moderation/list_ip_bans.rs +++ b/src/http_server/endpoints/moderation/list_ip_bans.rs @@ -0,0 +1,155 @@ +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::database_helpers::enums::{DownloadUrlType, CreatorSetVisibility, W2lTemplateType}; +use crate::http_server::web_utils::ip_address::get_request_ip; +use crate::http_server::web_utils::response_error_helpers::to_simple_json_error; +use crate::http_server::web_utils::response_success_helpers::simple_json_success; +use crate::server_state::ServerState; +use crate::util::random_prefix_crockford_token::random_prefix_crockford_token; +use crate::validations::check_for_slurs::contains_slurs; +use crate::validations::model_uploads::validate_model_title; +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::error::DatabaseError; +use sqlx::error::Error::Database; +use sqlx::mysql::MySqlDatabaseError; +use std::sync::Arc; + +#[derive(Deserialize)] +pub struct ListIpBansRequest { + delete: bool, +} + +#[derive(Serialize)] +pub struct ListIpBansResponse { + pub success: bool, + pub ip_address_bans: Vec, +} + +#[derive(Serialize)] +pub struct IpBanRecordForList { + pub ip_address: String, + pub maybe_target_user_token: Option, + pub maybe_target_username: Option, + pub mod_user_token: String, + pub mod_notes: String, + pub created_at: DateTime, + pub updated_at: DateTime, +} + +#[derive(Debug, Display)] +pub enum ListIpBansError { + BadInput(String), + ServerError, + Unauthorized, +} + +impl ResponseError for ListIpBansError { + fn status_code(&self) -> StatusCode { + match *self { + ListIpBansError::BadInput(_) => StatusCode::BAD_REQUEST, + ListIpBansError::ServerError => StatusCode::INTERNAL_SERVER_ERROR, + ListIpBansError::Unauthorized => StatusCode::UNAUTHORIZED, + } + } + + fn error_response(&self) -> HttpResponse { + let error_reason = match self { + ListIpBansError::BadInput(reason) => reason.to_string(), + ListIpBansError::ServerError => "server error".to_string(), + ListIpBansError::Unauthorized => "unauthorized".to_string(), + }; + + to_simple_json_error(&error_reason, self.status_code()) + } +} + +pub async fn list_ip_bans_handler( + http_request: HttpRequest, + request: web::Json, + 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); + ListIpBansError::ServerError + })?; + + let user_session = match maybe_user_session { + Some(session) => session, + None => { + warn!("not logged in"); + return Err(ListIpBansError::Unauthorized); + } + }; + + if !user_session.can_ban_users { + warn!("user is not allowed to delete bans: {}", user_session.user_token); + return Err(ListIpBansError::Unauthorized); + } + + // NB: Lookup failure is Err(RowNotFound). + let maybe_results = sqlx::query_as!( + IpBanRecordForList, + r#" +SELECT + ip_bans.ip_address, + ip_bans.maybe_target_user_token, + users.username as maybe_target_username, + ip_bans.mod_user_token, + ip_bans.mod_notes, + ip_bans.created_at, + ip_bans.updated_at +FROM + ip_address_bans AS ip_bans +LEFT OUTER JOIN users + ON ip_bans.maybe_target_user_token = users.token + "#, + ) + .fetch_all(&server_state.mysql_pool) + .await; + + let results : Vec = match maybe_results { + Ok(results) => { + info!("Results length: {}", results.len()); + results + }, + Err(err) => { + match err { + RowNotFound => { + Vec::new() + }, + _ => { + warn!("list ip bans db error: {:?}", err); + return Err(ListIpBansError::ServerError); + } + } + } + }; + + let response = ListIpBansResponse { + success: true, + ip_address_bans: results, + }; + + let body = serde_json::to_string(&response) + .map_err(|e| ListIpBansError::ServerError)?; + + Ok(HttpResponse::Ok() + .content_type("application/json") + .body(body)) +} diff --git a/src/main.rs b/src/main.rs index 2ace0fcce6..dbf508e495 100644 --- a/src/main.rs +++ b/src/main.rs @@ -79,6 +79,7 @@ use crate::http_server::endpoints::w2l::delete_w2l_result::delete_w2l_inference_ use crate::http_server::endpoints::tts::delete_tts_result::delete_tts_inference_result_handler; use crate::http_server::endpoints::moderation::add_ip_ban::add_ip_ban_handler; use crate::http_server::endpoints::moderation::delete_ip_ban::delete_ip_ban_handler; +use crate::http_server::endpoints::moderation::list_ip_bans::list_ip_bans_handler; // TODO TODO TODO TODO // TODO TODO TODO TODO @@ -283,6 +284,11 @@ pub async fn serve(server_state: ServerState) -> AnyhowResult<()> web::scope("/moderation") .service( web::scope("/ip_bans") + .service( + web::resource("/list") + .route(web::get().to(list_ip_bans_handler)) + .route(web::head().to(|| HttpResponse::Ok())) + ) .service( web::resource("/add") .route(web::post().to(add_ip_ban_handler))