Skip to content

Commit

Permalink
Fix duplicate file names (#927)
Browse files Browse the repository at this point in the history
* Fix duplicate file names

* Fix checks
  • Loading branch information
Geometrically committed Jun 13, 2024
1 parent b8963d2 commit 608e55c
Show file tree
Hide file tree
Showing 10 changed files with 65 additions and 98 deletions.

This file was deleted.

This file was deleted.

This file was deleted.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions src/routes/v2/version_creation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::models::projects::{
Dependency, FileType, Loader, ProjectId, Version, VersionId, VersionStatus, VersionType,
};
use crate::models::v2::projects::LegacyVersion;
use crate::queue::moderation::AutomatedModerationQueue;
use crate::queue::session::AuthQueue;
use crate::routes::v3::project_creation::CreateError;
use crate::routes::v3::version_creation;
Expand Down Expand Up @@ -87,6 +88,7 @@ pub async fn version_create(
redis: Data<RedisPool>,
file_host: Data<Arc<dyn FileHost + Send + Sync>>,
session_queue: Data<AuthQueue>,
moderation_queue: Data<AutomatedModerationQueue>,
) -> Result<HttpResponse, CreateError> {
let payload = v2_reroute::alter_actix_multipart(
payload,
Expand Down Expand Up @@ -233,6 +235,7 @@ pub async fn version_create(
redis.clone(),
file_host,
session_queue,
moderation_queue,
)
.await?;

Expand Down
2 changes: 0 additions & 2 deletions src/routes/v2/versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,6 @@ pub struct EditVersion {
pub game_versions: Option<Vec<String>>,
pub loaders: Option<Vec<models::projects::Loader>>,
pub featured: Option<bool>,
pub primary_file: Option<(String, String)>,
pub downloads: Option<u32>,
pub status: Option<VersionStatus>,
pub file_types: Option<Vec<EditVersionFileType>>,
Expand Down Expand Up @@ -278,7 +277,6 @@ pub async fn version_edit(
dependencies: new_version.dependencies,
loaders,
featured: new_version.featured,
primary_file: new_version.primary_file,
downloads: new_version.downloads,
status: new_version.status,
file_types: new_version.file_types.map(|v| {
Expand Down
6 changes: 6 additions & 0 deletions src/routes/v3/project_creation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -538,6 +538,11 @@ async fn project_create_inner(
let version_data = project_create_data.initial_versions.get(index).unwrap();
// TODO: maybe redundant is this calculation done elsewhere?

let existing_file_names = created_version
.files
.iter()
.map(|x| x.filename.clone())
.collect();
// Upload the new jar file
super::version_creation::upload_file(
&mut field,
Expand All @@ -555,6 +560,7 @@ async fn project_create_inner(
version_data.primary_file.is_some(),
version_data.primary_file.as_deref() == Some(name),
None,
existing_file_names,
transaction,
redis,
)
Expand Down
30 changes: 29 additions & 1 deletion src/routes/v3/version_creation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,13 @@ use crate::models::images::{Image, ImageContext, ImageId};
use crate::models::notifications::NotificationBody;
use crate::models::pack::PackFileHash;
use crate::models::pats::Scopes;
use crate::models::projects::{skip_nulls, DependencyType};
use crate::models::projects::{skip_nulls, DependencyType, ProjectStatus};
use crate::models::projects::{
Dependency, FileType, Loader, ProjectId, Version, VersionFile, VersionId, VersionStatus,
VersionType,
};
use crate::models::teams::ProjectPermissions;
use crate::queue::moderation::AutomatedModerationQueue;
use crate::queue::session::AuthQueue;
use crate::util::routes::read_from_field;
use crate::util::validate::validation_errors_to_string;
Expand Down Expand Up @@ -102,6 +103,7 @@ pub async fn version_create(
redis: Data<RedisPool>,
file_host: Data<Arc<dyn FileHost + Send + Sync>>,
session_queue: Data<AuthQueue>,
moderation_queue: web::Data<AutomatedModerationQueue>,
) -> Result<HttpResponse, CreateError> {
let mut transaction = client.begin().await?;
let mut uploaded_files = Vec::new();
Expand All @@ -115,6 +117,7 @@ pub async fn version_create(
&mut uploaded_files,
&client,
&session_queue,
&moderation_queue,
)
.await;

Expand Down Expand Up @@ -144,6 +147,7 @@ async fn version_create_inner(
uploaded_files: &mut Vec<UploadedFile>,
pool: &PgPool,
session_queue: &AuthQueue,
moderation_queue: &AutomatedModerationQueue,
) -> Result<HttpResponse, CreateError> {
let cdn_url = dotenvy::var("CDN_URL")?;

Expand Down Expand Up @@ -333,6 +337,8 @@ async fn version_create_inner(
.clone()
.ok_or_else(|| CreateError::InvalidInput("`data` field is required".to_string()))?;

let existing_file_names = version.files.iter().map(|x| x.filename.clone()).collect();

upload_file(
&mut field,
file_host,
Expand All @@ -349,6 +355,7 @@ async fn version_create_inner(
version_data.primary_file.is_some(),
version_data.primary_file.as_deref() == Some(name),
version_data.file_types.get(name).copied().flatten(),
existing_file_names,
transaction,
redis,
)
Expand Down Expand Up @@ -498,6 +505,19 @@ async fn version_create_inner(

models::Project::clear_cache(project_id, None, Some(true), redis).await?;

let project_status = sqlx::query!(
"SELECT status FROM mods WHERE id = $1",
project_id as models::ProjectId,
)
.fetch_optional(pool)
.await?;

if let Some(project_status) = project_status {
if project_status.status == ProjectStatus::Processing.as_str() {
moderation_queue.projects.insert(project_id.into());
}
}

Ok(HttpResponse::Ok().json(response))
}

Expand Down Expand Up @@ -706,6 +726,7 @@ async fn upload_file_to_version_inner(
true,
false,
file_data.file_types.get(name).copied().flatten(),
version.files.iter().map(|x| x.filename.clone()).collect(),
transaction,
&redis,
)
Expand Down Expand Up @@ -759,11 +780,18 @@ pub async fn upload_file(
ignore_primary: bool,
force_primary: bool,
file_type: Option<FileType>,
other_file_names: Vec<String>,
transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
redis: &RedisPool,
) -> Result<(), CreateError> {
let (file_name, file_extension) = get_name_ext(content_disposition)?;

if other_file_names.contains(&format!("{}.{}", file_name, file_extension)) {
return Err(CreateError::InvalidInput(
"Duplicate files are not allowed to be uploaded to Modrinth!".to_string(),
));
}

if file_name.contains('/') {
return Err(CreateError::InvalidInput(
"File names must not contain slashes!".to_string(),
Expand Down
43 changes: 0 additions & 43 deletions src/routes/v3/versions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ pub struct EditVersion {
pub dependencies: Option<Vec<Dependency>>,
pub loaders: Option<Vec<Loader>>,
pub featured: Option<bool>,
pub primary_file: Option<(String, String)>,
pub downloads: Option<u32>,
pub status: Option<VersionStatus>,
pub file_types: Option<Vec<EditVersionFileType>>,
Expand Down Expand Up @@ -490,48 +489,6 @@ pub async fn version_edit_helper(
.await?;
}

if let Some(primary_file) = &new_version.primary_file {
let result = sqlx::query!(
"
SELECT f.id id FROM hashes h
INNER JOIN files f ON h.file_id = f.id
WHERE h.algorithm = $2 AND h.hash = $1
",
primary_file.1.as_bytes(),
primary_file.0
)
.fetch_optional(&**pool)
.await?
.ok_or_else(|| {
ApiError::InvalidInput(format!(
"Specified file with hash {} does not exist.",
primary_file.1.clone()
))
})?;

sqlx::query!(
"
UPDATE files
SET is_primary = FALSE
WHERE (version_id = $1)
",
id as database::models::ids::VersionId,
)
.execute(&mut *transaction)
.await?;

sqlx::query!(
"
UPDATE files
SET is_primary = TRUE
WHERE (id = $1)
",
result.id,
)
.execute(&mut *transaction)
.await?;
}

if let Some(body) = &new_version.changelog {
sqlx::query!(
"
Expand Down
6 changes: 5 additions & 1 deletion src/validate/modpack.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ impl super::Validator for ModpackValidator {
(x.ends_with("jar") || x.ends_with("zip"))
&& (x.starts_with("overrides/mods")
|| x.starts_with("client-overrides/mods")
|| x.starts_with("server-overrides/mods"))
|| x.starts_with("server-overrides/mods")
|| x.starts_with("overrides/resourcepacks")
|| x.starts_with("server-overrides/resourcepacks")
|| x.starts_with("overrides/shaderpacks")
|| x.starts_with("client-overrides/shaderpacks"))
})
.flat_map(|x| x.rsplit('/').next().map(|x| x.to_string()))
.collect::<Vec<String>>(),
Expand Down

0 comments on commit 608e55c

Please sign in to comment.