Make mod creation always create initial versions & don't require mod id for mod creation versions (#79)

* Make mod creation always create initial versions, other fixes

* Fix sqlx prepare

Co-authored-by: Geometrically <18202329+Geometrically@users.noreply.github.com>
This commit is contained in:
Aeledfyr
2020-10-16 15:28:53 -05:00
committed by GitHub
parent 5c8ffe961e
commit 520b12e56b
3 changed files with 133 additions and 108 deletions
+20 -20
View File
@@ -519,26 +519,6 @@
"nullable": []
}
},
"40597b84607e77809c13ffa9c6b0b1674bd6378a4737a8f6118e91ae2ede7e4a": {
"query": "\n SELECT id\n FROM release_channels\n WHERE channel = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false
]
}
},
"4411f2aefd43881450da34db81e826110ac86c3a6cef9fd6a3e9e341508d1f09": {
"query": "\n SELECT id FROM versions\n WHERE mod_id = $1\n ",
"describe": {
@@ -1498,6 +1478,26 @@
]
}
},
"d88b160963bffbf3297de4418a38f4c914819fff94b912fab451b892c7494370": {
"query": "\n SELECT id\n FROM release_channels\n WHERE channel = $1\n ",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "id",
"type_info": "Int4"
}
],
"parameters": {
"Left": [
"Text"
]
},
"nullable": [
false
]
}
},
"d8b4e7e382c77a05395124d5a6a27cccb687d0e2c31b76d49b03aa364d099d42": {
"query": "\n DELETE FROM files\n WHERE files.version_id = $1\n ",
"describe": {
+70 -50
View File
@@ -181,7 +181,7 @@ async fn mod_create_inner(
) -> Result<HttpResponse, CreateError> {
let cdn_url = dotenv::var("CDN_URL")?;
let mod_id = models::generate_mod_id(transaction).await?.into();
let mod_id: ModId = models::generate_mod_id(transaction).await?.into();
let user = get_user_from_headers(req.headers(), &mut *transaction).await?;
let mut created_versions: Vec<models::version_item::VersionBuilder> = vec![];
@@ -208,52 +208,12 @@ async fn mod_create_inner(
check_length("mod_name", 3, 255, &*create_data.mod_name)?;
check_length("mod_description", 3, 2048, &*create_data.mod_description)?;
mod_create_data = Some(create_data);
continue;
for version_data in &create_data.initial_versions {
if version_data.mod_id.is_some() {
return Err(CreateError::InvalidInput(String::from(
"Found mod id in initial version for new mod",
)));
}
let create_data = mod_create_data.as_ref().ok_or_else(|| {
CreateError::InvalidInput(String::from("`data` field must come before file fields"))
})?;
let (file_name, file_extension) =
super::version_creation::get_name_ext(&content_disposition)?;
if name == "icon" {
icon_url = process_icon_upload(
uploaded_files,
mod_id,
file_name,
file_extension,
file_host,
field,
&cdn_url,
)
.await?;
continue;
}
let version_data = create_data
.initial_versions
.iter()
.find(|x| x.file_parts.iter().any(|n| n == name))
.ok_or_else(|| {
CreateError::InvalidInput(format!(
"File `{}` (field {}) isn't specified in the versions data",
file_name, name
))
})?;
// If a version has already been created for this version, add the
// file to it instead of creating a new version.
// Versions must have at least one jar file to be uploaded
let created_version = if let Some(created_version) = created_versions
.iter_mut()
.find(|x| x.version_number == version_data.version_number)
{
created_version
} else {
let version_id: VersionId = models::generate_version_id(transaction).await?.into();
let body_url = format!("data/{}/changelogs/{}/body.md", mod_id, version_id);
@@ -320,7 +280,54 @@ async fn mod_create_inner(
};
created_versions.push(version);
created_versions.last_mut().unwrap()
}
mod_create_data = Some(create_data);
continue;
}
let create_data = mod_create_data.as_ref().ok_or_else(|| {
CreateError::InvalidInput(String::from("`data` field must come before file fields"))
})?;
let (file_name, file_extension) =
super::version_creation::get_name_ext(&content_disposition)?;
if name == "icon" {
icon_url = process_icon_upload(
uploaded_files,
mod_id,
file_name,
file_extension,
file_host,
field,
&cdn_url,
)
.await?;
continue;
}
let (version_index, version_data) = create_data
.initial_versions
.iter()
.enumerate()
.find(|(_, x)| x.file_parts.iter().any(|n| n == name))
.ok_or_else(|| {
CreateError::InvalidInput(format!(
"File `{}` (field {}) isn't specified in the versions data",
file_name, name
))
})?;
let created_version = if let Some(created_version) = created_versions.get_mut(version_index)
{
created_version
} else {
// This shouldn't be reachable, but better safe than sorry
return Err(CreateError::InvalidInput(format!(
"File `{}` (field {}) isn't specified in the versions data",
file_name, name
)));
};
// Upload the new jar file
@@ -342,11 +349,23 @@ async fn mod_create_inner(
let create_data = if let Some(create_data) = mod_create_data {
create_data
} else {
return Err(CreateError::InvalidInput(String::from(
return Err(CreateError::MissingValueError(String::from(
"Multipart upload missing `data` field",
)));
};
for (version_data, builder) in create_data
.initial_versions
.iter()
.zip(created_versions.iter())
{
if version_data.file_parts.len() != builder.files.len() {
return Err(CreateError::InvalidInput(String::from(
"Some files were specified in initial_versions but not uploaded",
)));
}
}
let ids: Vec<UserId> = (&create_data.team_members)
.iter()
.map(|m| m.user_id)
@@ -561,10 +580,11 @@ fn check_length(
max_length: usize,
string: &str,
) -> Result<(), CreateError> {
if string.len() > max_length || string.len() < min_length {
let length = string.len();
if length > max_length || length < min_length {
Err(CreateError::InvalidInput(format!(
"The {} must be between {} and {} characters; got {}.",
var_name, string, min_length, max_length
var_name, min_length, max_length, length
)))
} else {
Ok(())
+9 -4
View File
@@ -15,7 +15,7 @@ use sqlx::postgres::PgPool;
#[derive(Serialize, Deserialize, Clone)]
pub struct InitialVersionData {
pub mod_id: ModId,
pub mod_id: Option<ModId>,
pub file_parts: Vec<String>,
pub version_number: String,
pub version_title: String,
@@ -101,7 +101,11 @@ async fn version_create_inner(
let version_create_data: InitialVersionData = serde_json::from_slice(&data)?;
initial_version_data = Some(version_create_data);
let version_create_data = initial_version_data.as_ref().unwrap();
let mod_id: models::ModId = version_create_data.mod_id.into();
if version_create_data.mod_id.is_none() {
return Err(CreateError::MissingValueError("Missing mod id".to_string()));
}
let mod_id: models::ModId = version_create_data.mod_id.unwrap().into();
let results = sqlx::query!(
"SELECT EXISTS(SELECT 1 FROM mods WHERE id=$1)",
@@ -152,7 +156,8 @@ async fn version_create_inner(
let version_id: VersionId = models::generate_version_id(transaction).await?.into();
let body_url = format!(
"data/{}/changelogs/{}/body.md",
version_create_data.mod_id, version_id
version_create_data.mod_id.unwrap(),
version_id
);
let uploaded_text = file_host
@@ -200,7 +205,7 @@ async fn version_create_inner(
version_builder = Some(VersionBuilder {
version_id: version_id.into(),
mod_id: version_create_data.mod_id.into(),
mod_id: version_create_data.mod_id.unwrap().into(),
author_id: user.id.into(),
name: version_create_data.version_title.clone(),
version_number: version_create_data.version_number.clone(),