Compare commits

..

1 Commits

Author SHA1 Message Date
Alejandro González
bc17b4b526 feat(labrinth): allow editing loader fields in bulk in v3 project PATCH 2025-08-08 02:05:57 +02:00
3 changed files with 43 additions and 17 deletions

View File

@@ -62,18 +62,18 @@ During development, you might notice that changes made directly to entities in t
#### Basic configuration
`DEBUG`: Whether debugging tools should be enabled
`RUST_LOG`: Specifies what information to log, from rust's [`env-logger`](https://github.com/env-logger-rs/env_logger); a reasonable default is `info,sqlx::query=warn`
`SITE_URL`: The main URL to be used for CORS
`CDN_URL`: The publicly accessible base URL for files uploaded to the CDN
`MODERATION_DISCORD_WEBHOOK`: The URL for a Discord webhook where projects pending approval will be sent
`CLOUDFLARE_INTEGRATION`: Whether Labrinth should integrate with Cloudflare's spam protection
`DATABASE_URL`: The URL for the PostgreSQL database, including its username, password, host, port, and database name
`DATABASE_MIN_CONNECTIONS`: The minimum number of concurrent connections allowed to the database at the same time
`DATABASE_MAX_CONNECTIONS`: The maximum number of concurrent connections allowed to the database at the same time
`MEILISEARCH_ADDR`: The URL for the MeiliSearch instance used for search
`MEILISEARCH_KEY`: The name that MeiliSearch is given
`BIND_ADDR`: The bind address for the server. Supports both IPv4 and IPv6
`DEBUG`: Whether debugging tools should be enabled
`RUST_LOG`: Specifies what information to log, from rust's [`env-logger`](https://github.com/env-logger-rs/env_logger); a reasonable default is `info,sqlx::query=warn`
`SITE_URL`: The main URL to be used for CORS
`CDN_URL`: The publicly accessible base URL for files uploaded to the CDN
`MODERATION_DISCORD_WEBHOOK`: The URL for a Discord webhook where projects pending approval will be sent
`CLOUDFLARE_INTEGRATION`: Whether labrinth should integrate with Cloudflare's spam protection
`DATABASE_URL`: The URL for the PostgreSQL database
`DATABASE_MIN_CONNECTIONS`: The minimum number of concurrent connections allowed to the database at the same time
`DATABASE_MAX_CONNECTIONS`: The maximum number of concurrent connections allowed to the database at the same time
`MEILISEARCH_ADDR`: The URL for the MeiliSearch instance used for search
`MEILISEARCH_KEY`: The name that MeiliSearch is given
`BIND_ADDR`: The bind address for the server. Supports both IPv4 and IPv6
`MOCK_FILE_PATH`: The path used to store uploaded files; this has no default value and will panic if unspecified
`SMTP_USERNAME`: The username used to authenticate with the SMTP server
`SMTP_PASSWORD`: The password associated with the `SMTP_USERNAME` for SMTP authentication
@@ -90,7 +90,7 @@ The S3 configuration options are fairly self-explanatory in name, so here's simp
#### Search, OAuth, and miscellaneous options
`LOCAL_INDEX_INTERVAL`: The interval, in seconds, at which the local database is reindexed for searching. Defaults to `3600` seconds (1 hour).
`LOCAL_INDEX_INTERVAL`: The interval, in seconds, at which the local database is reindexed for searching. Defaults to `3600` seconds (1 hour).
`VERSION_INDEX_INTERVAL`: The interval, in seconds, at which versions are reindexed for searching. Defaults to `1800` seconds (30 minutes).
The OAuth configuration options are fairly self-explanatory. For help setting up authentication, please contact us on [Discord].
@@ -99,8 +99,8 @@ The OAuth configuration options are fairly self-explanatory. For help setting up
#### Command line options
`--skip-first-index`: Skips indexing the local database on startup. This is useful to prevent doing unnecessary work when frequently restarting.
`--reconfigure-indices`: Resets the MeiliSearch settings for the search indices and exits.
`--skip-first-index`: Skips indexing the local database on startup. This is useful to prevent doing unnecessary work when frequently restarting.
`--reconfigure-indices`: Resets the MeiliSearch settings for the search indices and exits.
`--reset-indices`: Resets the MeiliSearch indices and exits; this clears all previously indexed mods.
</details>
@@ -114,7 +114,7 @@ If you're prepared to contribute by submitting a pull request, ensure you have m
- `cargo check` has been run.
- `cargo sqlx prepare` has been run.
> Note: If you encounter issues with `sqlx` saying 'no queries found' after running `cargo sqlx prepare`, you may need to ensure the installed version of `sqlx-cli` matches the current version of `sqlx` used [in Labrinth](https://github.com/modrinth/labrinth/blob/master/Cargo.toml).
> Note: If you encounter issues with `sqlx` saying 'no queries found' after running `cargo sqlx prepare`, you may need to ensure the installed version of `sqlx-cli` matches the current version of `sqlx` used [in labrinth](https://github.com/modrinth/labrinth/blob/master/Cargo.toml).
[Discord]: https://discord.modrinth.com
[GitHub]: https://github.com/modrinth

View File

@@ -512,6 +512,7 @@ pub async fn project_edit(
moderation_message_body: v2_new_project.moderation_message_body,
monetization_status: v2_new_project.monetization_status,
side_types_migration_review_status: None, // Not to be exposed in v2
loader_fields: HashMap::new(), // Loader fields are not a thing in v2
};
// This returns 204 or failure so we don't need to do anything with it

View File

@@ -11,7 +11,7 @@ use crate::database::redis::RedisPool;
use crate::database::{self, models as db_models};
use crate::file_hosting::{FileHost, FileHostPublicity};
use crate::models;
use crate::models::ids::ProjectId;
use crate::models::ids::{ProjectId, VersionId};
use crate::models::images::ImageContext;
use crate::models::notifications::NotificationBody;
use crate::models::pats::Scopes;
@@ -250,6 +250,8 @@ pub struct EditProject {
pub monetization_status: Option<MonetizationStatus>,
pub side_types_migration_review_status:
Option<SideTypesMigrationReviewStatus>,
#[serde(flatten)]
pub loader_fields: HashMap<String, serde_json::Value>,
}
#[allow(clippy::too_many_arguments)]
@@ -870,6 +872,29 @@ pub async fn project_edit(
.await?;
}
if !new_project.loader_fields.is_empty() {
for version in db_models::DBVersion::get_many(
&project_item.versions,
&**pool,
&redis,
)
.await?
{
super::versions::version_edit_helper(
req.clone(),
(VersionId::from(version.inner.id),),
pool.clone(),
redis.clone(),
super::versions::EditVersion {
fields: new_project.loader_fields.clone(),
..Default::default()
},
session_queue.clone(),
)
.await?;
}
}
// check new description and body for links to associated images
// if they no longer exist in the description or body, delete them
let checkable_strings: Vec<&str> =