More project type validators (#383)

This commit is contained in:
Geometrically
2022-06-26 10:39:38 -07:00
committed by GitHub
parent 134c43ad9e
commit 4e97a3b3d5
9 changed files with 111 additions and 33 deletions

13
Cargo.lock generated
View File

@@ -46,7 +46,8 @@ dependencies = [
[[package]] [[package]]
name = "actix-cors" name = "actix-cors"
version = "0.6.1" version = "0.6.1"
source = "git+https://github.com/modrinth/actix-extras.git?rev=34d301f#34d301f173c1e7dd5d835ffe29ea46b3e0e4bb8c" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "414360eed71ba2d5435b185ba43ecbe281dfab5df3898286d6b7be8074372c92"
dependencies = [ dependencies = [
"actix-utils", "actix-utils",
"actix-web", "actix-web",
@@ -107,7 +108,8 @@ dependencies = [
[[package]] [[package]]
name = "actix-multipart" name = "actix-multipart"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/modrinth/actix-web?rev=88c7c18#88c7c184abeed2b3d8765af2d7d1a9345010b9eb" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c9edfb0e7663d7fe18c8d5b668c9c1bcf79176b1dcc9d4da9592503209a6bfb0"
dependencies = [ dependencies = [
"actix-utils", "actix-utils",
"actix-web", "actix-web",
@@ -187,8 +189,9 @@ dependencies = [
[[package]] [[package]]
name = "actix-web" name = "actix-web"
version = "4.0.1" version = "4.1.0"
source = "git+https://github.com/modrinth/actix-web?rev=88c7c18#88c7c184abeed2b3d8765af2d7d1a9345010b9eb" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a27e8fe9ba4ae613c21f677c2cfaf0696c3744030c6f485b34634e502d6bb379"
dependencies = [ dependencies = [
"actix-codec", "actix-codec",
"actix-http", "actix-http",
@@ -1441,7 +1444,7 @@ dependencies = [
[[package]] [[package]]
name = "labrinth" name = "labrinth"
version = "2.4.3" version = "2.4.4"
dependencies = [ dependencies = [
"actix", "actix",
"actix-cors", "actix-cors",

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "labrinth" name = "labrinth"
version = "2.4.3" version = "2.4.4"
#Team members, please add your emails and usernames #Team members, please add your emails and usernames
authors = ["geometrically <jai.a@tuta.io>", "Redblueflame <contact@redblueflame.com>", "Aeledfyr <aeledfyr@gmail.com>", "Charalampos Fanoulis <yo@fanoulis.dev>", "AppleTheGolden <scotsbox@protonmail.com>"] authors = ["geometrically <jai.a@tuta.io>", "Redblueflame <contact@redblueflame.com>", "Aeledfyr <aeledfyr@gmail.com>", "Charalampos Fanoulis <yo@fanoulis.dev>", "AppleTheGolden <scotsbox@protonmail.com>"]
edition = "2018" edition = "2018"
@@ -14,12 +14,12 @@ path = "src/main.rs"
[dependencies] [dependencies]
actix = "0.13.0" actix = "0.13.0"
actix-web = { git = "https://github.com/modrinth/actix-web", rev = "88c7c18" } actix-web = "4.1.0"
actix-rt = "2.7.0" actix-rt = "2.7.0"
tokio = { version = "1.19.0", features = ["sync"] } tokio = { version = "1.19.0", features = ["sync"] }
tokio-stream = "0.1.8" tokio-stream = "0.1.8"
actix-multipart = { git = "https://github.com/modrinth/actix-web", rev = "88c7c18" } actix-multipart = "0.4.0"
actix-cors = { git = "https://github.com/modrinth/actix-extras.git", rev = "34d301f" } actix-cors = "0.6.1"
meilisearch-sdk = "0.15.0" meilisearch-sdk = "0.15.0"
reqwest = { version = "0.11.10", features = ["json"] } reqwest = { version = "0.11.10", features = ["json"] }

View File

@@ -679,7 +679,7 @@ impl Project {
.donations .donations
.unwrap_or_default() .unwrap_or_default()
.split(" ~~~~ ") .split(" ~~~~ ")
.map(|d| { .flat_map(|d| {
let strings: Vec<&str> = d.split(" |||| ").collect(); let strings: Vec<&str> = d.split(" |||| ").collect();
if strings.len() >= 3 { if strings.len() >= 3 {
@@ -696,13 +696,12 @@ impl Project {
None None
} }
}) })
.flatten()
.collect(), .collect(),
gallery_items: m gallery_items: m
.gallery .gallery
.unwrap_or_default() .unwrap_or_default()
.split(" ~~~~ ") .split(" ~~~~ ")
.map(|d| { .flat_map(|d| {
let strings: Vec<&str> = d.split(" |||| ").collect(); let strings: Vec<&str> = d.split(" |||| ").collect();
if strings.len() >= 5 { if strings.len() >= 5 {
@@ -726,7 +725,6 @@ impl Project {
None None
} }
}) })
.flatten()
.collect(), .collect(),
status: crate::models::projects::ProjectStatus::from_str( status: crate::models::projects::ProjectStatus::from_str(
&m.status_name, &m.status_name,
@@ -822,7 +820,7 @@ impl Project {
.gallery .gallery
.unwrap_or_default() .unwrap_or_default()
.split(" ~~~~ ") .split(" ~~~~ ")
.map(|d| { .flat_map(|d| {
let strings: Vec<&str> = d.split(" |||| ").collect(); let strings: Vec<&str> = d.split(" |||| ").collect();
if strings.len() >= 5 { if strings.len() >= 5 {
@@ -838,13 +836,12 @@ impl Project {
None None
} }
}) })
.flatten()
.collect(), .collect(),
donation_urls: m donation_urls: m
.donations .donations
.unwrap_or_default() .unwrap_or_default()
.split(" ~~~~ ") .split(" ~~~~ ")
.map(|d| { .flat_map(|d| {
let strings: Vec<&str> = d.split(" |||| ").collect(); let strings: Vec<&str> = d.split(" |||| ").collect();
if strings.len() >= 3 { if strings.len() >= 3 {
@@ -859,7 +856,6 @@ impl Project {
None None
} }
}) })
.flatten()
.collect(), .collect(),
status: crate::models::projects::ProjectStatus::from_str(&m.status_name), status: crate::models::projects::ProjectStatus::from_str(&m.status_name),
license_id: m.short, license_id: m.short,

View File

@@ -650,7 +650,7 @@ impl Version {
.hashes .hashes
.unwrap_or_default() .unwrap_or_default()
.split(" ~~~~ ") .split(" ~~~~ ")
.map(|f| { .flat_map(|f| {
let hash: Vec<&str> = f.split(" |||| ").collect(); let hash: Vec<&str> = f.split(" |||| ").collect();
if hash.len() >= 3 { if hash.len() >= 3 {
@@ -663,13 +663,12 @@ impl Version {
None None
} }
}) })
.flatten()
.collect(); .collect();
v.files v.files
.unwrap_or_default() .unwrap_or_default()
.split(" ~~~~ ") .split(" ~~~~ ")
.map(|f| { .flat_map(|f| {
let file: Vec<&str> = f.split(" |||| ").collect(); let file: Vec<&str> = f.split(" |||| ").collect();
if file.len() >= 5 { if file.len() >= 5 {
@@ -698,7 +697,6 @@ impl Version {
None None
} }
}) })
.flatten()
.collect() .collect()
}, },
game_versions: { game_versions: {
@@ -737,7 +735,7 @@ impl Version {
.dependencies .dependencies
.unwrap_or_default() .unwrap_or_default()
.split(" ~~~~ ") .split(" ~~~~ ")
.map(|f| { .flat_map(|f| {
let dependency: Vec<&str> = f.split(" |||| ").collect(); let dependency: Vec<&str> = f.split(" |||| ").collect();
if dependency.len() >= 4 { if dependency.len() >= 4 {
@@ -767,7 +765,6 @@ impl Version {
None None
} }
}) })
.flatten()
.collect(), .collect(),
version_type: v.version_type, version_type: v.version_type,
})) }))
@@ -824,7 +821,7 @@ impl Version {
date_published: v.date_published, date_published: v.date_published,
downloads: v.downloads, downloads: v.downloads,
files: { files: {
let hashes: Vec<(FileId, String, Vec<u8>)> = v.hashes.unwrap_or_default().split(" ~~~~ ").map(|f| { let hashes: Vec<(FileId, String, Vec<u8>)> = v.hashes.unwrap_or_default().split(" ~~~~ ").flat_map(|f| {
let hash: Vec<&str> = f.split(" |||| ").collect(); let hash: Vec<&str> = f.split(" |||| ").collect();
if hash.len() >= 3 { if hash.len() >= 3 {
@@ -836,9 +833,9 @@ impl Version {
} else { } else {
None None
} }
}).flatten().collect(); }).collect();
v.files.unwrap_or_default().split(" ~~~~ ").map(|f| { v.files.unwrap_or_default().split(" ~~~~ ").flat_map(|f| {
let file: Vec<&str> = f.split(" |||| ").collect(); let file: Vec<&str> = f.split(" |||| ").collect();
if file.len() >= 5 { if file.len() >= 5 {
@@ -862,7 +859,7 @@ impl Version {
} else { } else {
None None
} }
}).flatten().collect() }).collect()
}, },
game_versions: { game_versions: {
let game_versions = v let game_versions = v
@@ -893,7 +890,7 @@ impl Version {
dependencies: v.dependencies dependencies: v.dependencies
.unwrap_or_default() .unwrap_or_default()
.split(" ~~~~ ") .split(" ~~~~ ")
.map(|f| { .flat_map(|f| {
let dependency: Vec<&str> = f.split(" |||| ").collect(); let dependency: Vec<&str> = f.split(" |||| ").collect();
if dependency.len() >= 4 { if dependency.len() >= 4 {
@@ -922,7 +919,7 @@ impl Version {
} else { } else {
None None
} }
}).flatten().collect(), }).collect(),
version_type: v.version_type version_type: v.version_type
} }
)) ))

View File

@@ -27,7 +27,7 @@ impl DownloadQueue {
pub async fn index(&self, pool: &PgPool) -> Result<(), DatabaseError> { pub async fn index(&self, pool: &PgPool) -> Result<(), DatabaseError> {
let queue = self.take().await; let queue = self.take().await;
if queue.len() > 0 { if !queue.is_empty() {
let mut transaction = pool.begin().await?; let mut transaction = pool.begin().await?;
for (project_id, version_id) in queue { for (project_id, version_id) in queue {

View File

@@ -89,7 +89,7 @@ where
.to_str() .to_str()
.map_err(|_| AuthenticationError::InvalidCredentials)?; .map_err(|_| AuthenticationError::InvalidCredentials)?;
Ok(get_user_from_token(token, executor).await?) get_user_from_token(token, executor).await
} }
pub async fn check_is_moderator_from_headers<'a, 'b, E>( pub async fn check_is_moderator_from_headers<'a, 'b, E>(

View File

@@ -4,7 +4,9 @@ use crate::validate::fabric::FabricValidator;
use crate::validate::forge::{ForgeValidator, LegacyForgeValidator}; use crate::validate::forge::{ForgeValidator, LegacyForgeValidator};
use crate::validate::liteloader::LiteLoaderValidator; use crate::validate::liteloader::LiteLoaderValidator;
use crate::validate::pack::PackValidator; use crate::validate::pack::PackValidator;
use crate::validate::plugin::PluginValidator;
use crate::validate::quilt::QuiltValidator; use crate::validate::quilt::QuiltValidator;
use crate::validate::resourcepack::ResourcePackValidator;
use std::io::Cursor; use std::io::Cursor;
use thiserror::Error; use thiserror::Error;
use time::OffsetDateTime; use time::OffsetDateTime;
@@ -14,7 +16,9 @@ mod fabric;
mod forge; mod forge;
mod liteloader; mod liteloader;
mod pack; mod pack;
mod plugin;
mod quilt; mod quilt;
mod resourcepack;
#[derive(Error, Debug)] #[derive(Error, Debug)]
pub enum ValidationError { pub enum ValidationError {
@@ -22,7 +26,7 @@ pub enum ValidationError {
Zip(#[from] zip::result::ZipError), Zip(#[from] zip::result::ZipError),
#[error("IO Error: {0}")] #[error("IO Error: {0}")]
Io(#[from] std::io::Error), Io(#[from] std::io::Error),
#[error("Error while validating JSON: {0}")] #[error("Error while validating JSON for uploaded file: {0}")]
SerDe(#[from] serde_json::Error), SerDe(#[from] serde_json::Error),
#[error("Invalid Input: {0}")] #[error("Invalid Input: {0}")]
InvalidInput(std::borrow::Cow<'static, str>), InvalidInput(std::borrow::Cow<'static, str>),
@@ -72,13 +76,15 @@ pub trait Validator: Sync {
) -> Result<ValidationResult, ValidationError>; ) -> Result<ValidationResult, ValidationError>;
} }
static VALIDATORS: [&dyn Validator; 6] = [ static VALIDATORS: [&dyn Validator; 8] = [
&PackValidator, &PackValidator,
&FabricValidator, &FabricValidator,
&ForgeValidator, &ForgeValidator,
&LegacyForgeValidator, &LegacyForgeValidator,
&QuiltValidator, &QuiltValidator,
&LiteLoaderValidator, &LiteLoaderValidator,
&ResourcePackValidator,
&PluginValidator,
]; ];
/// The return value is whether this file should be marked as primary or not, based on the analysis of the file /// The return value is whether this file should be marked as primary or not, based on the analysis of the file

38
src/validate/plugin.rs Normal file
View File

@@ -0,0 +1,38 @@
use crate::validate::{
SupportedGameVersions, ValidationError, ValidationResult,
};
use std::io::Cursor;
use zip::ZipArchive;
pub struct PluginValidator;
impl super::Validator for PluginValidator {
fn get_file_extensions(&self) -> &[&str] {
&["zip", "jar"]
}
fn get_project_types(&self) -> &[&str] {
&["mod"]
}
fn get_supported_loaders(&self) -> &[&str] {
&["bukkit", "spigot", "paper", "purpur"]
}
fn get_supported_game_versions(&self) -> SupportedGameVersions {
SupportedGameVersions::All
}
fn validate(
&self,
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
) -> Result<ValidationResult, ValidationError> {
archive.by_name("plugin.yml").map_err(|_| {
ValidationError::InvalidInput(
"No plugin.yml present for plugin file.".into(),
)
})?;
Ok(ValidationResult::Pass)
}
}

View File

@@ -0,0 +1,38 @@
use crate::validate::{
SupportedGameVersions, ValidationError, ValidationResult,
};
use std::io::Cursor;
use zip::ZipArchive;
pub struct ResourcePackValidator;
impl super::Validator for ResourcePackValidator {
fn get_file_extensions(&self) -> &[&str] {
&["zip"]
}
fn get_project_types(&self) -> &[&str] {
&["resourcepack"]
}
fn get_supported_loaders(&self) -> &[&str] {
&["minecraft"]
}
fn get_supported_game_versions(&self) -> SupportedGameVersions {
SupportedGameVersions::All
}
fn validate(
&self,
archive: &mut ZipArchive<Cursor<bytes::Bytes>>,
) -> Result<ValidationResult, ValidationError> {
archive.by_name("pack.mcmeta").map_err(|_| {
ValidationError::InvalidInput(
"No pack.mcmeta present for resourcepack file.".into(),
)
})?;
Ok(ValidationResult::Pass)
}
}