Add dependencies to search (#578)

* Add dependencies to search

* add attrs for faceting

* run prepare

* Add user data route from token

* update to 24hrs

* Fix report bugs
This commit is contained in:
Geometrically
2023-04-20 16:38:30 -07:00
committed by GitHub
parent 5c559af936
commit 59f24df294
65 changed files with 1518 additions and 2218 deletions

View File

@@ -4,8 +4,8 @@ use crate::database::models::thread_item::ThreadBuilder;
use crate::file_hosting::{FileHost, FileHostingError};
use crate::models::error::ApiError;
use crate::models::projects::{
DonationLink, License, MonetizationStatus, ProjectId, ProjectStatus,
SideType, VersionId, VersionStatus,
DonationLink, License, MonetizationStatus, ProjectId, ProjectStatus, SideType, VersionId,
VersionStatus,
};
use crate::models::threads::ThreadType;
use crate::models::users::UserId;
@@ -79,14 +79,10 @@ impl actix_web::ResponseError for CreateError {
fn status_code(&self) -> StatusCode {
match self {
CreateError::EnvError(..) => StatusCode::INTERNAL_SERVER_ERROR,
CreateError::SqlxDatabaseError(..) => {
StatusCode::INTERNAL_SERVER_ERROR
}
CreateError::SqlxDatabaseError(..) => StatusCode::INTERNAL_SERVER_ERROR,
CreateError::DatabaseError(..) => StatusCode::INTERNAL_SERVER_ERROR,
CreateError::IndexingError(..) => StatusCode::INTERNAL_SERVER_ERROR,
CreateError::FileHostingError(..) => {
StatusCode::INTERNAL_SERVER_ERROR
}
CreateError::FileHostingError(..) => StatusCode::INTERNAL_SERVER_ERROR,
CreateError::SerDeError(..) => StatusCode::BAD_REQUEST,
CreateError::MultipartError(..) => StatusCode::BAD_REQUEST,
CreateError::MissingValueError(..) => StatusCode::BAD_REQUEST,
@@ -97,9 +93,7 @@ impl actix_web::ResponseError for CreateError {
CreateError::InvalidCategory(..) => StatusCode::BAD_REQUEST,
CreateError::InvalidFileType(..) => StatusCode::BAD_REQUEST,
CreateError::Unauthorized(..) => StatusCode::UNAUTHORIZED,
CreateError::CustomAuthenticationError(..) => {
StatusCode::UNAUTHORIZED
}
CreateError::CustomAuthenticationError(..) => StatusCode::UNAUTHORIZED,
CreateError::SlugCollision => StatusCode::BAD_REQUEST,
CreateError::ValidationError(..) => StatusCode::BAD_REQUEST,
CreateError::FileValidationError(..) => StatusCode::BAD_REQUEST,
@@ -347,21 +341,17 @@ async fn project_create_inner(
let cdn_url = dotenvy::var("CDN_URL")?;
// The currently logged in user
let current_user =
get_user_from_headers(req.headers(), &mut *transaction).await?;
let current_user = get_user_from_headers(req.headers(), &mut *transaction).await?;
let project_id: ProjectId =
models::generate_project_id(transaction).await?.into();
let project_id: ProjectId = models::generate_project_id(transaction).await?.into();
let project_create_data;
let mut versions;
let mut versions_map = std::collections::HashMap::new();
let mut gallery_urls = Vec::new();
let all_game_versions =
models::categories::GameVersion::list(&mut *transaction).await?;
let all_loaders =
models::categories::Loader::list(&mut *transaction).await?;
let all_game_versions = models::categories::GameVersion::list(&mut *transaction).await?;
let all_loaders = models::categories::Loader::list(&mut *transaction).await?;
{
// The first multipart field must be named "data" and contain a
@@ -378,9 +368,9 @@ async fn project_create_inner(
})?;
let content_disposition = field.content_disposition();
let name = content_disposition.get_name().ok_or_else(|| {
CreateError::MissingValueError(String::from("Missing content name"))
})?;
let name = content_disposition
.get_name()
.ok_or_else(|| CreateError::MissingValueError(String::from("Missing content name")))?;
if name != "data" {
return Err(CreateError::InvalidInput(String::from(
@@ -390,22 +380,19 @@ async fn project_create_inner(
let mut data = Vec::new();
while let Some(chunk) = field.next().await {
data.extend_from_slice(
&chunk.map_err(CreateError::MultipartError)?,
);
data.extend_from_slice(&chunk.map_err(CreateError::MultipartError)?);
}
let create_data: ProjectCreateData = serde_json::from_slice(&data)?;
create_data.validate().map_err(|err| {
CreateError::InvalidInput(validation_errors_to_string(err, None))
})?;
create_data
.validate()
.map_err(|err| CreateError::InvalidInput(validation_errors_to_string(err, None)))?;
let slug_project_id_option: Option<ProjectId> =
serde_json::from_str(&format!("\"{}\"", create_data.slug)).ok();
if let Some(slug_project_id) = slug_project_id_option {
let slug_project_id: models::ids::ProjectId =
slug_project_id.into();
let slug_project_id: models::ids::ProjectId = slug_project_id.into();
let results = sqlx::query!(
"
SELECT EXISTS(SELECT 1 FROM mods WHERE id=$1)
@@ -492,9 +479,7 @@ async fn project_create_inner(
let content_disposition = field.content_disposition().clone();
let name = content_disposition.get_name().ok_or_else(|| {
CreateError::MissingValueError(
"Missing content name".to_string(),
)
CreateError::MissingValueError("Missing content name".to_string())
})?;
let (file_name, file_extension) =
@@ -528,9 +513,7 @@ async fn project_create_inner(
)));
}
if let Some(item) =
gallery_items.iter().find(|x| x.item == name)
{
if let Some(item) = gallery_items.iter().find(|x| x.item == name) {
let data = read_from_field(
&mut field,
5 * (1 << 20),
@@ -540,22 +523,13 @@ async fn project_create_inner(
let hash = sha1::Sha1::from(&data).hexdigest();
let (_, file_extension) =
super::version_creation::get_name_ext(
&content_disposition,
)?;
let content_type =
crate::util::ext::get_image_content_type(
file_extension,
)
super::version_creation::get_name_ext(&content_disposition)?;
let content_type = crate::util::ext::get_image_content_type(file_extension)
.ok_or_else(|| {
CreateError::InvalidIconFormat(
file_extension.to_string(),
)
CreateError::InvalidIconFormat(file_extension.to_string())
})?;
let url = format!(
"data/{project_id}/images/{hash}.{file_extension}"
);
let url = format!("data/{project_id}/images/{hash}.{file_extension}");
let upload_data = file_host
.upload_file(content_type, &url, data.freeze())
.await?;
@@ -588,8 +562,7 @@ async fn project_create_inner(
// `index` is always valid for these lists
let created_version = versions.get_mut(index).unwrap();
let version_data =
project_create_data.initial_versions.get(index).unwrap();
let version_data = project_create_data.initial_versions.get(index).unwrap();
// Upload the new jar file
super::version_creation::upload_file(
@@ -642,8 +615,7 @@ async fn project_create_inner(
}
// Convert the list of category names to actual categories
let mut categories =
Vec::with_capacity(project_create_data.categories.len());
let mut categories = Vec::with_capacity(project_create_data.categories.len());
for category in &project_create_data.categories {
let id = models::categories::Category::get_id_project(
category,
@@ -706,9 +678,7 @@ async fn project_create_inner(
)
.await?
.ok_or_else(|| {
CreateError::InvalidInput(
"Client side type specified does not exist.".to_string(),
)
CreateError::InvalidInput("Client side type specified does not exist.".to_string())
})?;
let server_side_id = models::categories::SideType::get_id(
@@ -717,35 +687,27 @@ async fn project_create_inner(
)
.await?
.ok_or_else(|| {
CreateError::InvalidInput(
"Server side type specified does not exist.".to_string(),
)
CreateError::InvalidInput("Server side type specified does not exist.".to_string())
})?;
let license_id = spdx::Expression::parse(
&project_create_data.license_id,
)
.map_err(|err| {
CreateError::InvalidInput(format!(
"Invalid SPDX license identifier: {err}"
))
})?;
let license_id =
spdx::Expression::parse(&project_create_data.license_id).map_err(|err| {
CreateError::InvalidInput(format!("Invalid SPDX license identifier: {err}"))
})?;
let mut donation_urls = vec![];
if let Some(urls) = &project_create_data.donation_urls {
for url in urls {
let platform_id = models::categories::DonationPlatform::get_id(
&url.id,
&mut *transaction,
)
.await?
.ok_or_else(|| {
CreateError::InvalidInput(format!(
"Donation platform {} does not exist.",
url.id.clone()
))
})?;
let platform_id =
models::categories::DonationPlatform::get_id(&url.id, &mut *transaction)
.await?
.ok_or_else(|| {
CreateError::InvalidInput(format!(
"Donation platform {} does not exist.",
url.id.clone()
))
})?;
donation_urls.push(models::project_item::DonationUrl {
platform_id,
@@ -856,16 +818,10 @@ async fn project_create_inner(
let _project_id = project_builder.insert(&mut *transaction).await?;
if status == ProjectStatus::Processing {
if let Ok(webhook_url) = dotenvy::var("MODERATION_DISCORD_WEBHOOK")
{
crate::util::webhook::send_discord_webhook(
response.id,
pool,
webhook_url,
None,
)
.await
.ok();
if let Ok(webhook_url) = dotenvy::var("MODERATION_DISCORD_WEBHOOK") {
crate::util::webhook::send_discord_webhook(response.id, pool, webhook_url, None)
.await
.ok();
}
}
@@ -888,13 +844,12 @@ async fn create_initial_version(
)));
}
version_data.validate().map_err(|err| {
CreateError::ValidationError(validation_errors_to_string(err, None))
})?;
version_data
.validate()
.map_err(|err| CreateError::ValidationError(validation_errors_to_string(err, None)))?;
// Randomly generate a new id to be used for the version
let version_id: VersionId =
models::generate_version_id(transaction).await?.into();
let version_id: VersionId = models::generate_version_id(transaction).await?.into();
let game_versions = version_data
.game_versions
@@ -963,15 +918,8 @@ async fn process_icon_upload(
mut field: Field,
cdn_url: &str,
) -> Result<(String, Option<u32>), CreateError> {
if let Some(content_type) =
crate::util::ext::get_image_content_type(file_extension)
{
let data = read_from_field(
&mut field,
262144,
"Icons must be smaller than 256KiB",
)
.await?;
if let Some(content_type) = crate::util::ext::get_image_content_type(file_extension) {
let data = read_from_field(&mut field, 262144, "Icons must be smaller than 256KiB").await?;
let color = crate::util::img::get_color_from_img(&data)?;