From e46ff3de8b6a096dc46a7c4880940f5bf5ba84bb Mon Sep 17 00:00:00 2001 From: BasiqueEvangelist Date: Tue, 23 Feb 2021 18:04:10 +0300 Subject: [PATCH] Add slug validation (#168) --- sqlx-data.json | 40 ++++++++++++++++++++++++++++++++++++++ src/routes/mod_creation.rs | 23 ++++++++++++++++++++++ src/routes/mods.rs | 23 ++++++++++++++++++++++ 3 files changed, 86 insertions(+) diff --git a/sqlx-data.json b/sqlx-data.json index baa30d69d..79a47ed76 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -235,6 +235,26 @@ ] } }, + "0f29bb5ba767ebd0669c860994e48e3cb2674f0d53f6c4ab85c79d46b04cbb40": { + "query": "\n SELECT EXISTS(SELECT 1 FROM mods WHERE id=$1)\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "exists", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + null + ] + } + }, "1220d15a56dbf823eaa452fbafa17442ab0568bc81a31fa38e16e3df3278e5f9": { "query": "SELECT EXISTS(SELECT 1 FROM users WHERE id = $1)", "describe": { @@ -3188,6 +3208,26 @@ ] } }, + "ac840a3ba466cfa1f914a1e44fcc9052bd1e0e908140e7147d1ff72d1794cfbf": { + "query": "\n SELECT EXISTS(SELECT 1 FROM mods WHERE id=$1)\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "exists", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [ + null + ] + } + }, "acbafe265c4b7a1c95b0494a0a03c8bd2cd778ae561ef5a662fa931ca26cf603": { "query": "\n DELETE FROM mods_donations\n WHERE joining_mod_id = $1\n ", "describe": { diff --git a/src/routes/mod_creation.rs b/src/routes/mod_creation.rs index 45c0f3ec8..971653cbd 100644 --- a/src/routes/mod_creation.rs +++ b/src/routes/mod_creation.rs @@ -46,6 +46,8 @@ pub enum CreateError { InvalidCategory(String), #[error("Invalid file type for version file: {0}")] InvalidFileType(String), + #[error("Slug collides with other mod's id!")] + SlugCollision, #[error("Authentication Error: {0}")] Unauthorized(#[from] AuthenticationError), #[error("Authentication Error: {0}")] @@ -71,6 +73,7 @@ impl actix_web::ResponseError for CreateError { CreateError::InvalidFileType(..) => StatusCode::BAD_REQUEST, CreateError::Unauthorized(..) => StatusCode::UNAUTHORIZED, CreateError::CustomAuthenticationError(..) => StatusCode::UNAUTHORIZED, + CreateError::SlugCollision => StatusCode::BAD_REQUEST, } } @@ -93,6 +96,7 @@ impl actix_web::ResponseError for CreateError { CreateError::InvalidFileType(..) => "invalid_input", CreateError::Unauthorized(..) => "unauthorized", CreateError::CustomAuthenticationError(..) => "unauthorized", + CreateError::SlugCollision => "invalid_input", }, description: &self.to_string(), }) @@ -324,6 +328,25 @@ async fn mod_create_inner( .try_for_each(|v| super::version_creation::check_version(v))?; } + let slug_modid_option: Option = + serde_json::from_str(&*format!("\"{}\"", create_data.mod_slug)).ok(); + if let Some(slug_modid) = slug_modid_option { + let slug_modid: models::ids::ModId = slug_modid.into(); + let results = sqlx::query!( + " + SELECT EXISTS(SELECT 1 FROM mods WHERE id=$1) + ", + slug_modid as models::ids::ModId + ) + .fetch_one(&mut *transaction) + .await + .map_err(|e| CreateError::DatabaseError(e.into()))?; + + if results.exists.unwrap_or(true) { + return Err(CreateError::SlugCollision); + } + } + // Create VersionBuilders for the versions specified in `initial_versions` versions = Vec::with_capacity(create_data.initial_versions.len()); for (i, data) in create_data.initial_versions.iter().enumerate() { diff --git a/src/routes/mods.rs b/src/routes/mods.rs index d9add07a9..926dcd1c1 100644 --- a/src/routes/mods.rs +++ b/src/routes/mods.rs @@ -588,6 +588,29 @@ pub async fn mod_edit( )); } + if let Some(slug) = slug { + let slug_modid_option: Option = + serde_json::from_str(&*format!("\"{}\"", slug)).ok(); + if let Some(slug_modid) = slug_modid_option { + let slug_modid: database::models::ids::ModId = slug_modid.into(); + let results = sqlx::query!( + " + SELECT EXISTS(SELECT 1 FROM mods WHERE id=$1) + ", + slug_modid as database::models::ids::ModId + ) + .fetch_one(&mut *transaction) + .await + .map_err(|e| ApiError::DatabaseError(e.into()))?; + + if results.exists.unwrap_or(true) { + return Err(ApiError::InvalidInputError( + "Slug collides with other mod's id!".to_string(), + )); + } + } + } + sqlx::query!( " UPDATE mods