You've already forked AstralRinth
forked from didirus/AstralRinth
Fix plugin validator, fix version urls, clippy lints, additional categories (#421)
This commit is contained in:
@@ -74,10 +74,9 @@ impl Category {
|
||||
where
|
||||
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
||||
{
|
||||
if !name
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
|
||||
{
|
||||
if !name.chars().all(|c| {
|
||||
c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+'
|
||||
}) {
|
||||
return Err(DatabaseError::InvalidIdentifier(name.to_string()));
|
||||
}
|
||||
|
||||
@@ -102,10 +101,9 @@ impl Category {
|
||||
where
|
||||
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
||||
{
|
||||
if !name
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
|
||||
{
|
||||
if !name.chars().all(|c| {
|
||||
c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+'
|
||||
}) {
|
||||
return Err(DatabaseError::InvalidIdentifier(name.to_string()));
|
||||
}
|
||||
|
||||
@@ -203,10 +201,9 @@ impl<'a> CategoryBuilder<'a> {
|
||||
self,
|
||||
name: &'a str,
|
||||
) -> Result<CategoryBuilder<'a>, DatabaseError> {
|
||||
if name
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
|
||||
{
|
||||
if name.chars().all(|c| {
|
||||
c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+'
|
||||
}) {
|
||||
Ok(Self {
|
||||
name: Some(name),
|
||||
..self
|
||||
@@ -296,10 +293,9 @@ impl Loader {
|
||||
where
|
||||
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
||||
{
|
||||
if !name
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
|
||||
{
|
||||
if !name.chars().all(|c| {
|
||||
c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+'
|
||||
}) {
|
||||
return Err(DatabaseError::InvalidIdentifier(name.to_string()));
|
||||
}
|
||||
|
||||
@@ -403,10 +399,9 @@ impl<'a> LoaderBuilder<'a> {
|
||||
self,
|
||||
name: &'a str,
|
||||
) -> Result<LoaderBuilder<'a>, DatabaseError> {
|
||||
if name
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
|
||||
{
|
||||
if name.chars().all(|c| {
|
||||
c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+'
|
||||
}) {
|
||||
Ok(Self {
|
||||
name: Some(name),
|
||||
..self
|
||||
@@ -501,10 +496,9 @@ impl GameVersion {
|
||||
where
|
||||
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
||||
{
|
||||
if !version
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || "-_.".contains(c))
|
||||
{
|
||||
if !version.chars().all(|c| {
|
||||
c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+'
|
||||
}) {
|
||||
return Err(DatabaseError::InvalidIdentifier(version.to_string()));
|
||||
}
|
||||
|
||||
@@ -676,7 +670,7 @@ impl<'a> GameVersionBuilder<'a> {
|
||||
) -> Result<GameVersionBuilder<'a>, DatabaseError> {
|
||||
if version
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || "-_.".contains(c))
|
||||
.all(|c| c.is_ascii_alphanumeric() || "-_.+".contains(c))
|
||||
{
|
||||
Ok(Self {
|
||||
version: Some(version),
|
||||
@@ -693,7 +687,7 @@ impl<'a> GameVersionBuilder<'a> {
|
||||
) -> Result<GameVersionBuilder<'a>, DatabaseError> {
|
||||
if version_type
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || "-_.".contains(c))
|
||||
.all(|c| c.is_ascii_alphanumeric() || "-_.+".contains(c))
|
||||
{
|
||||
Ok(Self {
|
||||
version_type: Some(version_type),
|
||||
@@ -851,10 +845,9 @@ impl<'a> LicenseBuilder<'a> {
|
||||
self,
|
||||
short: &'a str,
|
||||
) -> Result<LicenseBuilder<'a>, DatabaseError> {
|
||||
if short
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || "-_.".contains(c))
|
||||
{
|
||||
if short.chars().all(|c| {
|
||||
c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+'
|
||||
}) {
|
||||
Ok(Self {
|
||||
short: Some(short),
|
||||
..self
|
||||
@@ -1011,10 +1004,9 @@ impl<'a> DonationPlatformBuilder<'a> {
|
||||
self,
|
||||
short: &'a str,
|
||||
) -> Result<DonationPlatformBuilder<'a>, DatabaseError> {
|
||||
if short
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || "-_.".contains(c))
|
||||
{
|
||||
if short.chars().all(|c| {
|
||||
c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+'
|
||||
}) {
|
||||
Ok(Self {
|
||||
short: Some(short),
|
||||
..self
|
||||
@@ -1075,10 +1067,9 @@ impl ReportType {
|
||||
where
|
||||
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
||||
{
|
||||
if !name
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
|
||||
{
|
||||
if !name.chars().all(|c| {
|
||||
c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+'
|
||||
}) {
|
||||
return Err(DatabaseError::InvalidIdentifier(name.to_string()));
|
||||
}
|
||||
|
||||
@@ -1164,10 +1155,9 @@ impl<'a> ReportTypeBuilder<'a> {
|
||||
self,
|
||||
name: &'a str,
|
||||
) -> Result<ReportTypeBuilder<'a>, DatabaseError> {
|
||||
if name
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
|
||||
{
|
||||
if name.chars().all(|c| {
|
||||
c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+'
|
||||
}) {
|
||||
Ok(Self { name: Some(name) })
|
||||
} else {
|
||||
Err(DatabaseError::InvalidIdentifier(name.to_string()))
|
||||
@@ -1213,10 +1203,9 @@ impl ProjectType {
|
||||
where
|
||||
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
|
||||
{
|
||||
if !name
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
|
||||
{
|
||||
if !name.chars().all(|c| {
|
||||
c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+'
|
||||
}) {
|
||||
return Err(DatabaseError::InvalidIdentifier(name.to_string()));
|
||||
}
|
||||
|
||||
@@ -1330,10 +1319,9 @@ impl<'a> ProjectTypeBuilder<'a> {
|
||||
self,
|
||||
name: &'a str,
|
||||
) -> Result<ProjectTypeBuilder<'a>, DatabaseError> {
|
||||
if name
|
||||
.chars()
|
||||
.all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_')
|
||||
{
|
||||
if name.chars().all(|c| {
|
||||
c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == '+'
|
||||
}) {
|
||||
Ok(Self { name: Some(name) })
|
||||
} else {
|
||||
Err(DatabaseError::InvalidIdentifier(name.to_string()))
|
||||
|
||||
@@ -116,7 +116,7 @@ pub struct TeamId(pub i64);
|
||||
#[sqlx(transparent)]
|
||||
pub struct TeamMemberId(pub i64);
|
||||
|
||||
#[derive(Copy, Clone, Debug, Type, PartialEq)]
|
||||
#[derive(Copy, Clone, Debug, Type, PartialEq, Eq)]
|
||||
#[sqlx(transparent)]
|
||||
pub struct ProjectId(pub i64);
|
||||
#[derive(Copy, Clone, Debug, Type)]
|
||||
|
||||
@@ -30,7 +30,7 @@ pub enum DatabaseError {
|
||||
RandomId,
|
||||
#[error(
|
||||
"Invalid identifier: Category/version names must contain only ASCII \
|
||||
alphanumeric characters or '_-'."
|
||||
alphanumeric characters or '_-+'."
|
||||
)]
|
||||
InvalidIdentifier(String),
|
||||
#[error("Invalid permissions bitflag!")]
|
||||
|
||||
@@ -629,8 +629,7 @@ impl Project {
|
||||
m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,
|
||||
m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,
|
||||
s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name,
|
||||
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null) categories,
|
||||
ARRAY_AGG(DISTINCT ca.category) filter (where ca.category is not null) additional_categories,
|
||||
ARRAY_AGG(DISTINCT c.category || ' |||| ' || mc.is_additional) filter (where c.category is not null) categories,
|
||||
ARRAY_AGG(DISTINCT v.id || ' |||| ' || v.date_published) filter (where v.id is not null) versions,
|
||||
ARRAY_AGG(DISTINCT mg.image_url || ' |||| ' || mg.featured || ' |||| ' || mg.created || ' |||| ' || COALESCE(mg.title, ' ') || ' |||| ' || COALESCE(mg.description, ' ')) filter (where mg.image_url is not null) gallery,
|
||||
ARRAY_AGG(DISTINCT md.joining_platform_id || ' |||| ' || dp.short || ' |||| ' || dp.name || ' |||| ' || md.url) filter (where md.joining_platform_id is not null) donations
|
||||
@@ -643,8 +642,7 @@ impl Project {
|
||||
LEFT JOIN mods_donations md ON md.joining_mod_id = m.id
|
||||
LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id
|
||||
LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id
|
||||
LEFT JOIN categories c ON mc.joining_category_id = c.id AND mc.is_additional = FALSE
|
||||
LEFT JOIN categories ca ON mc.joining_category_id = c.id AND mc.is_additional = TRUE
|
||||
LEFT JOIN categories c ON mc.joining_category_id = c.id
|
||||
LEFT JOIN versions v ON v.mod_id = m.id
|
||||
LEFT JOIN mods_gallery mg ON mg.mod_id = m.id
|
||||
WHERE m.id = $1
|
||||
@@ -656,6 +654,23 @@ impl Project {
|
||||
.await?;
|
||||
|
||||
if let Some(m) = result {
|
||||
let categories_raw = m.categories.unwrap_or_default();
|
||||
|
||||
let mut categories = Vec::new();
|
||||
let mut additional_categories = Vec::new();
|
||||
|
||||
for category in categories_raw {
|
||||
let category: Vec<&str> = category.split(" |||| ").collect();
|
||||
|
||||
if category.len() >= 2 {
|
||||
if category[1].parse::<bool>().ok().unwrap_or_default() {
|
||||
additional_categories.push(category[0].to_string());
|
||||
} else {
|
||||
categories.push(category[0].to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Some(QueryProject {
|
||||
inner: Project {
|
||||
id: ProjectId(m.id),
|
||||
@@ -685,10 +700,8 @@ impl Project {
|
||||
approved: m.approved,
|
||||
},
|
||||
project_type: m.project_type_name,
|
||||
categories: m.categories.unwrap_or_default(),
|
||||
additional_categories: m
|
||||
.additional_categories
|
||||
.unwrap_or_default(),
|
||||
categories,
|
||||
additional_categories,
|
||||
versions: {
|
||||
let versions = m.versions.unwrap_or_default();
|
||||
|
||||
@@ -803,8 +816,7 @@ impl Project {
|
||||
m.issues_url issues_url, m.source_url source_url, m.wiki_url wiki_url, m.discord_url discord_url, m.license_url license_url,
|
||||
m.team_id team_id, m.client_side client_side, m.server_side server_side, m.license license, m.slug slug, m.moderation_message moderation_message, m.moderation_message_body moderation_message_body,
|
||||
s.status status_name, cs.name client_side_type, ss.name server_side_type, l.short short, l.name license_name, pt.name project_type_name,
|
||||
ARRAY_AGG(DISTINCT c.category) filter (where c.category is not null) categories,
|
||||
ARRAY_AGG(DISTINCT ca.category) filter (where ca.category is not null) additional_categories,
|
||||
ARRAY_AGG(DISTINCT c.category || ' |||| ' || mc.is_additional) filter (where c.category is not null) categories,
|
||||
ARRAY_AGG(DISTINCT v.id || ' |||| ' || v.date_published) filter (where v.id is not null) versions,
|
||||
ARRAY_AGG(DISTINCT mg.image_url || ' |||| ' || mg.featured || ' |||| ' || mg.created || ' |||| ' || COALESCE(mg.title, ' ') || ' |||| ' || COALESCE(mg.description, ' ')) filter (where mg.image_url is not null) gallery,
|
||||
ARRAY_AGG(DISTINCT md.joining_platform_id || ' |||| ' || dp.short || ' |||| ' || dp.name || ' |||| ' || md.url) filter (where md.joining_platform_id is not null) donations
|
||||
@@ -817,8 +829,7 @@ impl Project {
|
||||
LEFT JOIN mods_donations md ON md.joining_mod_id = m.id
|
||||
LEFT JOIN donation_platforms dp ON md.joining_platform_id = dp.id
|
||||
LEFT JOIN mods_categories mc ON mc.joining_mod_id = m.id
|
||||
LEFT JOIN categories c ON mc.joining_category_id = c.id AND mc.is_additional = FALSE
|
||||
LEFT JOIN categories ca ON mc.joining_category_id = c.id AND mc.is_additional = TRUE
|
||||
LEFT JOIN categories c ON mc.joining_category_id = c.id
|
||||
LEFT JOIN versions v ON v.mod_id = m.id
|
||||
LEFT JOIN mods_gallery mg ON mg.mod_id = m.id
|
||||
WHERE m.id = ANY($1)
|
||||
@@ -830,6 +841,25 @@ impl Project {
|
||||
.try_filter_map(|e| async {
|
||||
Ok(e.right().map(|m| {
|
||||
let id = m.id;
|
||||
|
||||
let categories_raw = m.categories.unwrap_or_default();
|
||||
|
||||
let mut categories = Vec::new();
|
||||
let mut additional_categories = Vec::new();
|
||||
|
||||
for category in categories_raw {
|
||||
let category: Vec<&str> =
|
||||
category.split(" |||| ").collect();
|
||||
|
||||
if category.len() >= 2 {
|
||||
if category[1].parse::<bool>().ok().unwrap_or_default() {
|
||||
additional_categories.push(category[0].to_string());
|
||||
} else {
|
||||
categories.push(category[0].to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QueryProject {
|
||||
inner: Project {
|
||||
id: ProjectId(id),
|
||||
@@ -859,8 +889,8 @@ impl Project {
|
||||
approved: m.approved
|
||||
},
|
||||
project_type: m.project_type_name,
|
||||
categories: m.categories.unwrap_or_default(),
|
||||
additional_categories: m.additional_categories.unwrap_or_default(),
|
||||
categories,
|
||||
additional_categories,
|
||||
versions: {
|
||||
let versions = m.versions.unwrap_or_default();
|
||||
|
||||
|
||||
@@ -735,14 +735,14 @@ impl Version {
|
||||
|
||||
if dependency.len() >= 4 {
|
||||
Some(QueryDependency {
|
||||
project_id: match &*dependency[1] {
|
||||
project_id: match dependency[1] {
|
||||
"0" => None,
|
||||
_ => match dependency[1].parse() {
|
||||
Ok(x) => Some(ProjectId(x)),
|
||||
Err(_) => None,
|
||||
},
|
||||
},
|
||||
version_id: match &*dependency[0] {
|
||||
version_id: match dependency[0] {
|
||||
"0" => None,
|
||||
_ => match dependency[0].parse() {
|
||||
Ok(x) => Some(VersionId(x)),
|
||||
@@ -896,14 +896,14 @@ impl Version {
|
||||
|
||||
if dependency.len() >= 4 {
|
||||
Some(QueryDependency {
|
||||
project_id: match &*dependency[1] {
|
||||
project_id: match dependency[1] {
|
||||
"0" => None,
|
||||
_ => match dependency[1].parse() {
|
||||
Ok(x) => Some(ProjectId(x)),
|
||||
Err(_) => None,
|
||||
},
|
||||
},
|
||||
version_id: match &*dependency[0] {
|
||||
version_id: match dependency[0] {
|
||||
"0" => None,
|
||||
_ => match dependency[0].parse() {
|
||||
Ok(x) => Some(VersionId(x)),
|
||||
|
||||
@@ -219,7 +219,10 @@ pub struct License {
|
||||
pub struct DonationLink {
|
||||
pub id: String,
|
||||
pub platform: String,
|
||||
#[validate(url)]
|
||||
#[validate(
|
||||
custom(function = "crate::util::validate::validate_url"),
|
||||
length(max = 2048)
|
||||
)]
|
||||
pub url: String,
|
||||
}
|
||||
|
||||
@@ -482,7 +485,7 @@ impl DependencyType {
|
||||
}
|
||||
|
||||
/// A specific version of Minecraft
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq)]
|
||||
#[derive(Serialize, Deserialize, Clone, PartialEq, Eq)]
|
||||
#[serde(transparent)]
|
||||
pub struct GameVersion(pub String);
|
||||
|
||||
|
||||
@@ -25,11 +25,18 @@ pub async fn count_download(
|
||||
let project_id: crate::database::models::ids::ProjectId =
|
||||
download_body.hash.into();
|
||||
|
||||
let id_option = crate::models::ids::base62_impl::parse_base62(
|
||||
&download_body.version_name,
|
||||
)
|
||||
.ok()
|
||||
.map(|x| x as i64);
|
||||
|
||||
let (version_id, project_id) = if let Some(version) = sqlx::query!(
|
||||
"SELECT id, mod_id FROM versions
|
||||
WHERE (version_number = $1 AND mod_id = $2)",
|
||||
WHERE ((version_number = $1 OR id = $3) AND mod_id = $2)",
|
||||
download_body.version_name,
|
||||
project_id as crate::database::models::ids::ProjectId
|
||||
project_id as crate::database::models::ids::ProjectId,
|
||||
id_option
|
||||
)
|
||||
.fetch_optional(pool.as_ref())
|
||||
.await?
|
||||
|
||||
@@ -118,7 +118,7 @@ pub async fn maven_metadata(
|
||||
.last()
|
||||
.unwrap_or(&"release".to_string())
|
||||
.to_string(),
|
||||
release: latest_release.unwrap_or_default().to_string(),
|
||||
release: latest_release.unwrap_or_default(),
|
||||
versions: Versions {
|
||||
versions: new_versions,
|
||||
},
|
||||
|
||||
@@ -170,19 +170,34 @@ struct ProjectCreateData {
|
||||
/// A list of the categories that the project is in.
|
||||
pub additional_categories: Vec<String>,
|
||||
|
||||
#[validate(url, length(max = 2048))]
|
||||
#[validate(
|
||||
custom(function = "crate::util::validate::validate_url"),
|
||||
length(max = 2048)
|
||||
)]
|
||||
/// An optional link to where to submit bugs or issues with the project.
|
||||
pub issues_url: Option<String>,
|
||||
#[validate(url, length(max = 2048))]
|
||||
#[validate(
|
||||
custom(function = "crate::util::validate::validate_url"),
|
||||
length(max = 2048)
|
||||
)]
|
||||
/// An optional link to the source code for the project.
|
||||
pub source_url: Option<String>,
|
||||
#[validate(url, length(max = 2048))]
|
||||
#[validate(
|
||||
custom(function = "crate::util::validate::validate_url"),
|
||||
length(max = 2048)
|
||||
)]
|
||||
/// An optional link to the project's wiki page or other relevant information.
|
||||
pub wiki_url: Option<String>,
|
||||
#[validate(url, length(max = 2048))]
|
||||
#[validate(
|
||||
custom(function = "crate::util::validate::validate_url"),
|
||||
length(max = 2048)
|
||||
)]
|
||||
/// An optional link to the project's license page
|
||||
pub license_url: Option<String>,
|
||||
#[validate(url, length(max = 2048))]
|
||||
#[validate(
|
||||
custom(function = "crate::util::validate::validate_url"),
|
||||
length(max = 2048)
|
||||
)]
|
||||
/// An optional link to the project's discord.
|
||||
pub discord_url: Option<String>,
|
||||
/// An optional list of all donation links the project has\
|
||||
@@ -550,7 +565,7 @@ pub async fn project_create_inner(
|
||||
&cdn_url,
|
||||
&content_disposition,
|
||||
project_id,
|
||||
&version_data.version_number,
|
||||
created_version.version_id.into(),
|
||||
&*project_create_data.project_type,
|
||||
version_data.loaders.clone(),
|
||||
version_data.game_versions.clone(),
|
||||
|
||||
@@ -266,35 +266,50 @@ pub struct EditProject {
|
||||
skip_serializing_if = "Option::is_none",
|
||||
with = "::serde_with::rust::double_option"
|
||||
)]
|
||||
#[validate(url, length(max = 2048))]
|
||||
#[validate(
|
||||
custom(function = "crate::util::validate::validate_url"),
|
||||
length(max = 2048)
|
||||
)]
|
||||
pub issues_url: Option<Option<String>>,
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
with = "::serde_with::rust::double_option"
|
||||
)]
|
||||
#[validate(url, length(max = 2048))]
|
||||
#[validate(
|
||||
custom(function = "crate::util::validate::validate_url"),
|
||||
length(max = 2048)
|
||||
)]
|
||||
pub source_url: Option<Option<String>>,
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
with = "::serde_with::rust::double_option"
|
||||
)]
|
||||
#[validate(url, length(max = 2048))]
|
||||
#[validate(
|
||||
custom(function = "crate::util::validate::validate_url"),
|
||||
length(max = 2048)
|
||||
)]
|
||||
pub wiki_url: Option<Option<String>>,
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
with = "::serde_with::rust::double_option"
|
||||
)]
|
||||
#[validate(url, length(max = 2048))]
|
||||
#[validate(
|
||||
custom(function = "crate::util::validate::validate_url"),
|
||||
length(max = 2048)
|
||||
)]
|
||||
pub license_url: Option<Option<String>>,
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
with = "::serde_with::rust::double_option"
|
||||
)]
|
||||
#[validate(url, length(max = 2048))]
|
||||
#[validate(
|
||||
custom(function = "crate::util::validate::validate_url"),
|
||||
length(max = 2048)
|
||||
)]
|
||||
pub discord_url: Option<Option<String>>,
|
||||
#[validate]
|
||||
pub donation_urls: Option<Vec<DonationLink>>,
|
||||
|
||||
@@ -302,7 +302,7 @@ async fn version_create_inner(
|
||||
&cdn_url,
|
||||
&content_disposition,
|
||||
version.project_id.into(),
|
||||
&version.version_number,
|
||||
version.version_id.into(),
|
||||
&*project_type,
|
||||
version_data.loaders,
|
||||
version_data.game_versions,
|
||||
@@ -520,7 +520,6 @@ async fn upload_file_to_version_inner(
|
||||
}
|
||||
|
||||
let project_id = ProjectId(version.project_id.0 as u64);
|
||||
let version_number = version.version_number;
|
||||
|
||||
let project_type = sqlx::query!(
|
||||
"
|
||||
@@ -567,7 +566,7 @@ async fn upload_file_to_version_inner(
|
||||
let mut dependencies = version
|
||||
.dependencies
|
||||
.iter()
|
||||
.map(|x| models::version_item::DependencyBuilder {
|
||||
.map(|x| DependencyBuilder {
|
||||
project_id: x.project_id,
|
||||
version_id: x.version_id,
|
||||
file_name: None,
|
||||
@@ -584,7 +583,7 @@ async fn upload_file_to_version_inner(
|
||||
&cdn_url,
|
||||
&content_disposition,
|
||||
project_id,
|
||||
&version_number,
|
||||
version_id.into(),
|
||||
&*project_type,
|
||||
version.loaders.clone().into_iter().map(Loader).collect(),
|
||||
version
|
||||
@@ -626,7 +625,7 @@ pub async fn upload_file(
|
||||
cdn_url: &str,
|
||||
content_disposition: &actix_web::http::header::ContentDisposition,
|
||||
project_id: ProjectId,
|
||||
version_number: &str,
|
||||
version_id: VersionId,
|
||||
project_type: &str,
|
||||
loaders: Vec<Loader>,
|
||||
game_versions: Vec<GameVersion>,
|
||||
@@ -748,13 +747,11 @@ pub async fn upload_file(
|
||||
let file_path_encode = format!(
|
||||
"data/{}/versions/{}/{}",
|
||||
project_id,
|
||||
version_number,
|
||||
version_id,
|
||||
urlencoding::encode(file_name)
|
||||
);
|
||||
let file_path = format!(
|
||||
"data/{}/versions/{}/{}",
|
||||
project_id, version_number, &file_name
|
||||
);
|
||||
let file_path =
|
||||
format!("data/{}/versions/{}/{}", project_id, version_id, &file_name);
|
||||
|
||||
let upload_data = file_host
|
||||
.upload_file(content_type, &file_path, data.freeze())
|
||||
|
||||
@@ -8,6 +8,7 @@ use meilisearch_sdk::document::Document;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::borrow::Cow;
|
||||
use std::cmp::min;
|
||||
use std::fmt::Write;
|
||||
use thiserror::Error;
|
||||
|
||||
pub mod indexing;
|
||||
@@ -20,6 +21,8 @@ pub enum SearchError {
|
||||
Serde(#[from] serde_json::Error),
|
||||
#[error("Error while parsing an integer: {0}")]
|
||||
IntParsing(#[from] std::num::ParseIntError),
|
||||
#[error("Error while formatting strings: {0}")]
|
||||
FormatError(#[from] std::fmt::Error),
|
||||
#[error("Environment Error")]
|
||||
Env(#[from] dotenv::Error),
|
||||
#[error("Invalid index to sort by: {0}")]
|
||||
@@ -34,6 +37,7 @@ impl actix_web::ResponseError for SearchError {
|
||||
SearchError::Serde(..) => StatusCode::BAD_REQUEST,
|
||||
SearchError::IntParsing(..) => StatusCode::BAD_REQUEST,
|
||||
SearchError::InvalidIndex(..) => StatusCode::BAD_REQUEST,
|
||||
SearchError::FormatError(..) => StatusCode::BAD_REQUEST,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,6 +49,7 @@ impl actix_web::ResponseError for SearchError {
|
||||
SearchError::Serde(..) => "invalid_input",
|
||||
SearchError::IntParsing(..) => "invalid_input",
|
||||
SearchError::InvalidIndex(..) => "invalid_input",
|
||||
SearchError::FormatError(..) => "invalid_input",
|
||||
},
|
||||
description: &self.to_string(),
|
||||
})
|
||||
@@ -215,7 +220,7 @@ pub async fn search_for_project(
|
||||
filter_string.push(')');
|
||||
|
||||
if !filters.is_empty() {
|
||||
filter_string.push_str(&format!(" AND ({})", filter_string))
|
||||
write!(filter_string, " AND ({})", filters)?;
|
||||
}
|
||||
} else {
|
||||
filter_string.push_str(&*filters);
|
||||
|
||||
@@ -88,3 +88,15 @@ pub fn validate_deps(
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn validate_url(value: &String) -> Result<(), validator::ValidationError> {
|
||||
let url = url::Url::parse(value)
|
||||
.ok()
|
||||
.ok_or_else(|| validator::ValidationError::new("invalid URL"))?;
|
||||
|
||||
if url.scheme() != "https" {
|
||||
return Err(validator::ValidationError::new("URL must be https"));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -27,11 +27,11 @@ impl super::Validator for BukkitValidator {
|
||||
&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(),
|
||||
)
|
||||
})?;
|
||||
if archive.by_name("plugin.yml").is_err() {
|
||||
return Ok(ValidationResult::Warning(
|
||||
"No plugin.yml present for plugin file.",
|
||||
));
|
||||
}
|
||||
|
||||
Ok(ValidationResult::Pass)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user