Skip to content

Commit

Permalink
Add community reports (only the database part) (#4996)
Browse files Browse the repository at this point in the history
* database stuff, not including tests

* change migration date

* fix community_report_view

* update stuff related to report_combined

* add db_schema/src/impls/community_report.rs

* add report counts to community_aggregates

* fix community_report columns and update report_combined_view::tests::test_combined

* add column for original sidebar; use None instead of clone; add report_combined_view::tests::test_community_reports

* use ts(optional) in CommunityReportView

* remove CommunityReportView::read
  • Loading branch information
dullbananas authored Jan 13, 2025
1 parent 11e0513 commit 4d17eef
Show file tree
Hide file tree
Showing 12 changed files with 443 additions and 20 deletions.
21 changes: 21 additions & 0 deletions crates/db_schema/replaceable_schema/triggers.sql
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,25 @@ END;

$$);

CALL r.create_triggers ('community_report', $$
BEGIN
UPDATE
community_aggregates AS a
SET
report_count = a.report_count + diff.report_count, unresolved_report_count = a.unresolved_report_count + diff.unresolved_report_count
FROM (
SELECT
(community_report).community_id, coalesce(sum(count_diff), 0) AS report_count, coalesce(sum(count_diff) FILTER (WHERE NOT (community_report).resolved), 0) AS unresolved_report_count
FROM select_old_and_new_rows AS old_and_new_rows GROUP BY (community_report).community_id) AS diff
WHERE (diff.report_count, diff.unresolved_report_count) != (0, 0)
AND a.community_id = diff.community_id;

RETURN NULL;

END;

$$);

-- These triggers create and update rows in each aggregates table to match its associated table's rows.
-- Deleting rows and updating IDs are already handled by `CASCADE` in foreign key constraints.
CREATE FUNCTION r.comment_aggregates_from_comment ()
Expand Down Expand Up @@ -685,6 +704,8 @@ CALL r.create_report_combined_trigger ('comment_report');

CALL r.create_report_combined_trigger ('private_message_report');

CALL r.create_report_combined_trigger ('community_report');

-- person_content (comment, post)
CREATE PROCEDURE r.create_person_content_combined_trigger (table_name text)
LANGUAGE plpgsql
Expand Down
2 changes: 2 additions & 0 deletions crates/db_schema/src/aggregates/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ pub struct CommunityAggregates {
#[serde(skip)]
pub hot_rank: f64,
pub subscribers_local: i64,
pub report_count: i16,
pub unresolved_report_count: i16,
}

#[derive(PartialEq, Eq, Debug, Serialize, Deserialize, Clone, Default)]
Expand Down
97 changes: 97 additions & 0 deletions crates/db_schema/src/impls/community_report.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use crate::{
newtypes::{CommunityId, CommunityReportId, PersonId},
schema::community_report::{
community_id,
dsl::{community_report, resolved, resolver_id, updated},
},
source::community_report::{CommunityReport, CommunityReportForm},
traits::Reportable,
utils::{get_conn, DbPool},
};
use chrono::Utc;
use diesel::{
dsl::{insert_into, update},
result::Error,
ExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl;

#[async_trait]
impl Reportable for CommunityReport {
type Form = CommunityReportForm;
type IdType = CommunityReportId;
type ObjectIdType = CommunityId;
/// creates a community report and returns it
///
/// * `conn` - the postgres connection
/// * `community_report_form` - the filled CommunityReportForm to insert
async fn report(
pool: &mut DbPool<'_>,
community_report_form: &CommunityReportForm,
) -> Result<Self, Error> {
let conn = &mut get_conn(pool).await?;
insert_into(community_report)
.values(community_report_form)
.get_result::<Self>(conn)
.await
}

/// resolve a community report
///
/// * `conn` - the postgres connection
/// * `report_id` - the id of the report to resolve
/// * `by_resolver_id` - the id of the user resolving the report
async fn resolve(
pool: &mut DbPool<'_>,
report_id_: Self::IdType,
by_resolver_id: PersonId,
) -> Result<usize, Error> {
let conn = &mut get_conn(pool).await?;
update(community_report.find(report_id_))
.set((
resolved.eq(true),
resolver_id.eq(by_resolver_id),
updated.eq(Utc::now()),
))
.execute(conn)
.await
}

async fn resolve_all_for_object(
pool: &mut DbPool<'_>,
community_id_: CommunityId,
by_resolver_id: PersonId,
) -> Result<usize, Error> {
let conn = &mut get_conn(pool).await?;
update(community_report.filter(community_id.eq(community_id_)))
.set((
resolved.eq(true),
resolver_id.eq(by_resolver_id),
updated.eq(Utc::now()),
))
.execute(conn)
.await
}

/// unresolve a community report
///
/// * `conn` - the postgres connection
/// * `report_id` - the id of the report to unresolve
/// * `by_resolver_id` - the id of the user unresolving the report
async fn unresolve(
pool: &mut DbPool<'_>,
report_id_: Self::IdType,
by_resolver_id: PersonId,
) -> Result<usize, Error> {
let conn = &mut get_conn(pool).await?;
update(community_report.find(report_id_))
.set((
resolved.eq(false),
resolver_id.eq(by_resolver_id),
updated.eq(Utc::now()),
))
.execute(conn)
.await
}
}
1 change: 1 addition & 0 deletions crates/db_schema/src/impls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod comment_reply;
pub mod comment_report;
pub mod community;
pub mod community_block;
pub mod community_report;
pub mod custom_emoji;
pub mod email_verification;
pub mod federation_allowlist;
Expand Down
6 changes: 6 additions & 0 deletions crates/db_schema/src/newtypes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ pub struct PersonMentionId(i32);
/// The comment report id.
pub struct CommentReportId(pub i32);

#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
#[cfg_attr(feature = "full", derive(DieselNewType, TS))]
#[cfg_attr(feature = "full", ts(export))]
/// The community report id.
pub struct CommunityReportId(pub i32);

#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
#[cfg_attr(feature = "full", derive(DieselNewType, TS))]
#[cfg_attr(feature = "full", ts(export))]
Expand Down
25 changes: 25 additions & 0 deletions crates/db_schema/src/schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,8 @@ diesel::table! {
users_active_half_year -> Int8,
hot_rank -> Float8,
subscribers_local -> Int8,
report_count -> Int2,
unresolved_report_count -> Int2,
}
}

