From 789dcbeacec176963b9eca1cd76719b24eb9e640 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=9F=83=E6=8B=89?= Date: Wed, 15 Jan 2025 22:12:15 +0800 Subject: [PATCH] wip: field changes in challenge --- crates/config/src/lib.rs | 6 +++ crates/db/src/entity/challenge.rs | 4 +- crates/db/src/transfer/challenge.rs | 46 ++++++++++++++++++---- crates/web/src/router/api/challenge/mod.rs | 26 +++++++----- crates/web/src/router/api/config/mod.rs | 42 ++++++++++++++------ crates/web/src/router/api/game/mod.rs | 5 ++- 6 files changed, 99 insertions(+), 30 deletions(-) diff --git a/crates/config/src/lib.rs b/crates/config/src/lib.rs index 961a7d0..1e143a4 100644 --- a/crates/config/src/lib.rs +++ b/crates/config/src/lib.rs @@ -20,6 +20,12 @@ impl From for Config { } } +impl Config { + pub fn desensitize(&mut self) { + self.auth.jwt.secret_key.clear(); + } +} + pub async fn init() { let config = cds_cache::get::("config").await.unwrap(); if config.is_none() { diff --git a/crates/db/src/entity/challenge.rs b/crates/db/src/entity/challenge.rs index a471912..7e67f35 100644 --- a/crates/db/src/entity/challenge.rs +++ b/crates/db/src/entity/challenge.rs @@ -23,7 +23,7 @@ pub struct Model { #[sea_orm(default_value = false)] pub has_attachment: bool, #[sea_orm(default_value = false)] - pub is_practicable: bool, + pub is_public: bool, pub image_name: Option, #[sea_orm(default_value = 0)] pub cpu_limit: i64, @@ -36,6 +36,8 @@ pub struct Model { pub envs: Vec, #[sea_orm(column_type = "JsonBinary")] pub flags: Vec, + #[sea_orm(default_value = false)] + pub is_deleted: bool, pub created_at: i64, pub updated_at: i64, } diff --git a/crates/db/src/transfer/challenge.rs b/crates/db/src/transfer/challenge.rs index 29d0775..5ae41e9 100644 --- a/crates/db/src/transfer/challenge.rs +++ b/crates/db/src/transfer/challenge.rs @@ -1,5 +1,10 @@ -use sea_orm::{ColumnTrait, DbErr, EntityTrait, PaginatorTrait, QueryFilter, QuerySelect}; +use std::str::FromStr; + +use sea_orm::{ + ColumnTrait, DbErr, EntityTrait, Order, PaginatorTrait, QueryFilter, QueryOrder, QuerySelect, +}; use serde::{Deserialize, Serialize}; +use tracing::debug; use crate::{ entity, @@ -16,7 +21,7 @@ pub struct Challenge { pub tags: Vec, pub is_dynamic: bool, pub has_attachment: bool, - pub is_practicable: bool, + pub is_public: bool, pub image_name: Option, pub cpu_limit: i64, pub memory_limit: i64, @@ -24,6 +29,7 @@ pub struct Challenge { pub ports: Vec, pub envs: Vec, pub flags: Vec, + pub is_deleted: bool, pub created_at: i64, pub updated_at: i64, } @@ -38,7 +44,7 @@ impl From for Challenge { tags: entity.tags, is_dynamic: entity.is_dynamic, has_attachment: entity.has_attachment, - is_practicable: entity.is_practicable, + is_public: entity.is_public, image_name: entity.image_name, cpu_limit: entity.cpu_limit, memory_limit: entity.memory_limit, @@ -46,6 +52,7 @@ impl From for Challenge { ports: entity.ports, envs: entity.envs, flags: entity.flags, + is_deleted: entity.is_deleted, created_at: entity.created_at, updated_at: entity.updated_at, } @@ -62,7 +69,7 @@ impl From for entity::challenge::Model { tags: challenge.tags, is_dynamic: challenge.is_dynamic, has_attachment: challenge.has_attachment, - is_practicable: challenge.is_practicable, + is_public: challenge.is_public, image_name: challenge.image_name, cpu_limit: challenge.cpu_limit, memory_limit: challenge.memory_limit, @@ -70,6 +77,7 @@ impl From for entity::challenge::Model { ports: challenge.ports, envs: challenge.envs, flags: challenge.flags, + is_deleted: challenge.is_deleted, created_at: challenge.created_at, updated_at: challenge.updated_at, } @@ -85,8 +93,9 @@ impl Challenge { } pub async fn find( - id: Option, title: Option, category: Option, is_practicable: Option, - is_dynamic: Option, page: Option, size: Option, + id: Option, title: Option, category: Option, is_public: Option, + is_dynamic: Option, is_deleted: Option, sorts: Option, page: Option, + size: Option, ) -> Result<(Vec, u64), DbErr> { let mut sql = entity::challenge::Entity::find(); @@ -102,16 +111,37 @@ pub async fn find( sql = sql.filter(entity::challenge::Column::Category.eq(category)); } - if let Some(is_practicable) = is_practicable { - sql = sql.filter(entity::challenge::Column::IsPracticable.eq(is_practicable)); + if let Some(is_public) = is_public { + sql = sql.filter(entity::challenge::Column::IsPublic.eq(is_public)); } if let Some(is_dynamic) = is_dynamic { sql = sql.filter(entity::challenge::Column::IsDynamic.eq(is_dynamic)); } + match is_deleted { + Some(true) => sql = sql.filter(entity::challenge::Column::IsDeleted.eq(true)), + _ => sql = sql.filter(entity::challenge::Column::IsDeleted.eq(false)), + } + let total = sql.clone().count(get_db()).await?; + if let Some(sorts) = sorts { + let sorts = sorts.split(",").collect::>(); + for sort in sorts { + let col = + match crate::entity::challenge::Column::from_str(sort.replace("-", "").as_str()) { + Ok(col) => col, + Err(_) => continue, + }; + if sort.starts_with("-") { + sql = sql.order_by(col, Order::Desc); + } else { + sql = sql.order_by(col, Order::Asc); + } + } + } + if let Some(page) = page { if let Some(size) = size { let offset = (page - 1) * size; diff --git a/crates/web/src/router/api/challenge/mod.rs b/crates/web/src/router/api/challenge/mod.rs index b257b92..0cbc268 100644 --- a/crates/web/src/router/api/challenge/mod.rs +++ b/crates/web/src/router/api/challenge/mod.rs @@ -48,11 +48,13 @@ pub struct GetRequest { pub title: Option, pub category: Option, pub tags: Option>, - pub is_practicable: Option, + pub is_public: Option, pub is_dynamic: Option, pub is_detailed: Option, + pub is_deleted: Option, pub page: Option, pub size: Option, + pub sorts: Option, } pub async fn get( @@ -67,8 +69,10 @@ pub async fn get( params.id, params.title, params.category, - params.is_practicable, + params.is_public, params.is_dynamic, + params.is_deleted, + params.sorts, params.page, params.size, ) @@ -187,7 +191,7 @@ pub struct CreateRequest { pub description: String, pub category: i32, pub tags: Option>, - pub is_practicable: Option, + pub is_public: Option, pub is_dynamic: Option, pub has_attachment: Option, pub difficulty: Option, @@ -213,7 +217,7 @@ pub async fn create( description: Set(Some(body.description)), category: Set(body.category), tags: Set(body.tags.unwrap_or(vec![])), - is_practicable: Set(body.is_practicable.unwrap_or(false)), + is_public: Set(body.is_public.unwrap_or(false)), is_dynamic: Set(body.is_dynamic.unwrap_or(false)), has_attachment: Set(body.has_attachment.unwrap_or(false)), image_name: Set(body.image_name), @@ -243,7 +247,7 @@ pub struct UpdateRequest { pub description: Option, pub category: Option, pub tags: Option>, - pub is_practicable: Option, + pub is_public: Option, pub is_dynamic: Option, pub has_attachment: Option, pub difficulty: Option, @@ -272,7 +276,7 @@ pub async fn update( description: body.description.map_or(NotSet, |v| Set(Some(v))), tags: body.tags.map_or(NotSet, Set), category: body.category.map_or(NotSet, Set), - is_practicable: body.is_practicable.map_or(NotSet, Set), + is_public: body.is_public.map_or(NotSet, Set), is_dynamic: body.is_dynamic.map_or(NotSet, Set), has_attachment: body.has_attachment.map_or(NotSet, Set), image_name: body.image_name.map_or(NotSet, |v| Set(Some(v))), @@ -303,9 +307,13 @@ pub async fn delete( return Err(WebError::Forbidden(json!(""))); } - let _ = cds_db::entity::challenge::Entity::delete_by_id(id) - .exec(get_db()) - .await?; + let _ = cds_db::entity::challenge::ActiveModel { + id: Set(id), + is_deleted: Set(true), + ..Default::default() + } + .update(get_db()) + .await?; Ok(WebResponse { code: StatusCode::OK.as_u16(), diff --git a/crates/web/src/router/api/config/mod.rs b/crates/web/src/router/api/config/mod.rs index c2fd386..fdf1001 100644 --- a/crates/web/src/router/api/config/mod.rs +++ b/crates/web/src/router/api/config/mod.rs @@ -8,10 +8,11 @@ use axum::{ use cds_config::get_config; use cds_db::{entity::user::Group, get_db}; use sea_orm::{ActiveModelTrait, ActiveValue::Set}; +use serde::{Deserialize, Serialize}; use serde_json::json; use crate::{ - extract::{Extension, Json}, + extract::{Extension, Json, Query}, traits::{Ext, WebError, WebResponse}, util::handle_image_multipart, }; @@ -25,19 +26,38 @@ pub fn router() -> Router { .route("/icon", axum::routing::delete(delete_icon)) } +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct GetRequest { + pub is_detailed: Option, +} + pub async fn get( - Extension(ext): Extension, + Extension(ext): Extension, Query(params): Query, ) -> Result, WebError> { - let operator = ext.operator.ok_or(WebError::Unauthorized(json!("")))?; - if operator.group != Group::Admin { - return Err(WebError::Forbidden(json!(""))); - } + match params.is_detailed { + Some(true) => { + let operator = ext.operator.ok_or(WebError::Unauthorized(json!("")))?; + if operator.group != Group::Admin { + return Err(WebError::Forbidden(json!(""))); + } - Ok(WebResponse { - code: StatusCode::OK.as_u16(), - data: Some(get_config().await), - ..WebResponse::default() - }) + Ok(WebResponse { + code: StatusCode::OK.as_u16(), + data: Some(get_config().await), + ..WebResponse::default() + }) + } + _ => { + let mut config = get_config().await; + config.desensitize(); + + Ok(WebResponse { + code: StatusCode::OK.as_u16(), + data: Some(config), + ..WebResponse::default() + }) + } + } } pub async fn update( diff --git a/crates/web/src/router/api/game/mod.rs b/crates/web/src/router/api/game/mod.rs index 479577e..0405713 100644 --- a/crates/web/src/router/api/game/mod.rs +++ b/crates/web/src/router/api/game/mod.rs @@ -47,7 +47,10 @@ pub async fn router() -> Router { .route("/{id}/teams/{team_id}", axum::routing::delete(delete_team)) .route("/{id}/notices", axum::routing::get(get_notice)) .route("/{id}/notices", axum::routing::post(create_notice)) - .route("/{id}/notices/{notice_id}", axum::routing::put(update_notice)) + .route( + "/{id}/notices/{notice_id}", + axum::routing::put(update_notice), + ) .route( "/{id}/notices/{notice_id}", axum::routing::delete(delete_notice),