diff --git a/sqlx-data.json b/sqlx-data.json index f35d0e19d..5704b3900 100644 --- a/sqlx-data.json +++ b/sqlx-data.json @@ -825,6 +825,51 @@ "nullable": [] } }, + "389088b3ccff3a3c970aba3deef8831cca140b74ffc74e43a1162a9021428820": { + "query": "\n SELECT f.id id, f.version_id version_id, f.filename filename, v.version_number version_number, v.mod_id mod_id FROM hashes h\n INNER JOIN files f ON h.file_id = f.id\n INNER JOIN versions v ON v.id = f.version_id\n WHERE h.algorithm = $2 AND h.hash = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "version_id", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "filename", + "type_info": "Varchar" + }, + { + "ordinal": 3, + "name": "version_number", + "type_info": "Varchar" + }, + { + "ordinal": 4, + "name": "mod_id", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Bytea", + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false, + false + ] + } + }, "398ac436f5fe2f6a66544204b9ff01ae1ea1204edf03ffc16de657a861cfe0ba": { "query": "\n DELETE FROM categories\n WHERE category = $1\n ", "describe": { @@ -1220,31 +1265,16 @@ "nullable": [] } }, - "55df56cd9938bca0edbf8d91649c8ce6d946125ad64e570ab127f6d9c6061787": { - "query": "\n SELECT version_id, filename FROM files\n INNER JOIN hashes ON hash = $1 AND algorithm = $2\n ", + "5322e7791400b47640f897f3e32d9a0f2915da7d71a34c4e6bf6bd648cfaaa6e": { + "query": "\n DELETE FROM files\n WHERE files.id = $1\n ", "describe": { - "columns": [ - { - "ordinal": 0, - "name": "version_id", - "type_info": "Int8" - }, - { - "ordinal": 1, - "name": "filename", - "type_info": "Varchar" - } - ], + "columns": [], "parameters": { "Left": [ - "Bytea", - "Text" + "Int8" ] }, - "nullable": [ - false, - false - ] + "nullable": [] } }, "560c3ba57c965c3ebdbe393b062da8a30a8a7116a9bace2aa7de2e8431fe0bc7": { @@ -1489,45 +1519,6 @@ ] } }, - "6a0d8560c0a392f66023b4186834f84d822e797b0c8b5ad360ef93a2c2300319": { - "query": "\n SELECT f.url url, f.id id, f.version_id version_id, v.mod_id mod_id FROM files f\n INNER JOIN versions v ON v.id = f.version_id\n INNER JOIN hashes ON hash = $1 AND algorithm = $2\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "url", - "type_info": "Varchar" - }, - { - "ordinal": 1, - "name": "id", - "type_info": "Int8" - }, - { - "ordinal": 2, - "name": "version_id", - "type_info": "Int8" - }, - { - "ordinal": 3, - "name": "mod_id", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Bytea", - "Text" - ] - }, - "nullable": [ - false, - false, - false, - false - ] - } - }, "6b28cb8b54ef57c9b6f03607611f688455f0e2b27eb5deda5a8cbc5b506b4602": { "query": "\n DELETE FROM mods\n WHERE id = $1\n ", "describe": { @@ -2042,6 +2033,27 @@ "nullable": [] } }, + "79d30dd9fe16ac93ece0b6272811e1b644bac8f61b446dceca46a16cb69953a1": { + "query": "\n SELECT f.version_id version_id FROM hashes h\n INNER JOIN files f ON h.file_id = f.id\n WHERE h.algorithm = $2 AND h.hash = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "version_id", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Bytea", + "Text" + ] + }, + "nullable": [ + false + ] + } + }, "7bbbeecf3246a8e07ad073a07f7d057e0990a810d69ae18cec41de60b704b174": { "query": "\n SELECT id, user_id, member_name, role, permissions, accepted\n FROM team_members\n WHERE (team_id = $1 AND user_id = $2 AND accepted = TRUE)\n ", "describe": { @@ -2153,27 +2165,6 @@ "nullable": [] } }, - "96585aa2586e69eeae18f5a0c97a93d2c221c8a97470e5f59839b1a52b2e353a": { - "query": "\n SELECT version_id FROM files\n INNER JOIN hashes ON hash = $1 AND algorithm = $2\n ", - "describe": { - "columns": [ - { - "ordinal": 0, - "name": "version_id", - "type_info": "Int8" - } - ], - "parameters": { - "Left": [ - "Bytea", - "Text" - ] - }, - "nullable": [ - false - ] - } - }, "97143e41c18d191d09d244113b7b6cdf5bd6ab89c62ac46d0980d700ab288f48": { "query": "\n SELECT name FROM side_types\n WHERE id = $1\n ", "describe": { @@ -2252,18 +2243,6 @@ "nullable": [] } }, - "9ef9174fa003186a07fbf465e9ac083f6d452cf3c702c6ca05b1f3bbc0e30b5a": { - "query": "\n DELETE FROM files\n WHERE files.version_id = $1\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "Int8" - ] - }, - "nullable": [] - } - }, "a28188c4840d0f3449379b3bba6b3c4af9483e01f50fd56785317398a59881ca": { "query": "\n SELECT files.id, files.url, files.filename, files.is_primary FROM files\n WHERE files.version_id = $1\n ", "describe": { @@ -2338,6 +2317,45 @@ "nullable": [] } }, + "a8f22bd234488500b06855c8258e1e290696adba0766b46640bf87d91b150518": { + "query": "\n SELECT f.url url, f.id id, f.version_id version_id, v.mod_id mod_id FROM hashes h\n INNER JOIN files f ON h.file_id = f.id\n INNER JOIN versions v ON v.id = f.version_id\n WHERE h.algorithm = $2 AND h.hash = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "url", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 2, + "name": "version_id", + "type_info": "Int8" + }, + { + "ordinal": 3, + "name": "mod_id", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Bytea", + "Text" + ] + }, + "nullable": [ + false, + false, + false, + false + ] + } + }, "a90bb6904e1b790c0e29e060dac5ba4c2a6087e07c1197dc1f59f0aff31944c9": { "query": "\n DELETE FROM states\n WHERE expires < CURRENT_DATE\n ", "describe": { diff --git a/src/database/models/mod_item.rs b/src/database/models/mod_item.rs index 1eef19489..7f7f2b687 100644 --- a/src/database/models/mod_item.rs +++ b/src/database/models/mod_item.rs @@ -459,9 +459,9 @@ impl Mod { ", inner.client_side.0, ) - .fetch_one(executor) - .await? - .name; + .fetch_one(executor) + .await? + .name; let server_side = sqlx::query!( " @@ -470,9 +470,9 @@ impl Mod { ", inner.server_side.0, ) - .fetch_one(executor) - .await? - .name; + .fetch_one(executor) + .await? + .name; let license = sqlx::query!( " @@ -481,8 +481,8 @@ impl Mod { ", inner.license.0, ) - .fetch_one(executor) - .await?; + .fetch_one(executor) + .await?; Ok(Some(QueryMod { inner, @@ -493,7 +493,7 @@ impl Mod { license_id: license.short, license_name: license.name, client_side: crate::models::mods::SideType::from_str(&client_side), - server_side: crate::models::mods::SideType::from_str(&server_side) + server_side: crate::models::mods::SideType::from_str(&server_side), })) } else { Ok(None) diff --git a/src/main.rs b/src/main.rs index 36cdf68f4..65ff1e8ed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -173,11 +173,14 @@ async fn main() -> std::io::Result<()> { WHERE date < (CURRENT_DATE - INTERVAL '30 minutes ago') " ) - .execute(&pool_ref) - .await; + .execute(&pool_ref) + .await; if let Err(e) = downloads_result { - warn!("Deleting old records from temporary table downloads failed: {:?}", e); + warn!( + "Deleting old records from temporary table downloads failed: {:?}", + e + ); } let states_result = sqlx::query!( @@ -186,16 +189,18 @@ async fn main() -> std::io::Result<()> { WHERE expires < CURRENT_DATE " ) - .execute(&pool_ref) - .await; + .execute(&pool_ref) + .await; if let Err(e) = states_result { - warn!("Deleting old records from temporary table states failed: {:?}", e); + warn!( + "Deleting old records from temporary table states failed: {:?}", + e + ); } info!("Finished deleting old records from temporary tables"); } - }); let indexing_queue = Arc::new(search::indexing::queue::CreationQueue::new()); @@ -260,7 +265,7 @@ async fn main() -> std::io::Result<()> { scheduler::schedule_versions(&mut scheduler, pool.clone(), skip_initial); let ip_salt = Pepper { - pepper: crate::models::ids::Base62Id(crate::models::ids::random_base62(11)).to_string() + pepper: crate::models::ids::Base62Id(crate::models::ids::random_base62(11)).to_string(), }; let allowed_origins = dotenv::var("CORS_ORIGINS") diff --git a/src/routes/moderation.rs b/src/routes/moderation.rs index e9a1bb64f..4a36eebba 100644 --- a/src/routes/moderation.rs +++ b/src/routes/moderation.rs @@ -2,12 +2,12 @@ use super::ApiError; use crate::auth::check_is_moderator_from_headers; use crate::database; use crate::models; -use crate::models::mods::{ModStatus, VersionType, ModId}; -use actix_web::{get, web, HttpRequest, HttpResponse}; -use serde::{Serialize, Deserialize}; -use sqlx::PgPool; -use sqlx::types::chrono::{DateTime, Utc}; +use crate::models::mods::{ModId, ModStatus, VersionType}; use crate::models::teams::TeamId; +use actix_web::{get, web, HttpRequest, HttpResponse}; +use serde::{Deserialize, Serialize}; +use sqlx::types::chrono::{DateTime, Utc}; +use sqlx::PgPool; #[derive(Deserialize)] pub struct ResultCount { diff --git a/src/routes/mods.rs b/src/routes/mods.rs index 00d1dc585..270016f2f 100644 --- a/src/routes/mods.rs +++ b/src/routes/mods.rs @@ -350,7 +350,9 @@ pub async fn mod_edit( )); } - if (status == &ModStatus::Rejected || status == &ModStatus::Approved) && !user.role.is_mod() { + if (status == &ModStatus::Rejected || status == &ModStatus::Approved) + && !user.role.is_mod() + { return Err(ApiError::CustomAuthenticationError( "You don't have permission to set this status".to_string(), )); diff --git a/src/routes/users.rs b/src/routes/users.rs index e8c4cb9ae..cb7604f42 100644 --- a/src/routes/users.rs +++ b/src/routes/users.rs @@ -45,10 +45,7 @@ pub async fn users_get( .await .map_err(|e| ApiError::DatabaseError(e.into()))?; - let users: Vec = users_data - .into_iter() - .map(convert_user) - .collect(); + let users: Vec = users_data.into_iter().map(convert_user).collect(); Ok(HttpResponse::Ok().json(users)) } diff --git a/src/routes/versions.rs b/src/routes/versions.rs index 06694de10..10dcc9e26 100644 --- a/src/routes/versions.rs +++ b/src/routes/versions.rs @@ -1,9 +1,9 @@ use super::ApiError; use crate::auth::{check_is_moderator_from_headers, get_user_from_headers}; -use crate::{database, Pepper}; use crate::file_hosting::FileHost; use crate::models; use crate::models::teams::Permissions; +use crate::{database, Pepper}; use actix_web::{delete, get, patch, web, HttpRequest, HttpResponse}; use serde::{Deserialize, Serialize}; use sqlx::PgPool; @@ -117,23 +117,27 @@ pub async fn version_get( let user_option = get_user_from_headers(req.headers(), &**pool).await.ok(); if let Some(data) = version_data { - if let Some(user) = user_option { - if !data.accepted && !user.role.is_mod() { - let user_id: database::models::ids::UserId = user.id.into(); + if !data.accepted { + if let Some(user) = user_option { + if !user.role.is_mod() { + let user_id: database::models::ids::UserId = user.id.into(); - let member_exists = sqlx::query!( - "SELECT EXISTS(SELECT 1 FROM team_members tm INNER JOIN mods m ON m.team_id = tm.id AND m.id = $1 WHERE tm.user_id = $2)", - data.mod_id as database::models::ModId, - user_id as database::models::ids::UserId, - ) - .fetch_one(&**pool) - .await - .map_err(|e| ApiError::DatabaseError(e.into()))? - .exists; + let member_exists = sqlx::query!( + "SELECT EXISTS(SELECT 1 FROM team_members tm INNER JOIN mods m ON m.team_id = tm.id AND m.id = $1 WHERE tm.user_id = $2)", + data.mod_id as database::models::ModId, + user_id as database::models::ids::UserId, + ) + .fetch_one(&**pool) + .await + .map_err(|e| ApiError::DatabaseError(e.into()))? + .exists; - if !member_exists.unwrap_or(false) { - return Ok(HttpResponse::NotFound().body("")); + if !member_exists.unwrap_or(false) { + return Ok(HttpResponse::NotFound().body("")); + } } + } else { + return Ok(HttpResponse::NotFound().body("")); } } @@ -553,8 +557,9 @@ pub async fn get_version_from_hash( let result = sqlx::query!( " - SELECT version_id FROM files - INNER JOIN hashes ON hash = $1 AND algorithm = $2 + SELECT f.version_id version_id FROM hashes h + INNER JOIN files f ON h.file_id = f.id + WHERE h.algorithm = $2 AND h.hash = $1 ", hash.as_bytes(), algorithm.algorithm @@ -599,9 +604,10 @@ pub async fn download_version( let result = sqlx::query!( " - SELECT f.url url, f.id id, f.version_id version_id, v.mod_id mod_id FROM files f + SELECT f.url url, f.id id, f.version_id version_id, v.mod_id mod_id FROM hashes h + INNER JOIN files f ON h.file_id = f.id INNER JOIN versions v ON v.id = f.version_id - INNER JOIN hashes ON hash = $1 AND algorithm = $2 + WHERE h.algorithm = $2 AND h.hash = $1 ", hash.as_bytes(), algorithm.algorithm @@ -692,8 +698,10 @@ pub async fn delete_file( let result = sqlx::query!( " - SELECT version_id, filename FROM files - INNER JOIN hashes ON hash = $1 AND algorithm = $2 + SELECT f.id id, f.version_id version_id, f.filename filename, v.version_number version_number, v.mod_id mod_id FROM hashes h + INNER JOIN files f ON h.file_id = f.id + INNER JOIN versions v ON v.id = f.version_id + WHERE h.algorithm = $2 AND h.hash = $1 ", hash.as_bytes(), algorithm.algorithm @@ -703,62 +711,51 @@ pub async fn delete_file( .map_err(|e| ApiError::DatabaseError(e.into()))?; if let Some(row) = result { - let version_data = database::models::Version::get_full( - database::models::VersionId(row.version_id), - &**pool, - ) - .await - .map_err(|e| ApiError::DatabaseError(e.into()))?; + let mut transaction = pool + .begin() + .await + .map_err(|e| ApiError::DatabaseError(e.into()))?; - if let Some(data) = version_data { - let mut transaction = pool - .begin() - .await - .map_err(|e| ApiError::DatabaseError(e.into()))?; - - sqlx::query!( - " + sqlx::query!( + " DELETE FROM hashes WHERE hash = $1 AND algorithm = $2 ", - hash.as_bytes(), - algorithm.algorithm - ) - .execute(&mut *transaction) - .await - .map_err(|e| ApiError::DatabaseError(e.into()))?; + hash.as_bytes(), + algorithm.algorithm + ) + .execute(&mut *transaction) + .await + .map_err(|e| ApiError::DatabaseError(e.into()))?; - sqlx::query!( - " + sqlx::query!( + " DELETE FROM files - WHERE files.version_id = $1 + WHERE files.id = $1 ", - data.id as database::models::ids::VersionId, + row.id, + ) + .execute(&mut *transaction) + .await + .map_err(|e| ApiError::DatabaseError(e.into()))?; + + let mod_id: models::mods::ModId = database::models::ids::ModId(row.mod_id).into(); + file_host + .delete_file_version( + "", + &format!( + "data/{}/versions/{}/{}", + mod_id, row.version_number, row.filename + ), ) - .execute(&mut *transaction) + .await?; + + transaction + .commit() .await .map_err(|e| ApiError::DatabaseError(e.into()))?; - let mod_id: models::mods::ModId = data.mod_id.into(); - file_host - .delete_file_version( - "", - &format!( - "data/{}/versions/{}/{}", - mod_id, data.version_number, row.filename - ), - ) - .await?; - - transaction - .commit() - .await - .map_err(|e| ApiError::DatabaseError(e.into()))?; - - Ok(HttpResponse::Ok().body("")) - } else { - Ok(HttpResponse::NotFound().body("")) - } + Ok(HttpResponse::Ok().body("")) } else { Ok(HttpResponse::NotFound().body("")) }