Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
CREATE TABLE project_disclosures (
project_id BIGINT NOT NULL REFERENCES mods(id) ON DELETE CASCADE,
type TEXT NOT NULL,
metadata JSONB NOT NULL,
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_by BIGINT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
set_by_moderator BOOLEAN NOT NULL,
PRIMARY KEY (project_id, type)
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
INSERT INTO project_disclosures (project_id, type, metadata, updated_by, set_by_moderator)
SELECT id, 'archived', '{"note": null}'::jsonb, 0, FALSE
FROM mods
WHERE status = 'archived'
ON CONFLICT (project_id, type) DO NOTHING;

UPDATE mods
SET status = 'approved'
WHERE status = 'archived';
2 changes: 2 additions & 0 deletions apps/labrinth/src/database/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub mod payout_item;
pub mod payouts_values_notifications;
pub mod product_item;
pub mod products_tax_identifier_item;
pub mod project_disclosure_item;
pub mod project_item;
pub mod report_item;
pub mod session_item;
Expand All @@ -53,6 +54,7 @@ pub use image_item::DBImage;
pub use oauth_client_item::DBOAuthClient;
pub use organization_item::DBOrganization;
pub use passkey_item::DBPasskey;
pub use project_disclosure_item::DBProjectDisclosure;
pub use project_item::DBProject;
pub use team_item::DBTeam;
pub use team_item::DBTeamMember;
Expand Down
151 changes: 151 additions & 0 deletions apps/labrinth/src/database/models/project_disclosure_item.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
use std::collections::HashSet;

use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};

use crate::{
database::models::{DBProjectId, DBUserId, DatabaseError},
models::v3::disclosures::{ProjectDisclosure, ProjectDisclosureType},
};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DBProjectDisclosure {
pub project_id: DBProjectId,
pub disclosure: ProjectDisclosure,
pub updated_at: DateTime<Utc>,
pub updated_by: DBUserId,
pub set_by_moderator: bool,
}

impl DBProjectDisclosure {
pub async fn upsert(
&self,
exec: impl crate::database::Executor<'_, Database = sqlx::Postgres>,
) -> Result<(), DatabaseError> {
let (disclosure_type, metadata) =
self.disclosure.to_parts().map_err(|e| {
DatabaseError::Internal(eyre::Report::new(e).wrap_err(
"failed to serialize project disclosure metadata",
))
})?;

sqlx::query!(
r#"
INSERT INTO project_disclosures (project_id, type, metadata, updated_by, set_by_moderator)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (project_id, type) DO UPDATE SET
metadata = $3,
updated_at = now(),
updated_by = $4,
set_by_moderator = $5
"#,
self.project_id as DBProjectId,
disclosure_type,
metadata,
self.updated_by as DBUserId,
self.set_by_moderator,
)
.execute(exec)
.await?;

Ok(())
}

pub async fn get_many_for_project(
project_id: DBProjectId,
exec: impl crate::database::Executor<'_, Database = sqlx::Postgres>,
) -> Result<Vec<DBProjectDisclosure>, DatabaseError> {
let rows = sqlx::query!(
r#"
SELECT project_id, type AS "disclosure_type!", metadata, updated_at, updated_by, set_by_moderator
FROM project_disclosures
WHERE project_id = $1
ORDER BY updated_at DESC
"#,
project_id as DBProjectId,
)
.fetch_all(exec)
.await?;

rows.into_iter()
.map(|row| {
Ok(DBProjectDisclosure {
project_id: DBProjectId(row.project_id),
disclosure: ProjectDisclosure::from_parts(
&row.disclosure_type,
row.metadata,
)
.map_err(|e| {
DatabaseError::Internal(eyre::Report::new(e).wrap_err(
"failed to deserialize project disclosure metadata",
))
})?,
updated_at: row.updated_at,
updated_by: DBUserId(row.updated_by),
set_by_moderator: row.set_by_moderator,
})
})
.collect()
}

/// Returns the subset of `project_ids` that carry a disclosure of the given type.
pub async fn projects_with_type(
disclosure_type: ProjectDisclosureType,
project_ids: &[DBProjectId],
exec: impl crate::database::Executor<'_, Database = sqlx::Postgres>,
) -> Result<HashSet<DBProjectId>, DatabaseError> {
let ids = project_ids.iter().map(|id| id.0).collect::<Vec<_>>();
let rows = sqlx::query_scalar!(
r#"
SELECT project_id
FROM project_disclosures
WHERE type = $1 AND project_id = ANY($2)
"#,
<&'static str>::from(disclosure_type),
&ids,
)
.fetch_all(exec)
.await?;

Ok(rows.into_iter().map(DBProjectId).collect())
}

pub async fn any_set_by_moderator(
project_id: DBProjectId,
types: &[String],
exec: impl crate::database::Executor<'_, Database = sqlx::Postgres>,
) -> Result<bool, DatabaseError> {
let existing = sqlx::query_scalar!(
r#"
SELECT 1 FROM project_disclosures
WHERE project_id = $1 AND type = ANY($2) AND set_by_moderator
LIMIT 1
"#,
project_id as DBProjectId,
types,
)
.fetch_optional(exec)
.await?;

Ok(existing.is_some())
}

pub async fn remove(
project_id: DBProjectId,
disclosure_type: ProjectDisclosureType,
exec: impl crate::database::Executor<'_, Database = sqlx::Postgres>,
) -> Result<bool, DatabaseError> {
let result = sqlx::query!(
r#"
DELETE FROM project_disclosures
WHERE project_id = $1 AND type = $2
"#,
project_id as DBProjectId,
<&'static str>::from(disclosure_type),
)
.execute(exec)
.await?;

Ok(result.rows_affected() > 0)
}
}
1 change: 1 addition & 0 deletions apps/labrinth/src/models/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod v3;
pub use v3::analytics;
pub use v3::billing;
pub use v3::collections;
pub use v3::disclosures;
pub use v3::ids;
pub use v3::images;
pub use v3::moderation_notes;
Expand Down
Loading
Loading