You've already forked AstralRinth
forked from didirus/AstralRinth
Lots of little fixes (#73)
* Lots of little fixes * Change + Add TODOs back that were incomplete * Fix migrations * Run prepare * Minor fixes * Fix formatting * SQLX Prepare
This commit is contained in:
@@ -6,8 +6,7 @@ pub async fn index_get() -> HttpResponse {
|
||||
let data = json!({
|
||||
"name": "modrinth-labrinth",
|
||||
"version": env!("CARGO_PKG_VERSION"),
|
||||
//TODO: Add the documentation link
|
||||
"documentation": "Nowhere yet",
|
||||
"documentation": "https://modrinth.com/documentation",
|
||||
"about": "Welcome traveler !"
|
||||
});
|
||||
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use crate::auth::{get_user_from_headers, AuthenticationError};
|
||||
use crate::database::models;
|
||||
use crate::database::models::StatusId;
|
||||
use crate::file_hosting::{FileHost, FileHostingError};
|
||||
use crate::models::error::ApiError;
|
||||
use crate::models::mods::{ModId, VersionId, VersionType};
|
||||
use crate::models::mods::{ModId, ModStatus, VersionId};
|
||||
use crate::models::teams::TeamMember;
|
||||
use crate::models::users::UserId;
|
||||
use crate::routes::version_creation::InitialVersionData;
|
||||
@@ -97,8 +98,6 @@ impl actix_web::ResponseError for CreateError {
|
||||
struct ModCreateData {
|
||||
/// The title or name of the mod.
|
||||
pub mod_name: String,
|
||||
/// The namespace of the mod
|
||||
pub mod_namespace: String,
|
||||
/// A short description of the mod.
|
||||
pub mod_description: String,
|
||||
/// A long description of the mod, in markdown.
|
||||
@@ -212,6 +211,9 @@ async fn mod_create_inner(
|
||||
CreateError::InvalidInput(String::from("`data` field must come before file fields"))
|
||||
})?;
|
||||
|
||||
check_length("mod_name", 3, 255, &*create_data.mod_name)?;
|
||||
check_length("mod_description", 3, 2048, &*create_data.mod_description)?;
|
||||
|
||||
let (file_name, file_extension) =
|
||||
super::version_creation::get_name_ext(&content_disposition)?;
|
||||
|
||||
@@ -267,12 +269,19 @@ async fn mod_create_inner(
|
||||
file_name: uploaded_text.file_name.clone(),
|
||||
});
|
||||
|
||||
// TODO: do a real lookup for the channels
|
||||
let release_channel = match version_data.release_channel {
|
||||
VersionType::Release => models::ChannelId(1),
|
||||
VersionType::Beta => models::ChannelId(3),
|
||||
VersionType::Alpha => models::ChannelId(5),
|
||||
};
|
||||
let release_channel = models::ChannelId(
|
||||
sqlx::query!(
|
||||
"
|
||||
SELECT id
|
||||
FROM release_channels
|
||||
WHERE channel = $1
|
||||
",
|
||||
version_data.release_channel.to_string()
|
||||
)
|
||||
.fetch_one(&mut *transaction)
|
||||
.await?
|
||||
.id,
|
||||
);
|
||||
|
||||
let mut game_versions = Vec::with_capacity(version_data.game_versions.len());
|
||||
for v in &version_data.game_versions {
|
||||
@@ -379,7 +388,18 @@ async fn mod_create_inner(
|
||||
|
||||
let team_id = team.insert(&mut *transaction).await?;
|
||||
|
||||
// Insert the new mod into the database
|
||||
let status = ModStatus::Processing;
|
||||
let status_id = sqlx::query!(
|
||||
"
|
||||
SELECT id
|
||||
FROM statuses
|
||||
WHERE status = $1
|
||||
",
|
||||
status.to_string()
|
||||
)
|
||||
.fetch_one(&mut *transaction)
|
||||
.await?
|
||||
.id;
|
||||
|
||||
let mod_builder = models::mod_item::ModBuilder {
|
||||
mod_id: mod_id.into(),
|
||||
@@ -394,6 +414,7 @@ async fn mod_create_inner(
|
||||
|
||||
categories,
|
||||
initial_versions: created_versions,
|
||||
status: StatusId(status_id),
|
||||
};
|
||||
|
||||
let versions_list = mod_builder
|
||||
@@ -410,7 +431,6 @@ async fn mod_create_inner(
|
||||
|
||||
let now = chrono::Utc::now();
|
||||
let timestamp = now.timestamp();
|
||||
let formatted = now.to_string();
|
||||
|
||||
let index_mod = crate::search::UploadSearchMod {
|
||||
mod_id: format!("local-{}", mod_id),
|
||||
@@ -418,17 +438,16 @@ async fn mod_create_inner(
|
||||
description: mod_builder.description.clone(),
|
||||
categories: create_data.categories.clone(),
|
||||
versions: versions_list,
|
||||
page_url: mod_builder.body_url.clone(),
|
||||
page_url: format!("https://modrinth.com/mod/{}", mod_id),
|
||||
icon_url: mod_builder.icon_url.clone().unwrap(),
|
||||
author: user.username,
|
||||
author_url: format!("https://modrinth.com/user/{}", user.id),
|
||||
// TODO: latest version info
|
||||
latest_version: String::new(),
|
||||
downloads: 0,
|
||||
date_created: formatted.clone(),
|
||||
date_created: now,
|
||||
created_timestamp: timestamp,
|
||||
// TODO: store and return modified time
|
||||
date_modified: formatted,
|
||||
date_modified: now,
|
||||
modified_timestamp: timestamp,
|
||||
host: Cow::Borrowed("modrinth"),
|
||||
empty: Cow::Borrowed("{}{}{}"),
|
||||
@@ -443,6 +462,8 @@ async fn mod_create_inner(
|
||||
description: mod_builder.description.clone(),
|
||||
body_url: mod_builder.body_url.clone(),
|
||||
published: now,
|
||||
updated: now,
|
||||
status,
|
||||
downloads: 0,
|
||||
categories: create_data.categories.clone(),
|
||||
versions: mod_builder
|
||||
@@ -514,3 +535,19 @@ fn get_image_content_type(extension: &str) -> Option<&'static str> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn check_length(
|
||||
var_name: &str,
|
||||
min_length: usize,
|
||||
max_length: usize,
|
||||
string: &str,
|
||||
) -> Result<(), CreateError> {
|
||||
if string.len() > max_length || string.len() < min_length {
|
||||
Err(CreateError::InvalidInput(format!(
|
||||
"The {} must be between {} and {} characters; got {}.",
|
||||
var_name, string, min_length, max_length
|
||||
)))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,15 +36,29 @@ pub async fn mods_get(
|
||||
.await
|
||||
.map_err(|e| ApiError::DatabaseError(e.into()))?;
|
||||
|
||||
let mods: Vec<models::mods::Mod> = mods_data
|
||||
.into_iter()
|
||||
.map(|m| models::mods::Mod {
|
||||
let mut mods: Vec<models::mods::Mod> = Vec::new();
|
||||
for m in mods_data {
|
||||
let status = sqlx::query!(
|
||||
"
|
||||
SELECT status FROM statuses
|
||||
WHERE id = $1
|
||||
",
|
||||
m.status.0,
|
||||
)
|
||||
.fetch_one(&**pool)
|
||||
.await
|
||||
.map_err(|e| ApiError::DatabaseError(e.into()))?
|
||||
.status;
|
||||
|
||||
mods.push(models::mods::Mod {
|
||||
id: m.id.into(),
|
||||
team: m.team_id.into(),
|
||||
title: m.title,
|
||||
description: m.description,
|
||||
body_url: m.body_url,
|
||||
published: m.published,
|
||||
updated: m.updated,
|
||||
status: models::mods::ModStatus::from_str(&*status),
|
||||
|
||||
downloads: m.downloads as u32,
|
||||
categories: vec![],
|
||||
@@ -54,7 +68,7 @@ pub async fn mods_get(
|
||||
source_url: m.source_url,
|
||||
wiki_url: m.wiki_url,
|
||||
})
|
||||
.collect();
|
||||
}
|
||||
|
||||
Ok(HttpResponse::Ok().json(mods))
|
||||
}
|
||||
@@ -71,6 +85,19 @@ pub async fn mod_get(
|
||||
|
||||
if let Some(data) = mod_data {
|
||||
let m = data.inner;
|
||||
|
||||
let status = sqlx::query!(
|
||||
"
|
||||
SELECT status FROM statuses
|
||||
WHERE id = $1
|
||||
",
|
||||
m.status.0,
|
||||
)
|
||||
.fetch_one(&**pool)
|
||||
.await
|
||||
.map_err(|e| ApiError::DatabaseError(e.into()))?
|
||||
.status;
|
||||
|
||||
let response = models::mods::Mod {
|
||||
id: m.id.into(),
|
||||
team: m.team_id.into(),
|
||||
@@ -78,6 +105,8 @@ pub async fn mod_get(
|
||||
description: m.description,
|
||||
body_url: m.body_url,
|
||||
published: m.published,
|
||||
updated: m.updated,
|
||||
status: models::mods::ModStatus::from_str(&*status),
|
||||
|
||||
downloads: m.downloads as u32,
|
||||
categories: data.categories,
|
||||
|
||||
@@ -68,6 +68,7 @@ pub async fn version_create(
|
||||
result
|
||||
}
|
||||
|
||||
/// TODO: Update mod timestamp when new version is created
|
||||
async fn version_create_inner(
|
||||
req: HttpRequest,
|
||||
mut payload: Multipart,
|
||||
@@ -167,12 +168,35 @@ async fn version_create_inner(
|
||||
file_name: uploaded_text.file_name.clone(),
|
||||
});
|
||||
|
||||
// TODO: do a real lookup for the channels
|
||||
let release_channel = match version_create_data.release_channel {
|
||||
VersionType::Release => models::ChannelId(1),
|
||||
VersionType::Beta => models::ChannelId(3),
|
||||
VersionType::Alpha => models::ChannelId(5),
|
||||
};
|
||||
let release_channel = models::ChannelId(
|
||||
sqlx::query!(
|
||||
"
|
||||
SELECT id
|
||||
FROM release_channels
|
||||
WHERE channel = $1
|
||||
",
|
||||
version_create_data.release_channel.to_string()
|
||||
)
|
||||
.fetch_one(&mut *transaction)
|
||||
.await?
|
||||
.id,
|
||||
);
|
||||
|
||||
let mut game_versions = Vec::with_capacity(version_create_data.game_versions.len());
|
||||
for v in &version_create_data.game_versions {
|
||||
let id = models::categories::GameVersion::get_id(&v.0, &mut *transaction)
|
||||
.await?
|
||||
.ok_or_else(|| CreateError::InvalidGameVersion(v.0.clone()))?;
|
||||
game_versions.push(id);
|
||||
}
|
||||
|
||||
let mut loaders = Vec::with_capacity(version_create_data.loaders.len());
|
||||
for l in &version_create_data.loaders {
|
||||
let id = models::categories::Loader::get_id(&l.0, &mut *transaction)
|
||||
.await?
|
||||
.ok_or_else(|| CreateError::InvalidLoader(l.0.clone()))?;
|
||||
loaders.push(id);
|
||||
}
|
||||
|
||||
version_builder = Some(VersionBuilder {
|
||||
version_id: version_id.into(),
|
||||
@@ -187,9 +211,8 @@ async fn version_create_inner(
|
||||
.iter()
|
||||
.map(|x| (*x).into())
|
||||
.collect::<Vec<_>>(),
|
||||
// TODO: add game_versions and loaders info
|
||||
game_versions: vec![],
|
||||
loaders: vec![],
|
||||
game_versions,
|
||||
loaders,
|
||||
release_channel,
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user