diff --git a/.idea/sqldialects.xml b/.idea/sqldialects.xml index a118a4e7..6df4889b 100644 --- a/.idea/sqldialects.xml +++ b/.idea/sqldialects.xml @@ -1,9 +1,6 @@ - - - \ No newline at end of file diff --git a/sqlx-data.json b/sqlx-data.json index 82db515b..eaad57a2 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -418,6 +418,26 @@ }, "query": "\n UPDATE mods_gallery\n SET description = $2\n WHERE id = $1\n " }, + "1220d15a56dbf823eaa452fbafa17442ab0568bc81a31fa38e16e3df3278e5f9": { + "describe": { + "columns": [ + { + "name": "exists", + "ordinal": 0, + "type_info": "Bool" + } + ], + "nullable": [ + null + ], + "parameters": { + "Left": [ + "Int8" + ] + } + }, + "query": "SELECT EXISTS(SELECT 1 FROM users WHERE id = $1)" + }, "124fbf0544ea6989d6dc5e840405dbc76d7385276a38ad79d9093c53c73bbde2": { "describe": { "columns": [], @@ -1351,6 +1371,26 @@ }, "query": "\n SELECT u.id\n FROM users u\n WHERE u.stripe_customer_id = $1\n " }, + "352185977065c9903c2504081ef7c400075807785d4b62fdb48d0a45ca560f51": { + "describe": { + "columns": [ + { + "name": "exists", + "ordinal": 0, + "type_info": "Bool" + } + ], + "nullable": [ + null + ], + "parameters": { + "Left": [ + "Int8" + ] + } + }, + "query": "SELECT EXISTS(SELECT 1 FROM versions WHERE id = $1)" + }, "371048e45dd74c855b84cdb8a6a565ccbef5ad166ec9511ab20621c336446da6": { "describe": { "columns": [], @@ -1974,6 +2014,26 @@ }, "query": "\n INSERT INTO project_types (name)\n VALUES ($1)\n ON CONFLICT (name) DO NOTHING\n RETURNING id\n " }, + "4c9e2190e2a68ffc093a69aaa1fc9384957138f57ac9cd85cbc6179613c13a08": { + "describe": { + "columns": [ + { + "name": "exists", + "ordinal": 0, + "type_info": "Bool" + } + ], + "nullable": [ + null + ], + "parameters": { + "Left": [ + "Int8" + ] + } + }, + "query": "SELECT EXISTS(SELECT 1 FROM mods WHERE id = $1)" + }, "4cfafb61d38608152743c38cb8fb9a9c35e788fcbefe6f7f81476a3f144af3f8": { "describe": { "columns": [ diff --git a/src/routes/mod.rs b/src/routes/mod.rs index 4ec16818..f4d346c7 100644 --- a/src/routes/mod.rs +++ b/src/routes/mod.rs @@ -228,6 +228,8 @@ pub enum ApiError { Payments(String), #[error("Discord Error: {0}")] DiscordError(String), + #[error("Error while decoding Base62: {0}")] + Decoding(#[from] crate::models::ids::DecodingError), } impl actix_web::ResponseError for ApiError { @@ -277,6 +279,7 @@ impl actix_web::ResponseError for ApiError { ApiError::DiscordError(..) => { actix_web::http::StatusCode::FAILED_DEPENDENCY } + ApiError::Decoding(..) => actix_web::http::StatusCode::BAD_REQUEST, } } @@ -300,6 +303,7 @@ impl actix_web::ResponseError for ApiError { ApiError::Crypto(..) => "crypto_error", ApiError::Payments(..) => "payments_error", ApiError::DiscordError(..) => "discord_error", + ApiError::Decoding(..) => "decoding_error", }, description: &self.to_string(), }, diff --git a/src/routes/reports.rs b/src/routes/reports.rs index ff3dbe4a..88dff35b 100644 --- a/src/routes/reports.rs +++ b/src/routes/reports.rs @@ -1,4 +1,6 @@ -use crate::models::ids::{ProjectId, UserId, VersionId}; +use crate::models::ids::{ + base62_impl::parse_base62, ProjectId, UserId, VersionId, +}; use crate::models::reports::{ItemType, Report}; use crate::routes::ApiError; use crate::util::auth::{ @@ -65,31 +67,63 @@ pub async fn report_create( match new_report.item_type { ItemType::Project | ItemType::Mod => { - report.project_id = Some( - serde_json::from_str::(&format!( - "\"{}\"", - new_report.item_id - ))? - .into(), + let project_id = + ProjectId(parse_base62(new_report.item_id.as_str())?); + + let result = sqlx::query!( + "SELECT EXISTS(SELECT 1 FROM mods WHERE id = $1)", + project_id.0 as i64 ) + .fetch_one(&mut transaction) + .await?; + + if !result.exists.unwrap_or(false) { + return Err(ApiError::InvalidInput(format!( + "Project could not be found: {}", + new_report.item_id + ))); + } + + report.project_id = Some(project_id.into()) } ItemType::Version => { - report.version_id = Some( - serde_json::from_str::(&format!( - "\"{}\"", - new_report.item_id - ))? - .into(), + let version_id = + VersionId(parse_base62(new_report.item_id.as_str())?); + + let result = sqlx::query!( + "SELECT EXISTS(SELECT 1 FROM versions WHERE id = $1)", + version_id.0 as i64 ) + .fetch_one(&mut transaction) + .await?; + + if !result.exists.unwrap_or(false) { + return Err(ApiError::InvalidInput(format!( + "Version could not be found: {}", + new_report.item_id + ))); + } + + report.version_id = Some(version_id.into()) } ItemType::User => { - report.user_id = Some( - serde_json::from_str::(&format!( - "\"{}\"", - new_report.item_id - ))? - .into(), + let user_id = UserId(parse_base62(new_report.item_id.as_str())?); + + let result = sqlx::query!( + "SELECT EXISTS(SELECT 1 FROM users WHERE id = $1)", + user_id.0 as i64 ) + .fetch_one(&mut transaction) + .await?; + + if !result.exists.unwrap_or(false) { + return Err(ApiError::InvalidInput(format!( + "User could not be found: {}", + new_report.item_id + ))); + } + + report.user_id = Some(user_id.into()) } ItemType::Unknown => { return Err(ApiError::InvalidInput(format!(