diff --git a/apps/labrinth/migrations/20260828065709_reports-organization.sql b/apps/labrinth/migrations/20260828065709_reports-organization.sql new file mode 100644 index 0000000000..1e271b2aec --- /dev/null +++ b/apps/labrinth/migrations/20260828065709_reports-organization.sql @@ -0,0 +1,2 @@ +ALTER TABLE reports + ADD COLUMN organization_id bigint diff --git a/apps/labrinth/src/database/models/report_item.rs b/apps/labrinth/src/database/models/report_item.rs index cf7edea740..6e748d89f2 100644 --- a/apps/labrinth/src/database/models/report_item.rs +++ b/apps/labrinth/src/database/models/report_item.rs @@ -9,6 +9,7 @@ pub struct DBReport { pub project_id: Option, pub version_id: Option, pub user_id: Option, + pub organization_id: Option, pub shared_instance_id: Option, pub shared_instance_version_id: Option, pub body: String, @@ -23,6 +24,7 @@ pub struct ReportQueryResult { pub project_id: Option, pub version_id: Option, pub user_id: Option, + pub organization_id: Option, pub shared_instance_id: Option, pub shared_instance_version_id: Option, pub body: String, @@ -40,12 +42,12 @@ impl DBReport { sqlx::query!( " INSERT INTO reports ( - id, report_type_id, mod_id, version_id, user_id, + id, report_type_id, mod_id, version_id, user_id, organization_id, shared_instance_id, shared_instance_version_id, body, reporter ) VALUES ( $1, $2, $3, $4, $5, - $6, $7, $8, $9 + $6, $7, $8, $9, $10 ) ", self.id as DBReportId, @@ -53,6 +55,7 @@ impl DBReport { self.project_id.map(|x| x.0 as i64), self.version_id.map(|x| x.0 as i64), self.user_id.map(|x| x.0 as i64), + self.organization_id.map(|x| x.0 as i64), self.shared_instance_id.map(|x| x.0 as i64), self.shared_instance_version_id, self.body, @@ -89,7 +92,7 @@ impl DBReport { report_ids.iter().map(|x| x.0).collect(); let reports = sqlx::query!( " - SELECT r.id, rt.name, r.mod_id, r.version_id, r.user_id, r.shared_instance_id, r.shared_instance_version_id, r.body, r.reporter, r.created, t.id thread_id, r.closed + SELECT r.id, rt.name, r.mod_id, r.version_id, r.user_id, r.organization_id, r.shared_instance_id, r.shared_instance_version_id, r.body, r.reporter, r.created, t.id thread_id, r.closed FROM reports r INNER JOIN report_types rt ON rt.id = r.report_type_id INNER JOIN threads t ON t.report_id = r.id @@ -105,6 +108,7 @@ impl DBReport { project_id: x.mod_id.map(DBProjectId), version_id: x.version_id.map(DBVersionId), user_id: x.user_id.map(DBUserId), + organization_id: x.organization_id.map(DBOrganizationId), shared_instance_id: x.shared_instance_id.map(SharedInstanceId), shared_instance_version_id: x.shared_instance_version_id, body: x.body, diff --git a/apps/labrinth/src/models/v3/reports.rs b/apps/labrinth/src/models/v3/reports.rs index 34beeb3f96..41b2fcfb8f 100644 --- a/apps/labrinth/src/models/v3/reports.rs +++ b/apps/labrinth/src/models/v3/reports.rs @@ -1,5 +1,7 @@ use crate::database::models::report_item::ReportQueryResult as DBReport; -use crate::models::ids::{ProjectId, ReportId, ThreadId, VersionId}; +use crate::models::ids::{ + OrganizationId, ProjectId, ReportId, ThreadId, VersionId, +}; use ariadne::ids::UserId; use ariadne::ids::base62_impl::to_base62; use chrono::{DateTime, Utc}; @@ -26,6 +28,7 @@ pub enum ItemType { Project, Version, User, + Organization, SharedInstance, Unknown, } @@ -36,6 +39,7 @@ impl ItemType { ItemType::Project => "project", ItemType::Version => "version", ItemType::User => "user", + ItemType::Organization => "organization", ItemType::SharedInstance => "shared-instance", ItemType::Unknown => "unknown", } @@ -57,6 +61,9 @@ impl From for Report { } else if let Some(user_id) = x.user_id { item_id = UserId::from(user_id).to_string(); item_type = ItemType::User; + } else if let Some(organization_id) = x.organization_id { + item_id = OrganizationId::from(organization_id).to_string(); + item_type = ItemType::Organization; } else if let Some(shared_instance_id) = x.shared_instance_id { item_id = to_base62(shared_instance_id.0 as u64); item_type = ItemType::SharedInstance; diff --git a/apps/labrinth/src/routes/v3/reports.rs b/apps/labrinth/src/routes/v3/reports.rs index a3bba51279..f686d463e7 100644 --- a/apps/labrinth/src/routes/v3/reports.rs +++ b/apps/labrinth/src/routes/v3/reports.rs @@ -8,7 +8,7 @@ use crate::database::models::thread_item::{ ThreadBuilder, ThreadMessageBuilder, }; use crate::env::ENV; -use crate::models::ids::ImageId; +use crate::models::ids::{ImageId, OrganizationId}; use crate::models::ids::{ProjectId, VersionId}; use crate::models::images::{Image, ImageContext}; use crate::models::notifications::NotificationBody; @@ -113,6 +113,7 @@ pub async fn report_create( project_id: None, version_id: None, user_id: None, + organization_id: None, shared_instance_id: None, shared_instance_version_id: None, body: new_report.body.clone(), @@ -191,6 +192,29 @@ pub async fn report_create( report.user_id = Some(user_id.into()) } + ItemType::Organization => { + let organization_id = OrganizationId( + parse_base62(new_report.item_id.as_str()) + .wrap_request_err("parsing reported organization ID")?, + ); + + let result = sqlx::query!( + "SELECT EXISTS(SELECT 1 FROM organizations WHERE id = $1)", + organization_id.0 as i64 + ) + .fetch_one(&mut transaction) + .await + .wrap_internal_err("querying database for `report_create`")?; + + if !result.exists.unwrap_or(false) { + return Err(ApiError::Request(eyre::eyre!(format!( + "Organization could not be found: {}", + new_report.item_id + )))); + } + + report.organization_id = Some(organization_id.into()) + } ItemType::SharedInstance => { // parsing let (instance_part, version_part) = new_report