mirror of
https://github.com/LemmyNet/lemmy.git
synced 2025-02-09 02:24:46 +00:00
Adding post_id and type_ filters to combined reports. (#5348)
* Adding post_id and type_ filters to combined reports. - Added tests for these also. - Some additional cleanup of the joins in reports_combined. - Fixes #5265 * Adding period.
This commit is contained in:
parent
8ee81a3967
commit
012e8c3085
5 changed files with 116 additions and 55 deletions
|
@ -15,9 +15,6 @@ pub async fn list_reports(
|
||||||
context: Data<LemmyContext>,
|
context: Data<LemmyContext>,
|
||||||
local_user_view: LocalUserView,
|
local_user_view: LocalUserView,
|
||||||
) -> LemmyResult<Json<ListReportsResponse>> {
|
) -> LemmyResult<Json<ListReportsResponse>> {
|
||||||
let community_id = data.community_id;
|
|
||||||
let unresolved_only = data.unresolved_only;
|
|
||||||
|
|
||||||
check_community_mod_of_any_or_admin_action(&local_user_view, &mut context.pool()).await?;
|
check_community_mod_of_any_or_admin_action(&local_user_view, &mut context.pool()).await?;
|
||||||
|
|
||||||
// parse pagination token
|
// parse pagination token
|
||||||
|
@ -29,8 +26,10 @@ pub async fn list_reports(
|
||||||
let page_back = data.page_back;
|
let page_back = data.page_back;
|
||||||
|
|
||||||
let reports = ReportCombinedQuery {
|
let reports = ReportCombinedQuery {
|
||||||
community_id,
|
community_id: data.community_id,
|
||||||
unresolved_only,
|
post_id: data.post_id,
|
||||||
|
type_: data.type_,
|
||||||
|
unresolved_only: data.unresolved_only,
|
||||||
page_after,
|
page_after,
|
||||||
page_back,
|
page_back,
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ use std::{cmp::min, time::Duration};
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
#[cfg_attr(feature = "full", derive(ts_rs::TS))]
|
#[cfg_attr(feature = "full", derive(ts_rs::TS))]
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
/// Saves settings for your user.
|
/// A response that completes successfully.
|
||||||
pub struct SuccessResponse {
|
pub struct SuccessResponse {
|
||||||
pub success: bool,
|
pub success: bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use lemmy_db_schema::newtypes::CommunityId;
|
use lemmy_db_schema::{
|
||||||
|
newtypes::{CommunityId, PostId},
|
||||||
|
ReportType,
|
||||||
|
};
|
||||||
use lemmy_db_views::structs::{ReportCombinedPaginationCursor, ReportCombinedView};
|
use lemmy_db_views::structs::{ReportCombinedPaginationCursor, ReportCombinedView};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_with::skip_serializing_none;
|
use serde_with::skip_serializing_none;
|
||||||
|
@ -14,6 +17,12 @@ pub struct ListReports {
|
||||||
/// Only shows the unresolved reports
|
/// Only shows the unresolved reports
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
pub unresolved_only: Option<bool>,
|
pub unresolved_only: Option<bool>,
|
||||||
|
/// Filter the type of report.
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub type_: Option<ReportType>,
|
||||||
|
/// Filter by the post id. Can return either comment or post reports.
|
||||||
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
|
pub post_id: Option<PostId>,
|
||||||
/// if no community is given, it returns reports for all communities moderated by the auth user
|
/// if no community is given, it returns reports for all communities moderated by the auth user
|
||||||
#[cfg_attr(feature = "full", ts(optional))]
|
#[cfg_attr(feature = "full", ts(optional))]
|
||||||
pub community_id: Option<CommunityId>,
|
pub community_id: Option<CommunityId>,
|
||||||
|
|
|
@ -229,13 +229,25 @@ pub enum InboxDataType {
|
||||||
#[derive(EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
#[cfg_attr(feature = "full", derive(TS))]
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
/// A list of possible types for the various modlog actions.
|
/// A list of possible types for a person's content.
|
||||||
pub enum PersonContentType {
|
pub enum PersonContentType {
|
||||||
All,
|
All,
|
||||||
Comments,
|
Comments,
|
||||||
Posts,
|
Posts,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// A list of possible types for reports.
|
||||||
|
pub enum ReportType {
|
||||||
|
All,
|
||||||
|
Posts,
|
||||||
|
Comments,
|
||||||
|
PrivateMessages,
|
||||||
|
Communities,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, Default, PartialEq, Eq, Hash,
|
EnumString, Display, Debug, Serialize, Deserialize, Clone, Copy, Default, PartialEq, Eq, Hash,
|
||||||
)]
|
)]
|
||||||
|
|
|
@ -22,7 +22,7 @@ use diesel_async::RunQueryDsl;
|
||||||
use i_love_jesus::PaginatedQueryBuilder;
|
use i_love_jesus::PaginatedQueryBuilder;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
aliases::{self, creator_community_actions},
|
aliases::{self, creator_community_actions},
|
||||||
newtypes::CommunityId,
|
newtypes::{CommunityId, PostId},
|
||||||
schema::{
|
schema::{
|
||||||
comment,
|
comment,
|
||||||
comment_actions,
|
comment_actions,
|
||||||
|
@ -49,6 +49,7 @@ use lemmy_db_schema::{
|
||||||
},
|
},
|
||||||
traits::InternalToCombinedView,
|
traits::InternalToCombinedView,
|
||||||
utils::{actions, actions_alias, functions::coalesce, get_conn, DbPool, ReverseTimestampKey},
|
utils::{actions, actions_alias, functions::coalesce, get_conn, DbPool, ReverseTimestampKey},
|
||||||
|
ReportType,
|
||||||
};
|
};
|
||||||
use lemmy_utils::error::LemmyResult;
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
|
||||||
|
@ -148,6 +149,8 @@ pub struct PaginationCursorData(ReportCombined);
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ReportCombinedQuery {
|
pub struct ReportCombinedQuery {
|
||||||
|
pub type_: Option<ReportType>,
|
||||||
|
pub post_id: Option<PostId>,
|
||||||
pub community_id: Option<CommunityId>,
|
pub community_id: Option<CommunityId>,
|
||||||
pub unresolved_only: Option<bool>,
|
pub unresolved_only: Option<bool>,
|
||||||
pub page_after: Option<PaginationCursorData>,
|
pub page_after: Option<PaginationCursorData>,
|
||||||
|
@ -167,6 +170,33 @@ impl ReportCombinedQuery {
|
||||||
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
|
||||||
|
let report_creator_join = post_report::creator_id
|
||||||
|
.eq(report_creator)
|
||||||
|
.or(comment_report::creator_id.eq(report_creator))
|
||||||
|
.or(private_message_report::creator_id.eq(report_creator))
|
||||||
|
.or(community_report::creator_id.eq(report_creator));
|
||||||
|
|
||||||
|
let item_creator_join = post::creator_id
|
||||||
|
.eq(item_creator)
|
||||||
|
.or(comment::creator_id.eq(item_creator))
|
||||||
|
.or(private_message::creator_id.eq(item_creator));
|
||||||
|
|
||||||
|
let resolver_join = private_message_report::resolver_id
|
||||||
|
.eq(resolver)
|
||||||
|
.or(post_report::resolver_id.eq(resolver))
|
||||||
|
.or(comment_report::resolver_id.eq(resolver))
|
||||||
|
.or(community_report::resolver_id.eq(resolver));
|
||||||
|
|
||||||
|
let post_join = post_report::post_id
|
||||||
|
.eq(post::id)
|
||||||
|
.or(comment::post_id.eq(post::id));
|
||||||
|
|
||||||
|
let community_join = community::table.on(
|
||||||
|
community_report::community_id
|
||||||
|
.eq(community::id)
|
||||||
|
.or(post::community_id.eq(community::id)),
|
||||||
|
);
|
||||||
|
|
||||||
// Notes: since the post_report_id and comment_report_id are optional columns,
|
// Notes: since the post_report_id and comment_report_id are optional columns,
|
||||||
// many joins must use an OR condition.
|
// many joins must use an OR condition.
|
||||||
// For example, the report creator must be the person table joined to either:
|
// For example, the report creator must be the person table joined to either:
|
||||||
|
@ -178,15 +208,7 @@ impl ReportCombinedQuery {
|
||||||
.left_join(private_message_report::table)
|
.left_join(private_message_report::table)
|
||||||
.left_join(community_report::table)
|
.left_join(community_report::table)
|
||||||
// The report creator
|
// The report creator
|
||||||
.inner_join(
|
.inner_join(person::table.on(report_creator_join))
|
||||||
person::table.on(
|
|
||||||
post_report::creator_id
|
|
||||||
.eq(report_creator)
|
|
||||||
.or(comment_report::creator_id.eq(report_creator))
|
|
||||||
.or(private_message_report::creator_id.eq(report_creator))
|
|
||||||
.or(community_report::creator_id.eq(report_creator)),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
// The comment
|
// The comment
|
||||||
.left_join(comment::table.on(comment_report::comment_id.eq(comment::id)))
|
.left_join(comment::table.on(comment_report::comment_id.eq(comment::id)))
|
||||||
// The private message
|
// The private message
|
||||||
|
@ -195,30 +217,13 @@ impl ReportCombinedQuery {
|
||||||
.on(private_message_report::private_message_id.eq(private_message::id)),
|
.on(private_message_report::private_message_id.eq(private_message::id)),
|
||||||
)
|
)
|
||||||
// The post
|
// The post
|
||||||
.left_join(
|
.left_join(post::table.on(post_join))
|
||||||
post::table.on(
|
|
||||||
post_report::post_id
|
|
||||||
.eq(post::id)
|
|
||||||
.or(comment::post_id.eq(post::id)),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
// The item creator (`item_creator` is the id of this person)
|
// The item creator (`item_creator` is the id of this person)
|
||||||
.left_join(
|
.left_join(aliases::person1.on(item_creator_join))
|
||||||
aliases::person1.on(
|
// The resolver
|
||||||
post::creator_id
|
.left_join(aliases::person2.on(resolver_join))
|
||||||
.eq(item_creator)
|
|
||||||
.or(comment::creator_id.eq(item_creator))
|
|
||||||
.or(private_message::creator_id.eq(item_creator)),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
// The community
|
// The community
|
||||||
.left_join(
|
.left_join(community_join)
|
||||||
community::table.on(
|
|
||||||
post::community_id
|
|
||||||
.eq(community::id)
|
|
||||||
.or(community_report::community_id.eq(community::id)),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.left_join(actions_alias(
|
.left_join(actions_alias(
|
||||||
creator_community_actions,
|
creator_community_actions,
|
||||||
item_creator,
|
item_creator,
|
||||||
|
@ -250,16 +255,6 @@ impl ReportCombinedQuery {
|
||||||
community_aggregates::table
|
community_aggregates::table
|
||||||
.on(community_report::community_id.eq(community_aggregates::community_id)),
|
.on(community_report::community_id.eq(community_aggregates::community_id)),
|
||||||
)
|
)
|
||||||
// The resolver
|
|
||||||
.left_join(
|
|
||||||
aliases::person2.on(
|
|
||||||
private_message_report::resolver_id
|
|
||||||
.eq(resolver)
|
|
||||||
.or(post_report::resolver_id.eq(resolver))
|
|
||||||
.or(comment_report::resolver_id.eq(resolver))
|
|
||||||
.or(community_report::resolver_id.eq(resolver)),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.left_join(actions(
|
.left_join(actions(
|
||||||
comment_actions::table,
|
comment_actions::table,
|
||||||
Some(my_person_id),
|
Some(my_person_id),
|
||||||
|
@ -318,6 +313,10 @@ impl ReportCombinedQuery {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(post_id) = self.post_id {
|
||||||
|
query = query.filter(post::id.eq(post_id));
|
||||||
|
}
|
||||||
|
|
||||||
// If its not an admin, get only the ones you mod
|
// If its not an admin, get only the ones you mod
|
||||||
if !user.local_user.admin {
|
if !user.local_user.admin {
|
||||||
query = query.filter(
|
query = query.filter(
|
||||||
|
@ -337,6 +336,18 @@ impl ReportCombinedQuery {
|
||||||
query = query.after(page_after);
|
query = query.after(page_after);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(type_) = self.type_ {
|
||||||
|
query = match type_ {
|
||||||
|
ReportType::All => query,
|
||||||
|
ReportType::Posts => query.filter(report_combined::post_report_id.is_not_null()),
|
||||||
|
ReportType::Comments => query.filter(report_combined::comment_report_id.is_not_null()),
|
||||||
|
ReportType::PrivateMessages => {
|
||||||
|
query.filter(report_combined::private_message_report_id.is_not_null())
|
||||||
|
}
|
||||||
|
ReportType::Communities => query.filter(report_combined::community_report_id.is_not_null()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If viewing all reports, order by newest, but if viewing unresolved only, show the oldest
|
// If viewing all reports, order by newest, but if viewing unresolved only, show the oldest
|
||||||
// first (FIFO)
|
// first (FIFO)
|
||||||
if self.unresolved_only.unwrap_or_default() {
|
if self.unresolved_only.unwrap_or_default() {
|
||||||
|
@ -508,6 +519,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
traits::{Crud, Joinable, Reportable},
|
traits::{Crud, Joinable, Reportable},
|
||||||
utils::{build_db_pool_for_tests, DbPool},
|
utils::{build_db_pool_for_tests, DbPool},
|
||||||
|
ReportType,
|
||||||
};
|
};
|
||||||
use lemmy_utils::error::LemmyResult;
|
use lemmy_utils::error::LemmyResult;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
@ -677,7 +689,7 @@ mod tests {
|
||||||
let reports = ReportCombinedQuery::default()
|
let reports = ReportCombinedQuery::default()
|
||||||
.list(pool, &data.admin_view)
|
.list(pool, &data.admin_view)
|
||||||
.await?;
|
.await?;
|
||||||
assert_eq!(4, reports.len());
|
assert_length!(4, reports);
|
||||||
|
|
||||||
// Make sure the report types are correct
|
// Make sure the report types are correct
|
||||||
if let ReportCombinedView::Community(v) = &reports[3] {
|
if let ReportCombinedView::Community(v) = &reports[3] {
|
||||||
|
@ -709,22 +721,41 @@ mod tests {
|
||||||
ReportCombinedViewInternal::get_report_count(pool, &data.admin_view, None).await?;
|
ReportCombinedViewInternal::get_report_count(pool, &data.admin_view, None).await?;
|
||||||
assert_eq!(4, report_count_admin);
|
assert_eq!(4, report_count_admin);
|
||||||
|
|
||||||
|
// Make sure the type_ filter is working
|
||||||
|
let reports_by_type = ReportCombinedQuery {
|
||||||
|
type_: Some(ReportType::Posts),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.list(pool, &data.admin_view)
|
||||||
|
.await?;
|
||||||
|
assert_length!(1, reports_by_type);
|
||||||
|
|
||||||
|
// Filter by the post id
|
||||||
|
// Should be 2, for the post, and the comment on that post
|
||||||
|
let reports_by_post_id = ReportCombinedQuery {
|
||||||
|
post_id: Some(data.post.id),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.list(pool, &data.admin_view)
|
||||||
|
.await?;
|
||||||
|
assert_length!(2, reports_by_post_id);
|
||||||
|
|
||||||
// Timmy should only see 2 reports, since they're not an admin,
|
// Timmy should only see 2 reports, since they're not an admin,
|
||||||
// but they do mod the community
|
// but they do mod the community
|
||||||
let reports = ReportCombinedQuery::default()
|
let timmys_reports = ReportCombinedQuery::default()
|
||||||
.list(pool, &data.timmy_view)
|
.list(pool, &data.timmy_view)
|
||||||
.await?;
|
.await?;
|
||||||
assert_eq!(2, reports.len());
|
assert_length!(2, timmys_reports);
|
||||||
|
|
||||||
// Make sure the report types are correct
|
// Make sure the report types are correct
|
||||||
if let ReportCombinedView::Post(v) = &reports[1] {
|
if let ReportCombinedView::Post(v) = &timmys_reports[1] {
|
||||||
assert_eq!(data.post.id, v.post.id);
|
assert_eq!(data.post.id, v.post.id);
|
||||||
assert_eq!(data.sara.id, v.creator.id);
|
assert_eq!(data.sara.id, v.creator.id);
|
||||||
assert_eq!(data.timmy.id, v.post_creator.id);
|
assert_eq!(data.timmy.id, v.post_creator.id);
|
||||||
} else {
|
} else {
|
||||||
panic!("wrong type");
|
panic!("wrong type");
|
||||||
}
|
}
|
||||||
if let ReportCombinedView::Comment(v) = &reports[0] {
|
if let ReportCombinedView::Comment(v) = &timmys_reports[0] {
|
||||||
assert_eq!(data.comment.id, v.comment.id);
|
assert_eq!(data.comment.id, v.comment.id);
|
||||||
assert_eq!(data.post.id, v.post.id);
|
assert_eq!(data.post.id, v.post.id);
|
||||||
assert_eq!(data.timmy.id, v.comment_creator.id);
|
assert_eq!(data.timmy.id, v.comment_creator.id);
|
||||||
|
@ -1050,6 +1081,16 @@ mod tests {
|
||||||
ReportCombinedViewInternal::get_report_count(pool, &data.timmy_view, None).await?;
|
ReportCombinedViewInternal::get_report_count(pool, &data.timmy_view, None).await?;
|
||||||
assert_eq!(1, report_count_after_resolved);
|
assert_eq!(1, report_count_after_resolved);
|
||||||
|
|
||||||
|
// Filter by post id, which should still include the comments.
|
||||||
|
let reports_post_id_filter = ReportCombinedQuery {
|
||||||
|
post_id: Some(data.post.id),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
.list(pool, &data.timmy_view)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
assert_length!(2, reports_post_id_filter);
|
||||||
|
|
||||||
cleanup(data, pool).await?;
|
cleanup(data, pool).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Reference in a new issue