Inherit dependencies from workspace manifest, and optimize some out (#3655)

* chore: inherit dependencies from workspace, optimize some deps out

* Update bitflags from 2.9.0 to 2.9.1

* Fix temp directory leak in check_java_at_filepath

* Fix build

* Fix lint

* chore(app-lib): refactor overkill `futures` executor usage to Tokio MPSC

* chore: fix Clippy lint

* tweak: optimize out dependency on OpenSSL source build

Contrary to what I expected before, this was caused due to the Tauri
updater plugin using a different TLS stack than everything else.

* chore(labrinth): drop now unused dependency

* Update zip because 2.6.1 got yanked

* Downgrade weezl to 0.1.8

* Mention that p256 is also a blocker for rand 0.9

* chore: sidestep GitHub review requirements

* chore: sidestep GitHub review requirements (2)

* chore: sidestep GitHub review requirements (3)

---------

Co-authored-by: Josiah Glosson <soujournme@gmail.com>
This commit is contained in:
Alejandro González
2025-05-15 22:47:29 +02:00
committed by GitHub
parent 37cc81a36d
commit f19643095e
35 changed files with 876 additions and 1020 deletions

View File

@@ -6,9 +6,6 @@ edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
theseus = { path = "../../packages/app-lib", features = ["cli"] }
tokio = { version = "1", features = ["full"] }
webbrowser = "1.0.4"
enumset = "1.1"
tracing = "0.1.37"
theseus = { workspace = true, features = ["cli"] }
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
enumset.workspace = true

View File

@@ -15,8 +15,7 @@ pub async fn authenticate_run() -> theseus::Result<Credentials> {
println!("A browser window will now open, follow the login flow there.");
let login = minecraft_auth::begin_login().await?;
println!("URL {}", login.redirect_uri.as_str());
webbrowser::open(login.redirect_uri.as_str())?;
println!("Open URL {} in a browser", login.redirect_uri.as_str());
println!("Please enter URL code: ");
let mut input = String::new();

View File

@@ -8,47 +8,45 @@ edition = "2024"
build = "build.rs"
[build-dependencies]
tauri-build = { version = "2.2.0", features = ["codegen"] }
tauri-build = { workspace = true, features = ["codegen"] }
[dependencies]
theseus = { path = "../../packages/app-lib", features = ["tauri"] }
theseus = { workspace = true, features = ["tauri"] }
serde_json = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_with = "3.0.0"
serde_json.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_with.workspace = true
tauri = { version = "2.5.1", features = ["devtools", "macos-private-api", "protocol-asset", "unstable"] }
tauri-plugin-window-state = "2.2.0"
tauri-plugin-deep-link = "2.2.0"
tauri-plugin-os = "2.2.0"
tauri-plugin-opener = "2.2.6"
tauri-plugin-dialog = "2.2.0"
tauri-plugin-updater = { version = "2.3.0" }
tauri-plugin-single-instance = { version = "2.2.0" }
tauri = { workspace = true, features = ["devtools", "macos-private-api", "protocol-asset", "unstable"] }
tauri-plugin-window-state.workspace = true
tauri-plugin-deep-link.workspace = true
tauri-plugin-os.workspace = true
tauri-plugin-opener.workspace = true
tauri-plugin-dialog.workspace = true
tauri-plugin-updater.workspace = true
tauri-plugin-single-instance.workspace = true
tokio = { version = "1", features = ["full"] }
thiserror = "2.0.12"
daedalus = { path = "../../packages/daedalus" }
chrono = "0.4.26"
either = "1.15"
tokio = { workspace = true, features = ["time"] }
thiserror.workspace = true
daedalus.workspace = true
chrono.workspace = true
either.workspace = true
url = "2.2"
urlencoding = "2.1"
uuid = { version = "1.1", features = ["serde", "v4"] }
url.workspace = true
urlencoding.workspace = true
uuid = { workspace = true, features = ["serde", "v4"] }
tracing = "0.1.37"
tracing-error = "0.2.0"
tracing.workspace = true
tracing-error.workspace = true
dashmap = "6.1.0"
paste = "1.0.15"
enumset = { version = "1.1", features = ["serde"] }
dashmap.workspace = true
paste.workspace = true
enumset = { workspace = true, features = ["serde"] }
opener = { version = "0.7.2", features = ["reveal", "dbus-vendored"] }
native-dialog = "0.9.0"
native-dialog.workspace = true
[target.'cfg(target_os = "linux")'.dependencies]
tauri-plugin-updater = { version = "2.3.0", optional = true, features = ["native-tls-vendored", "zip"], default-features = false }
tauri-plugin-updater = { workspace = true, optional = true }
[features]
# by default Tauri runs in production mode

View File

@@ -1,4 +1,6 @@
use serde::{Deserialize, Serialize};
use tauri::Runtime;
use tauri_plugin_opener::OpenerExt;
use theseus::{
handler,
prelude::{CommandPayload, DirectoryInfo},
@@ -74,29 +76,29 @@ pub async fn should_disable_mouseover() -> bool {
}
#[tauri::command]
pub fn highlight_in_folder(path: PathBuf) {
let res = opener::reveal(path);
if let Err(e) = res {
pub fn highlight_in_folder<R: Runtime>(
app: tauri::AppHandle<R>,
path: PathBuf,
) {
if let Err(e) = app.opener().reveal_item_in_dir(path) {
tracing::error!("Failed to highlight file in folder: {}", e);
}
}
#[tauri::command]
pub fn open_path(path: PathBuf) {
let res = opener::open(path);
if let Err(e) = res {
pub fn open_path<R: Runtime>(app: tauri::AppHandle<R>, path: PathBuf) {
if let Err(e) = app.opener().open_path(path.to_string_lossy(), None::<&str>)
{
tracing::error!("Failed to open path: {}", e);
}
}
#[tauri::command]
pub fn show_launcher_logs_folder() {
pub fn show_launcher_logs_folder<R: Runtime>(app: tauri::AppHandle<R>) {
let path = DirectoryInfo::launcher_logs_dir().unwrap_or_default();
// failure to get folder just opens filesystem
// (ie: if in debug mode only and launcher_logs never created)
open_path(path);
open_path(app, path);
}
// Get opening command

View File

@@ -7,25 +7,24 @@ edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
daedalus = { path = "../../packages/daedalus" }
tokio = { version = "1", features = ["full"] }
futures = "0.3.25"
dotenvy = "0.15.6"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde-xml-rs = "0.6.0"
lazy_static = "1.4.0"
thiserror = "2.0"
reqwest = { version = "0.12.15", default-features = false, features = ["stream", "json", "rustls-tls-native-roots"] }
async_zip = { version = "0.0.17", features = ["full"] }
chrono = { version = "0.4", features = ["serde"] }
bytes = "1.6.0"
rust-s3 = { version = "0.35.1", default-features = false, features = ["fail-on-err", "tags", "tokio-rustls-tls"] }
dashmap = "6.1.0"
sha1_smol = { version = "1.0.0", features = ["std"] }
indexmap = { version = "2.2.6", features = ["serde"] }
itertools = "0.14.0"
tracing-error = "0.2.0"
daedalus.workspace = true
tokio = { workspace = true, features = ["sync", "macros", "rt-multi-thread"] }
futures.workspace = true
dotenvy.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
serde-xml-rs.workspace = true
thiserror.workspace = true
reqwest = { workspace = true, features = ["stream", "json", "rustls-tls-native-roots"] }
async_zip = { workspace = true, features = ["chrono", "tokio-fs", "deflate", "bzip2", "zstd", "deflate64"] }
chrono = { workspace = true, features = ["serde"] }
bytes.workspace = true
rust-s3.workspace = true
dashmap.workspace = true
sha1_smol.workspace = true
indexmap = { workspace = true, features = ["serde"] }
itertools.workspace = true
tracing-error.workspace = true
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
tracing.workspace = true
tracing-subscriber = { workspace = true, features = ["env-filter"] }

View File

@@ -3,59 +3,57 @@ use bytes::Bytes;
use s3::creds::Credentials;
use s3::{Bucket, Region};
use serde::de::DeserializeOwned;
use std::sync::Arc;
use std::sync::{Arc, LazyLock};
use tokio::sync::Semaphore;
lazy_static::lazy_static! {
static ref BUCKET: Bucket = {
let region = dotenvy::var("S3_REGION").unwrap();
let b = Bucket::new(
&dotenvy::var("S3_BUCKET_NAME").unwrap(),
if &*region == "r2" {
Region::R2 {
account_id: dotenvy::var("S3_URL").unwrap(),
}
} else {
Region::Custom {
region: region.clone(),
endpoint: dotenvy::var("S3_URL").unwrap(),
}
},
Credentials::new(
Some(&*dotenvy::var("S3_ACCESS_TOKEN").unwrap()),
Some(&*dotenvy::var("S3_SECRET").unwrap()),
None,
None,
None,
).unwrap(),
).unwrap();
if region == "path-style" {
*b.with_path_style()
static BUCKET: LazyLock<Bucket> = LazyLock::new(|| {
let region = dotenvy::var("S3_REGION").unwrap();
let b = Bucket::new(
&dotenvy::var("S3_BUCKET_NAME").unwrap(),
if &*region == "r2" {
Region::R2 {
account_id: dotenvy::var("S3_URL").unwrap(),
}
} else {
*b
}
};
}
Region::Custom {
region: region.clone(),
endpoint: dotenvy::var("S3_URL").unwrap(),
}
},
Credentials::new(
Some(&*dotenvy::var("S3_ACCESS_TOKEN").unwrap()),
Some(&*dotenvy::var("S3_SECRET").unwrap()),
None,
None,
None,
)
.unwrap(),
)
.unwrap();
lazy_static::lazy_static! {
pub static ref REQWEST_CLIENT: reqwest::Client = {
let mut headers = reqwest::header::HeaderMap::new();
if let Ok(header) = reqwest::header::HeaderValue::from_str(&format!(
"modrinth/daedalus/{} (support@modrinth.com)",
env!("CARGO_PKG_VERSION")
)) {
headers.insert(reqwest::header::USER_AGENT, header);
}
if region == "path-style" {
*b.with_path_style()
} else {
*b
}
});
reqwest::Client::builder()
.tcp_keepalive(Some(std::time::Duration::from_secs(10)))
.timeout(std::time::Duration::from_secs(15))
.default_headers(headers)
.build()
.unwrap()
};
}
pub static REQWEST_CLIENT: LazyLock<reqwest::Client> = LazyLock::new(|| {
let mut headers = reqwest::header::HeaderMap::new();
if let Ok(header) = reqwest::header::HeaderValue::from_str(&format!(
"modrinth/daedalus/{} (support@modrinth.com)",
env!("CARGO_PKG_VERSION")
)) {
headers.insert(reqwest::header::USER_AGENT, header);
}
reqwest::Client::builder()
.tcp_keepalive(Some(std::time::Duration::from_secs(10)))
.timeout(std::time::Duration::from_secs(15))
.default_headers(headers)
.build()
.unwrap()
});
#[tracing::instrument(skip(bytes, semaphore))]
pub async fn upload_file_to_bucket(

View File

@@ -11,74 +11,72 @@ name = "labrinth"
path = "src/main.rs"
[dependencies]
actix-web = "4.10.2"
actix-rt = "2.9.0"
actix-multipart = "0.7.2"
actix-cors = "0.7.1"
actix-ws = "0.3.0"
actix-files = "0.6.5"
prometheus = "0.13.4" # Locked on 0.13 until actix updates to 0.14
actix-web-prom = { version = "0.9.0", features = ["process"] }
actix-web.workspace = true
actix-rt.workspace = true
actix-multipart.workspace = true
actix-cors.workspace = true
actix-ws.workspace = true
actix-files.workspace = true
prometheus.workspace = true
actix-web-prom = { workspace = true, features = ["process"] }
tracing = "0.1.41"
tracing-actix-web = "0.7.18"
console-subscriber = "0.4.1"
tracing.workspace = true
tracing-actix-web.workspace = true
console-subscriber.workspace = true
tokio = { version = "1.35.1", features = ["sync", "rt-multi-thread"] }
tokio-stream = "0.1.14"
tokio = { workspace = true, features = ["sync", "rt-multi-thread"] }
tokio-stream.workspace = true
futures = "0.3.30"
futures-util = "0.3.30"
async-trait = "0.1.70"
dashmap = "6.1.0"
lazy_static = "1.4.0"
futures.workspace = true
futures-util.workspace = true
async-trait.workspace = true
dashmap.workspace = true
meilisearch-sdk = "0.28.0"
rust-s3 = { version = "0.35.1", default-features = false, features = ["fail-on-err", "tags", "tokio-rustls-tls"] }
reqwest = { version = "0.12.15", features = ["json", "multipart"] }
hyper = { version = "1.6", features = ["full"] }
hyper-tls = "0.6.0"
hyper-util = "0.1.11"
meilisearch-sdk = { workspace = true, features = ["reqwest"] }
rust-s3.workspace = true
reqwest = { workspace = true, features = ["http2", "rustls-tls-webpki-roots", "json", "multipart"] }
hyper-tls.workspace = true
hyper-util.workspace = true
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_with = "3.0.0"
chrono = { version = "0.4.26", features = ["serde"] }
yaserde = "0.12.0"
yaserde_derive = "0.12.0"
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
serde_with.workspace = true
chrono = { workspace = true, features = ["serde"] }
yaserde = { workspace = true, features = ["derive"] }
rand = "0.8.5" # Locked on 0.8 until argon2 updates to 0.9
rand_chacha = "0.3.1" # Locked on 0.3 until we can update rand to 0.9
bytes = "1.4.0"
base64 = "0.22.1"
sha1 = { version = "0.10.6", features = ["std"] }
sha2 = "0.10.9"
hmac = "0.12.1"
argon2 = { version = "0.5.0", features = ["std"] }
murmur2 = "0.1.0"
bitflags = "2.4.0"
hex = "0.4.3"
zxcvbn = "3.1.0"
totp-rs = { version = "5.0.2", features = ["gen_secret"] }
rand.workspace = true
rand_chacha.workspace = true
bytes.workspace = true
base64.workspace = true
sha1.workspace = true
sha2.workspace = true
hmac.workspace = true
argon2.workspace = true
murmur2.workspace = true
bitflags.workspace = true
hex.workspace = true
zxcvbn.workspace = true
totp-rs = { workspace = true, features = ["gen_secret"] }
url = "2.4.0"
urlencoding = "2.1.2"
url.workspace = true
urlencoding.workspace = true
zip = "2.6.1"
zip.workspace = true
itertools = "0.14.0"
itertools.workspace = true
validator = { version = "0.20.0", features = ["derive"] }
regex = "1.10.2"
censor = "0.3.0"
spdx = { version = "0.10.3", features = ["text"] }
validator = { workspace = true, features = ["derive"] }
regex.workspace = true
censor.workspace = true
spdx = { workspace = true, features = ["text"] }
dotenvy = "0.15.7"
thiserror = "2.0.12"
either = "1.13"
dotenvy.workspace = true
thiserror.workspace = true
either.workspace = true
sqlx = { version = "0.8.2", features = [
"runtime-tokio-rustls",
sqlx = { workspace = true, features = [
"runtime-tokio",
"tls-rustls-ring",
"postgres",
"chrono",
"macros",
@@ -86,51 +84,49 @@ sqlx = { version = "0.8.2", features = [
"rust_decimal",
"json",
] }
rust_decimal = { version = "1.33.1", features = [
rust_decimal = { workspace = true, features = [
"serde-with-float",
"serde-with-str",
] }
redis = { version = "0.29.5", features = ["tokio-comp", "ahash", "r2d2"] } # Locked on 0.29 until deadpool-redis updates to 0.30
deadpool-redis = "0.20.0"
clickhouse = { version = "0.13.2", features = ["uuid", "time"] }
uuid = { version = "1.2.2", features = ["v4", "fast-rng", "serde"] }
redis = { workspace = true, features = ["tokio-comp", "ahash", "r2d2"] } # Locked on 0.29 until deadpool-redis updates to 0.30
deadpool-redis.workspace = true
clickhouse = { workspace = true, features = ["uuid", "time"] }
uuid = { workspace = true, features = ["v4", "fast-rng", "serde"] }
maxminddb = "0.26.0"
flate2 = "1.0.25"
tar = "0.4.38"
maxminddb.workspace = true
flate2.workspace = true
tar.workspace = true
sentry = { version = "0.37.0", default-features = false, features = ["backtrace", "contexts", "debug-images", "panic", "rustls", "reqwest"] }
sentry-actix = "0.37.0"
sentry.workspace = true
sentry-actix.workspace = true
image = "0.25.6"
color-thief = "0.2.2"
webp = "0.3.0"
image = { workspace = true, features = ["avif", "bmp", "dds", "exr", "ff", "gif", "hdr", "ico", "jpeg", "png", "pnm", "qoi", "tga", "tiff", "webp"] }
color-thief.workspace = true
webp.workspace = true
woothee = "0.13.0"
woothee.workspace = true
lettre = "0.11.3"
lettre.workspace = true
derive-new = "0.7.0"
rust_iso3166 = "0.1.11"
rust_iso3166.workspace = true
async-stripe = { version = "0.41.0", features = ["runtime-tokio-hyper-rustls"] }
rusty-money = "0.4.1"
json-patch = "4.0.0"
async-stripe = { workspace = true, features = ["billing", "checkout", "connect", "webhook-events"] }
rusty-money.workspace = true
json-patch.workspace = true
ariadne = { path = "../../packages/ariadne" }
ariadne.workspace = true
clap = { version = "4.5", features = ["derive"] }
iana-time-zone = "0.1.61"
clap = { workspace = true, features = ["derive"] }
[target.'cfg(target_os = "linux")'.dependencies]
tikv-jemallocator = { version = "0.6.0", features = ["profiling", "unprefixed_malloc_on_supported_platforms"] }
tikv-jemalloc-ctl = { version = "0.6.0", features = ["stats"] }
jemalloc_pprof = { version = "0.7.0", features = ["flamegraph"] }
tikv-jemallocator = { workspace = true, features = ["profiling", "unprefixed_malloc_on_supported_platforms"] }
tikv-jemalloc-ctl = { workspace = true, features = ["stats"] }
jemalloc_pprof = { workspace = true, features = ["flamegraph"] }
[dev-dependencies]
actix-http = "3.4.0"
actix-http.workspace = true
[build-dependencies]
dotenv-build = "0.1.1"
chrono = "0.4.38"
iana-time-zone = "0.1.60"
dotenv-build.workspace = true
chrono.workspace = true
iana-time-zone.workspace = true

View File

@@ -111,10 +111,10 @@ pub async fn init_oauth(
.map_err(|e| {
OAuthError::redirect(e, &oauth_info.state, &redirect_uri)
})?;
let redirect_uris = OAuthRedirectUris::new(
oauth_info.redirect_uri.clone(),
redirect_uri.clone(),
);
let redirect_uris = OAuthRedirectUris {
original: oauth_info.redirect_uri.clone(),
validated: redirect_uri.clone(),
};
match existing_authorization {
Some(existing_authorization)
if existing_authorization.scopes.contains(requested_scopes) =>

View File

@@ -3,7 +3,7 @@ use crate::auth::oauth::OAuthErrorType;
use crate::database::models::OAuthClientId;
use serde::{Deserialize, Serialize};
#[derive(derive_new::new, Serialize, Deserialize)]
#[derive(Serialize, Deserialize)]
pub struct OAuthRedirectUris {
pub original: Option<String>,
pub validated: ValidatedRedirectUri,

View File

@@ -132,6 +132,8 @@ pub async fn payouts(
}
mod version_updater {
use std::sync::LazyLock;
use crate::database::models::legacy_loader_fields::MinecraftGameVersion;
use crate::database::redis::RedisPool;
use chrono::{DateTime, Utc};
@@ -197,36 +199,45 @@ mod version_updater {
("3D Shareware v1.34", "3D-Shareware-v1.34"),
];
lazy_static::lazy_static! {
/// Mojank for some reason has versions released at the same DateTime. This hardcodes them to fix this,
/// as most of our ordering logic is with DateTime
static ref HALL_OF_SHAME_2: [(&'static str, DateTime<Utc>); 4] = [
(
"1.4.5",
chrono::DateTime::parse_from_rfc3339("2012-12-19T22:00:00+00:00")
/// Mojank for some reason has versions released at the same DateTime. This hardcodes them to fix this,
/// as most of our ordering logic is with DateTime
static HALL_OF_SHAME_2: LazyLock<[(&'static str, DateTime<Utc>); 4]> =
LazyLock::new(|| {
[
(
"1.4.5",
chrono::DateTime::parse_from_rfc3339(
"2012-12-19T22:00:00+00:00",
)
.unwrap()
.into(),
),
(
"1.4.6",
chrono::DateTime::parse_from_rfc3339("2012-12-19T22:00:01+00:00")
),
(
"1.4.6",
chrono::DateTime::parse_from_rfc3339(
"2012-12-19T22:00:01+00:00",
)
.unwrap()
.into(),
),
(
"1.6.3",
chrono::DateTime::parse_from_rfc3339("2013-09-13T10:54:41+00:00")
),
(
"1.6.3",
chrono::DateTime::parse_from_rfc3339(
"2013-09-13T10:54:41+00:00",
)
.unwrap()
.into(),
),
(
"13w37b",
chrono::DateTime::parse_from_rfc3339("2013-09-13T10:54:42+00:00")
),
(
"13w37b",
chrono::DateTime::parse_from_rfc3339(
"2013-09-13T10:54:42+00:00",
)
.unwrap()
.into(),
),
];
}
),
]
});
for version in input.versions.into_iter() {
let mut name = version.id;

View File

@@ -117,11 +117,10 @@ impl GalleryItem {
}
}
#[derive(derive_new::new)]
pub struct ModCategory {
project_id: ProjectId,
category_id: CategoryId,
is_additional: bool,
pub project_id: ProjectId,
pub category_id: CategoryId,
pub is_additional: bool,
}
impl ModCategory {
@@ -245,12 +244,18 @@ impl ProjectBuilder {
let project_id = self.project_id;
let mod_categories = categories
.into_iter()
.map(|c| ModCategory::new(project_id, c, false))
.chain(
additional_categories
.into_iter()
.map(|c| ModCategory::new(project_id, c, true)),
)
.map(|category_id| ModCategory {
project_id,
category_id,
is_additional: false,
})
.chain(additional_categories.into_iter().map(|category_id| {
ModCategory {
project_id,
category_id,
is_additional: true,
}
}))
.collect_vec();
ModCategory::insert_many(mod_categories, &mut *transaction).await?;

View File

@@ -229,7 +229,10 @@ impl VersionBuilder {
let loader_versions = loaders
.iter()
.map(|l| LoaderVersion::new(*l, version_id))
.map(|&loader_id| LoaderVersion {
loader_id,
version_id,
})
.collect_vec();
LoaderVersion::insert_many(loader_versions, transaction).await?;
@@ -239,7 +242,7 @@ impl VersionBuilder {
}
}
#[derive(derive_new::new, Serialize, Deserialize)]
#[derive(Serialize, Deserialize)]
pub struct LoaderVersion {
pub loader_id: LoaderId,
pub version_id: VersionId,

View File

@@ -152,7 +152,7 @@ async fn main() -> std::io::Result<()> {
.expect("Failed to register redis metrics");
#[cfg(target_os = "linux")]
labrinth::routes::debug::jemalloc_mmeory_stats(&prometheus.registry)
labrinth::routes::debug::jemalloc_memory_stats(&prometheus.registry)
.expect("Failed to register jemalloc metrics");
let labrinth_config = labrinth::app_setup(

View File

@@ -50,7 +50,7 @@ fn require_profiling_activated(
}
}
pub fn jemalloc_mmeory_stats(
pub fn jemalloc_memory_stats(
registry: &Registry,
) -> Result<(), prometheus::Error> {
let allocated_mem = IntGauge::new(

View File

@@ -13,7 +13,7 @@ use crate::util::captcha::check_hcaptcha;
use crate::util::env::parse_strings_from_var;
use crate::util::ext::get_image_ext;
use crate::util::img::upload_image_optimized;
use crate::util::validate::{RE_URL_SAFE, validation_errors_to_string};
use crate::util::validate::validation_errors_to_string;
use actix_web::web::{Data, Query, ServiceConfig, scope};
use actix_web::{HttpRequest, HttpResponse, delete, get, patch, post, web};
use argon2::password_hash::SaltString;
@@ -1318,7 +1318,7 @@ pub async fn sign_up_sendy(email: &str) -> Result<(), AuthenticationError> {
#[derive(Deserialize, Validate)]
pub struct NewAccount {
#[validate(length(min = 1, max = 39), regex(path = *RE_URL_SAFE))]
#[validate(length(min = 1, max = 39), regex(path = *crate::util::validate::RE_URL_SAFE))]
pub username: String,
#[validate(length(min = 8, max = 256))]
pub password: String,

View File

@@ -12,7 +12,7 @@ use crate::{auth::get_user_from_headers, database};
use actix_web::{HttpRequest, HttpResponse, get, route, web};
use sqlx::PgPool;
use std::collections::HashSet;
use yaserde_derive::YaSerialize;
use yaserde::YaSerialize;
pub fn config(cfg: &mut web::ServiceConfig) {
cfg.service(maven_metadata);

View File

@@ -9,8 +9,6 @@ use crate::models::v2::user::LegacyUser;
use crate::queue::session::AuthQueue;
use crate::routes::{ApiError, v2_reroute, v3};
use actix_web::{HttpRequest, HttpResponse, delete, get, patch, web};
use lazy_static::lazy_static;
use regex::Regex;
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use std::sync::Arc;
@@ -135,20 +133,16 @@ pub async fn projects_list(
}
}
lazy_static! {
static ref RE_URL_SAFE: Regex = Regex::new(r"^[a-zA-Z0-9_-]*$").unwrap();
}
#[derive(Serialize, Deserialize, Validate)]
pub struct EditUser {
#[validate(length(min = 1, max = 39), regex(path = *RE_URL_SAFE))]
#[validate(length(min = 1, max = 39), regex(path = *crate::util::validate::RE_URL_SAFE))]
pub username: Option<String>,
#[serde(
default,
skip_serializing_if = "Option::is_none",
with = "::serde_with::rust::double_option"
)]
#[validate(length(min = 1, max = 64), regex(path = *RE_URL_SAFE))]
#[validate(length(min = 1, max = 64), regex(path = *crate::util::validate::RE_URL_SAFE))]
pub name: Option<Option<String>>,
#[serde(
default,

View File

@@ -906,11 +906,11 @@ pub async fn edit_project_categories(
categories: &Vec<String>,
perms: &ProjectPermissions,
project_id: db_ids::ProjectId,
additional: bool,
is_additional: bool,
transaction: &mut sqlx::Transaction<'_, sqlx::Postgres>,
) -> Result<(), ApiError> {
if !perms.contains(ProjectPermissions::EDIT_DETAILS) {
let additional_str = if additional { "additional " } else { "" };
let additional_str = if is_additional { "additional " } else { "" };
return Err(ApiError::CustomAuthentication(format!(
"You do not have the permissions to edit the {additional_str}categories of this project!"
)));
@@ -928,7 +928,11 @@ pub async fn edit_project_categories(
let mcategories = category_ids
.values()
.map(|x| ModCategory::new(project_id, *x, additional))
.map(|&category_id| ModCategory {
project_id,
category_id,
is_additional,
})
.collect::<Vec<_>>();
mod_categories.extend(mcategories);
}
@@ -1081,7 +1085,6 @@ pub async fn dependency_list(
}
}
#[derive(derive_new::new)]
pub struct CategoryChanges<'a> {
pub categories: &'a Option<Vec<String>>,
pub add_categories: &'a Option<Vec<String>>,
@@ -1241,11 +1244,11 @@ pub async fn projects_edit(
&categories,
&project.categories,
project.inner.id as db_ids::ProjectId,
CategoryChanges::new(
&bulk_edit_project.categories,
&bulk_edit_project.add_categories,
&bulk_edit_project.remove_categories,
),
CategoryChanges {
categories: &bulk_edit_project.categories,
add_categories: &bulk_edit_project.add_categories,
remove_categories: &bulk_edit_project.remove_categories,
},
3,
false,
&mut transaction,
@@ -1256,11 +1259,12 @@ pub async fn projects_edit(
&categories,
&project.additional_categories,
project.inner.id as db_ids::ProjectId,
CategoryChanges::new(
&bulk_edit_project.additional_categories,
&bulk_edit_project.add_additional_categories,
&bulk_edit_project.remove_additional_categories,
),
CategoryChanges {
categories: &bulk_edit_project.additional_categories,
add_categories: &bulk_edit_project.add_additional_categories,
remove_categories: &bulk_edit_project
.remove_additional_categories,
},
256,
true,
&mut transaction,
@@ -1383,11 +1387,11 @@ pub async fn bulk_edit_project_categories(
))
})?
.id;
mod_categories.push(ModCategory::new(
mod_categories.push(ModCategory {
project_id,
category_id,
is_additional,
));
});
}
ModCategory::insert_many(mod_categories, &mut *transaction).await?;
}

View File

@@ -1,8 +1,6 @@
use std::{collections::HashMap, sync::Arc};
use actix_web::{HttpRequest, HttpResponse, web};
use lazy_static::lazy_static;
use regex::Regex;
use serde::{Deserialize, Serialize};
use sqlx::PgPool;
use validator::Validate;
@@ -358,13 +356,9 @@ pub async fn orgs_list(
}
}
lazy_static! {
static ref RE_URL_SAFE: Regex = Regex::new(r"^[a-zA-Z0-9_-]*$").unwrap();
}
#[derive(Serialize, Deserialize, Validate)]
pub struct EditUser {
#[validate(length(min = 1, max = 39), regex(path = *RE_URL_SAFE))]
#[validate(length(min = 1, max = 39), regex(path = *crate::util::validate::RE_URL_SAFE))]
pub username: Option<String>,
#[serde(
default,

View File

@@ -287,10 +287,10 @@ pub async fn version_edit_helper(
ApiError::Validation(validation_errors_to_string(err, None))
})?;
let version_id = info.0;
let id = version_id.into();
let version_id = info.0.into();
let result = database::models::Version::get(id, &**pool, &redis).await?;
let result =
database::models::Version::get(version_id, &**pool, &redis).await?;
if let Some(version_item) = result {
let team_member =
@@ -345,7 +345,7 @@ pub async fn version_edit_helper(
WHERE (id = $2)
",
name.trim(),
id as database::models::ids::VersionId,
version_id as database::models::ids::VersionId,
)
.execute(&mut *transaction)
.await?;
@@ -359,7 +359,7 @@ pub async fn version_edit_helper(
WHERE (id = $2)
",
number,
id as database::models::ids::VersionId,
version_id as database::models::ids::VersionId,
)
.execute(&mut *transaction)
.await?;
@@ -373,7 +373,7 @@ pub async fn version_edit_helper(
WHERE (id = $2)
",
version_type.as_str(),
id as database::models::ids::VersionId,
version_id as database::models::ids::VersionId,
)
.execute(&mut *transaction)
.await?;
@@ -384,7 +384,7 @@ pub async fn version_edit_helper(
"
DELETE FROM dependencies WHERE dependent_id = $1
",
id as database::models::ids::VersionId,
version_id as database::models::ids::VersionId,
)
.execute(&mut *transaction)
.await?;
@@ -448,7 +448,7 @@ pub async fn version_edit_helper(
WHERE version_id = $1
AND field_id = ANY($2)
",
id as database::models::ids::VersionId,
version_id as database::models::ids::VersionId,
&loader_field_ids
)
.execute(&mut *transaction)
@@ -476,7 +476,7 @@ pub async fn version_edit_helper(
.remove(&loader_field.id)
.unwrap_or_default();
let vf: VersionField = VersionField::check_parse(
version_id.into(),
version_id,
loader_field.clone(),
vf_value.clone(),
enum_variants,
@@ -493,7 +493,7 @@ pub async fn version_edit_helper(
"
DELETE FROM loaders_versions WHERE version_id = $1
",
id as database::models::ids::VersionId,
version_id as database::models::ids::VersionId,
)
.execute(&mut *transaction)
.await?;
@@ -513,7 +513,10 @@ pub async fn version_edit_helper(
.to_string(),
)
})?;
loader_versions.push(LoaderVersion::new(loader_id, id));
loader_versions.push(LoaderVersion {
loader_id,
version_id,
});
}
LoaderVersion::insert_many(loader_versions, &mut transaction)
.await?;
@@ -535,7 +538,7 @@ pub async fn version_edit_helper(
WHERE (id = $2)
",
featured,
id as database::models::ids::VersionId,
version_id as database::models::ids::VersionId,
)
.execute(&mut *transaction)
.await?;
@@ -549,7 +552,7 @@ pub async fn version_edit_helper(
WHERE (id = $2)
",
body,
id as database::models::ids::VersionId,
version_id as database::models::ids::VersionId,
)
.execute(&mut *transaction)
.await?;
@@ -569,7 +572,7 @@ pub async fn version_edit_helper(
WHERE (id = $2)
",
*downloads as i32,
id as database::models::ids::VersionId,
version_id as database::models::ids::VersionId,
)
.execute(&mut *transaction)
.await?;
@@ -604,7 +607,7 @@ pub async fn version_edit_helper(
WHERE (id = $2)
",
status.as_str(),
id as database::models::ids::VersionId,
version_id as database::models::ids::VersionId,
)
.execute(&mut *transaction)
.await?;
@@ -652,7 +655,7 @@ pub async fn version_edit_helper(
WHERE (id = $2)
",
ordering.to_owned() as Option<i32>,
id as database::models::ids::VersionId,
version_id as database::models::ids::VersionId,
)
.execute(&mut *transaction)
.await?;

View File

@@ -1,14 +1,13 @@
use std::sync::LazyLock;
use itertools::Itertools;
use lazy_static::lazy_static;
use regex::Regex;
use validator::{ValidationErrors, ValidationErrorsKind};
use crate::models::pats::Scopes;
lazy_static! {
pub static ref RE_URL_SAFE: Regex =
Regex::new(r#"^[a-zA-Z0-9!@$()`.+,_"-]*$"#).unwrap();
}
pub static RE_URL_SAFE: LazyLock<Regex> =
LazyLock::new(|| Regex::new(r"^[a-zA-Z0-9_-]*$").unwrap());
//TODO: In order to ensure readability, only the first error is printed, this may need to be expanded on in the future!
pub fn validation_errors_to_string(