Expand All @@ -263,6 +265,25 @@ diesel::table! {
}
}

diesel::table! {
community_report (id) {
id -> Int4,
creator_id -> Int4,
community_id -> Int4,
original_community_name -> Text,
original_community_title -> Text,
original_community_description -> Nullable<Text>,
original_community_sidebar -> Nullable<Text>,
original_community_icon -> Nullable<Text>,
original_community_banner -> Nullable<Text>,
reason -> Text,
resolved -> Bool,
resolver_id -> Nullable<Int4>,
published -> Timestamptz,
updated -> Nullable<Timestamptz>,
}
}

diesel::table! {
custom_emoji (id) {
id -> Int4,
Expand Down Expand Up @@ -922,6 +943,7 @@ diesel::table! {
post_report_id -> Nullable<Int4>,
comment_report_id -> Nullable<Int4>,
private_message_report_id -> Nullable<Int4>,
community_report_id -> Nullable<Int4>,
}
}

Expand Down Expand Up @@ -1040,6 +1062,7 @@ diesel::joinable!(community_actions -> community (community_id));
diesel::joinable!(community_aggregates -> community (community_id));
diesel::joinable!(community_language -> community (community_id));
diesel::joinable!(community_language -> language (language_id));
diesel::joinable!(community_report -> community (community_id));
diesel::joinable!(custom_emoji_keyword -> custom_emoji (custom_emoji_id));
diesel::joinable!(email_verification -> local_user (local_user_id));
diesel::joinable!(federation_allowlist -> instance (instance_id));
Expand Down Expand Up @@ -1099,6 +1122,7 @@ diesel::joinable!(private_message_report -> private_message (private_message_id)
diesel::joinable!(registration_application -> local_user (local_user_id));
diesel::joinable!(registration_application -> person (admin_id));
diesel::joinable!(report_combined -> comment_report (comment_report_id));
diesel::joinable!(report_combined -> community_report (community_report_id));
diesel::joinable!(report_combined -> post_report (post_report_id));
diesel::joinable!(report_combined -> private_message_report (private_message_report_id));
diesel::joinable!(site -> instance (instance_id));
Expand All @@ -1124,6 +1148,7 @@ diesel::allow_tables_to_appear_in_same_query!(
community_actions,
community_aggregates,
community_language,
community_report,
custom_emoji,
custom_emoji_keyword,
email_verification,
Expand Down
60 changes: 60 additions & 0 deletions crates/db_schema/src/source/community_report.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use crate::newtypes::{CommunityId, CommunityReportId, DbUrl, PersonId};
#[cfg(feature = "full")]
use crate::schema::community_report;
use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
#[cfg(feature = "full")]
use ts_rs::TS;

#[skip_serializing_none]
#[derive(PartialEq, Eq, Serialize, Deserialize, Debug, Clone)]
#[cfg_attr(
feature = "full",
derive(Queryable, Selectable, Associations, Identifiable, TS)
)]
#[cfg_attr(
feature = "full",
diesel(belongs_to(crate::source::community::Community))
)]
#[cfg_attr(feature = "full", diesel(table_name = community_report))]
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
#[cfg_attr(feature = "full", ts(export))]
/// A comment report.
pub struct CommunityReport {
pub id: CommunityReportId,
pub creator_id: PersonId,
pub community_id: CommunityId,
pub original_community_name: String,
pub original_community_title: String,
#[cfg_attr(feature = "full", ts(optional))]
pub original_community_description: Option<String>,
#[cfg_attr(feature = "full", ts(optional))]
pub original_community_sidebar: Option<String>,
#[cfg_attr(feature = "full", ts(optional))]
pub original_community_icon: Option<String>,
#[cfg_attr(feature = "full", ts(optional))]
pub original_community_banner: Option<String>,
pub reason: String,
pub resolved: bool,
#[cfg_attr(feature = "full", ts(optional))]
pub resolver_id: Option<PersonId>,
pub published: DateTime<Utc>,
#[cfg_attr(feature = "full", ts(optional))]
pub updated: Option<DateTime<Utc>>,
}

#[derive(Clone)]
#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))]
#[cfg_attr(feature = "full", diesel(table_name = community_report))]
pub struct CommunityReportForm {
pub creator_id: PersonId,
pub community_id: CommunityId,
pub original_community_name: String,
pub original_community_title: String,
pub original_community_description: Option<String>,
pub original_community_sidebar: Option<String>,
pub original_community_icon: Option<DbUrl>,
pub original_community_banner: Option<DbUrl>,
pub reason: String,
}
1 change: 1 addition & 0 deletions crates/db_schema/src/source/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub mod comment_reply;
pub mod comment_report;
pub mod community;
pub mod community_block;
pub mod community_report;
pub mod custom_emoji;
pub mod custom_emoji_keyword;
pub mod email_verification;
Expand Down
Loading

0 comments on commit 4d17eef

Please sign in to comment.