1
0
Files
AstralRinth/src/models/v3/pack.rs
Wyatt Verchere ae1c5342f2 Search test + v3 (#731)
* search patch for accurate loader/gv filtering

* backup

* basic search test

* finished test

* incomplete commit; backing up

* Working multipat reroute backup

* working rough draft v3

* most tests passing

* works

* search v2 conversion

* added some tags.rs v2 conversions

* Worked through warnings, unwraps, prints

* refactors

* new search test

* version files changes fixes

* redesign to revs

* removed old caches

* removed games

* fmt clippy

* merge conflicts

* fmt, prepare

* moved v2 routes over to v3

* fixes; tests passing

* project type changes

* moved files over

* fmt, clippy, prepare, etc

* loaders to loader_fields, added tests

* fmt, clippy, prepare

* fixed sorting bug

* reversed back- wrong order for consistency

* fmt; clippy; prepare

---------

Co-authored-by: Jai A <jaiagr+gpg@pm.me>
2023-11-11 16:40:10 -08:00

110 lines
3.2 KiB
Rust

use crate::{models::projects::SideType, util::env::parse_strings_from_var};
use serde::{Deserialize, Serialize};
use validator::Validate;
#[derive(Serialize, Deserialize, Validate, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct PackFormat {
pub game: String,
pub format_version: i32,
#[validate(length(min = 1, max = 512))]
pub version_id: String,
#[validate(length(min = 1, max = 512))]
pub name: String,
#[validate(length(max = 2048))]
pub summary: Option<String>,
#[validate]
pub files: Vec<PackFile>,
pub dependencies: std::collections::HashMap<PackDependency, String>,
}
#[derive(Serialize, Deserialize, Validate, Eq, PartialEq)]
#[serde(rename_all = "camelCase")]
pub struct PackFile {
pub path: String,
pub hashes: std::collections::HashMap<PackFileHash, String>,
pub env: Option<std::collections::HashMap<EnvType, SideType>>,
#[validate(custom(function = "validate_download_url"))]
pub downloads: Vec<String>,
pub file_size: u32,
}
fn validate_download_url(values: &[String]) -> Result<(), validator::ValidationError> {
for value in values {
let url = url::Url::parse(value)
.ok()
.ok_or_else(|| validator::ValidationError::new("invalid URL"))?;
if url.as_str() != value {
return Err(validator::ValidationError::new("invalid URL"));
}
let domains = parse_strings_from_var("WHITELISTED_MODPACK_DOMAINS").unwrap_or_default();
if !domains.contains(
&url.domain()
.ok_or_else(|| validator::ValidationError::new("invalid URL"))?
.to_string(),
) {
return Err(validator::ValidationError::new(
"File download source is not from allowed sources",
));
}
}
Ok(())
}
#[derive(Serialize, Deserialize, Eq, PartialEq, Hash)]
#[serde(rename_all = "camelCase", from = "String")]
pub enum PackFileHash {
Sha1,
Sha512,
Unknown(String),
}
impl From<String> for PackFileHash {
fn from(s: String) -> Self {
return match s.as_str() {
"sha1" => PackFileHash::Sha1,
"sha512" => PackFileHash::Sha512,
_ => PackFileHash::Unknown(s),
};
}
}
#[derive(Serialize, Deserialize, Eq, PartialEq, Hash)]
#[serde(rename_all = "camelCase")]
pub enum EnvType {
Client,
Server,
}
#[derive(Serialize, Deserialize, Clone, Hash, PartialEq, Eq)]
#[serde(rename_all = "kebab-case")]
pub enum PackDependency {
Forge,
Neoforge,
FabricLoader,
QuiltLoader,
Minecraft,
}
impl std::fmt::Display for PackDependency {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.write_str(self.as_str())
}
}
impl PackDependency {
// These are constant, so this can remove unnecessary allocations (`to_string`)
pub fn as_str(&self) -> &'static str {
match self {
PackDependency::Forge => "forge",
PackDependency::Neoforge => "neoforge",
PackDependency::FabricLoader => "fabric-loader",
PackDependency::Minecraft => "minecraft",
PackDependency::QuiltLoader => "quilt-loader",
}
}
}