Add modlog entries for bulk removals. (#5050)
* Add modlog entries for bulk removals. - Added unit tests for removal / restore to api_common/utils. - Fixes #4699 * Address PR comments. * Combining remove and restore functions. * Trigger build. * Trigger build 2. * Changing allow to expect.
This commit is contained in:
parent
338344dbc5
commit
e3edc317be
8 changed files with 424 additions and 176 deletions
|
@ -92,8 +92,10 @@ pub async fn ban_from_community(
|
|||
let remove_data = data.ban;
|
||||
remove_or_restore_user_data_in_community(
|
||||
data.community_id,
|
||||
local_user_view.person.id,
|
||||
banned_person_id,
|
||||
remove_data,
|
||||
&data.reason,
|
||||
&mut context.pool(),
|
||||
)
|
||||
.await?;
|
||||
|
|
|
@ -5,7 +5,7 @@ use lemmy_api_common::{
|
|||
context::LemmyContext,
|
||||
person::{BanPerson, BanPersonResponse},
|
||||
send_activity::{ActivityChannel, SendActivityData},
|
||||
utils::{check_expire_time, is_admin, remove_user_data, restore_user_data},
|
||||
utils::{check_expire_time, is_admin, remove_or_restore_user_data},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
|
@ -66,11 +66,15 @@ pub async fn ban_from_site(
|
|||
|
||||
// Remove their data if that's desired
|
||||
if data.remove_or_restore_data.unwrap_or(false) {
|
||||
if data.ban {
|
||||
remove_user_data(person.id, &context).await?;
|
||||
} else {
|
||||
restore_user_data(person.id, &context).await?;
|
||||
}
|
||||
let removed = data.ban;
|
||||
remove_or_restore_user_data(
|
||||
local_user_view.person.id,
|
||||
person.id,
|
||||
removed,
|
||||
&data.reason,
|
||||
&context,
|
||||
)
|
||||
.await?;
|
||||
};
|
||||
|
||||
// Mod tables
|
||||
|
|
|
@ -11,7 +11,7 @@ use chrono::{DateTime, Days, Local, TimeZone, Utc};
|
|||
use enum_map::{enum_map, EnumMap};
|
||||
use lemmy_db_schema::{
|
||||
aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm},
|
||||
newtypes::{CommunityId, DbUrl, InstanceId, PersonId, PostId},
|
||||
newtypes::{CommentId, CommunityId, DbUrl, InstanceId, PersonId, PostId},
|
||||
source::{
|
||||
comment::{Comment, CommentUpdateForm},
|
||||
community::{Community, CommunityModerator, CommunityUpdateForm},
|
||||
|
@ -23,6 +23,7 @@ use lemmy_db_schema::{
|
|||
local_site::LocalSite,
|
||||
local_site_rate_limit::LocalSiteRateLimit,
|
||||
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
||||
moderator::{ModRemoveComment, ModRemoveCommentForm, ModRemovePost, ModRemovePostForm},
|
||||
oauth_account::OAuthAccount,
|
||||
password_reset_request::PasswordResetRequest,
|
||||
person::{Person, PersonUpdateForm},
|
||||
|
@ -667,112 +668,179 @@ pub async fn purge_image_posts_for_community(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn remove_user_data(
|
||||
/// Removes or restores user data.
|
||||
pub async fn remove_or_restore_user_data(
|
||||
mod_person_id: PersonId,
|
||||
banned_person_id: PersonId,
|
||||
removed: bool,
|
||||
reason: &Option<String>,
|
||||
context: &LemmyContext,
|
||||
) -> LemmyResult<()> {
|
||||
let pool = &mut context.pool();
|
||||
// Purge user images
|
||||
let person = Person::read(pool, banned_person_id).await?;
|
||||
if let Some(avatar) = person.avatar {
|
||||
purge_image_from_pictrs(&avatar, context).await.ok();
|
||||
}
|
||||
if let Some(banner) = person.banner {
|
||||
purge_image_from_pictrs(&banner, context).await.ok();
|
||||
|
||||
// Only these actions are possible when removing, not restoring
|
||||
if removed {
|
||||
// Purge user images
|
||||
let person = Person::read(pool, banned_person_id).await?;
|
||||
if let Some(avatar) = person.avatar {
|
||||
purge_image_from_pictrs(&avatar, context).await.ok();
|
||||
}
|
||||
if let Some(banner) = person.banner {
|
||||
purge_image_from_pictrs(&banner, context).await.ok();
|
||||
}
|
||||
|
||||
// Update the fields to None
|
||||
Person::update(
|
||||
pool,
|
||||
banned_person_id,
|
||||
&PersonUpdateForm {
|
||||
avatar: Some(None),
|
||||
banner: Some(None),
|
||||
bio: Some(None),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Purge image posts
|
||||
purge_image_posts_for_person(banned_person_id, context).await?;
|
||||
|
||||
// Communities
|
||||
// Remove all communities where they're the top mod
|
||||
// for now, remove the communities manually
|
||||
let first_mod_communities = CommunityModeratorView::get_community_first_mods(pool).await?;
|
||||
|
||||
// Filter to only this banned users top communities
|
||||
let banned_user_first_communities: Vec<CommunityModeratorView> = first_mod_communities
|
||||
.into_iter()
|
||||
.filter(|fmc| fmc.moderator.id == banned_person_id)
|
||||
.collect();
|
||||
|
||||
for first_mod_community in banned_user_first_communities {
|
||||
let community_id = first_mod_community.community.id;
|
||||
Community::update(
|
||||
pool,
|
||||
community_id,
|
||||
&CommunityUpdateForm {
|
||||
removed: Some(removed),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Delete the community images
|
||||
if let Some(icon) = first_mod_community.community.icon {
|
||||
purge_image_from_pictrs(&icon, context).await.ok();
|
||||
}
|
||||
if let Some(banner) = first_mod_community.community.banner {
|
||||
purge_image_from_pictrs(&banner, context).await.ok();
|
||||
}
|
||||
// Update the fields to None
|
||||
Community::update(
|
||||
pool,
|
||||
community_id,
|
||||
&CommunityUpdateForm {
|
||||
icon: Some(None),
|
||||
banner: Some(None),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the fields to None
|
||||
Person::update(
|
||||
// Posts
|
||||
let removed_or_restored_posts =
|
||||
Post::update_removed_for_creator(pool, banned_person_id, None, removed).await?;
|
||||
create_modlog_entries_for_removed_or_restored_posts(
|
||||
pool,
|
||||
banned_person_id,
|
||||
&PersonUpdateForm {
|
||||
avatar: Some(None),
|
||||
banner: Some(None),
|
||||
bio: Some(None),
|
||||
..Default::default()
|
||||
},
|
||||
mod_person_id,
|
||||
removed_or_restored_posts.iter().map(|r| r.id).collect(),
|
||||
removed,
|
||||
reason,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Posts
|
||||
Post::update_removed_for_creator(pool, banned_person_id, None, true).await?;
|
||||
|
||||
// Purge image posts
|
||||
purge_image_posts_for_person(banned_person_id, context).await?;
|
||||
|
||||
// Communities
|
||||
// Remove all communities where they're the top mod
|
||||
// for now, remove the communities manually
|
||||
let first_mod_communities = CommunityModeratorView::get_community_first_mods(pool).await?;
|
||||
|
||||
// Filter to only this banned users top communities
|
||||
let banned_user_first_communities: Vec<CommunityModeratorView> = first_mod_communities
|
||||
.into_iter()
|
||||
.filter(|fmc| fmc.moderator.id == banned_person_id)
|
||||
.collect();
|
||||
|
||||
for first_mod_community in banned_user_first_communities {
|
||||
let community_id = first_mod_community.community.id;
|
||||
Community::update(
|
||||
pool,
|
||||
community_id,
|
||||
&CommunityUpdateForm {
|
||||
removed: Some(true),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Delete the community images
|
||||
if let Some(icon) = first_mod_community.community.icon {
|
||||
purge_image_from_pictrs(&icon, context).await.ok();
|
||||
}
|
||||
if let Some(banner) = first_mod_community.community.banner {
|
||||
purge_image_from_pictrs(&banner, context).await.ok();
|
||||
}
|
||||
// Update the fields to None
|
||||
Community::update(
|
||||
pool,
|
||||
community_id,
|
||||
&CommunityUpdateForm {
|
||||
icon: Some(None),
|
||||
banner: Some(None),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
// Comments
|
||||
Comment::update_removed_for_creator(pool, banned_person_id, true).await?;
|
||||
let removed_or_restored_comments =
|
||||
Comment::update_removed_for_creator(pool, banned_person_id, removed).await?;
|
||||
create_modlog_entries_for_removed_or_restored_comments(
|
||||
pool,
|
||||
mod_person_id,
|
||||
removed_or_restored_comments.iter().map(|r| r.id).collect(),
|
||||
removed,
|
||||
reason,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// We can't restore their images, but we can unremove their posts and comments
|
||||
pub async fn restore_user_data(
|
||||
banned_person_id: PersonId,
|
||||
context: &LemmyContext,
|
||||
async fn create_modlog_entries_for_removed_or_restored_posts(
|
||||
pool: &mut DbPool<'_>,
|
||||
mod_person_id: PersonId,
|
||||
post_ids: Vec<PostId>,
|
||||
removed: bool,
|
||||
reason: &Option<String>,
|
||||
) -> LemmyResult<()> {
|
||||
let pool = &mut context.pool();
|
||||
// Build the forms
|
||||
let forms = post_ids
|
||||
.iter()
|
||||
.map(|&post_id| ModRemovePostForm {
|
||||
mod_person_id,
|
||||
post_id,
|
||||
removed: Some(removed),
|
||||
reason: reason.clone(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
// Posts
|
||||
Post::update_removed_for_creator(pool, banned_person_id, None, false).await?;
|
||||
ModRemovePost::create_multiple(pool, &forms).await?;
|
||||
|
||||
// Comments
|
||||
Comment::update_removed_for_creator(pool, banned_person_id, false).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_modlog_entries_for_removed_or_restored_comments(
|
||||
pool: &mut DbPool<'_>,
|
||||
mod_person_id: PersonId,
|
||||
comment_ids: Vec<CommentId>,
|
||||
removed: bool,
|
||||
reason: &Option<String>,
|
||||
) -> LemmyResult<()> {
|
||||
// Build the forms
|
||||
let forms = comment_ids
|
||||
.iter()
|
||||
.map(|&comment_id| ModRemoveCommentForm {
|
||||
mod_person_id,
|
||||
comment_id,
|
||||
removed: Some(removed),
|
||||
reason: reason.clone(),
|
||||
})
|
||||
.collect();
|
||||
|
||||
ModRemoveComment::create_multiple(pool, &forms).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn remove_or_restore_user_data_in_community(
|
||||
community_id: CommunityId,
|
||||
mod_person_id: PersonId,
|
||||
banned_person_id: PersonId,
|
||||
remove: bool,
|
||||
reason: &Option<String>,
|
||||
pool: &mut DbPool<'_>,
|
||||
) -> LemmyResult<()> {
|
||||
// Posts
|
||||
Post::update_removed_for_creator(pool, banned_person_id, Some(community_id), remove).await?;
|
||||
let posts =
|
||||
Post::update_removed_for_creator(pool, banned_person_id, Some(community_id), remove).await?;
|
||||
create_modlog_entries_for_removed_or_restored_posts(
|
||||
pool,
|
||||
mod_person_id,
|
||||
posts.iter().map(|r| r.id).collect(),
|
||||
remove,
|
||||
reason,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Comments
|
||||
// TODO Diesel doesn't allow updates with joins, so this has to be a loop
|
||||
|
@ -798,6 +866,15 @@ pub async fn remove_or_restore_user_data_in_community(
|
|||
.await?;
|
||||
}
|
||||
|
||||
create_modlog_entries_for_removed_or_restored_comments(
|
||||
pool,
|
||||
mod_person_id,
|
||||
comments.iter().map(|r| r.comment.id).collect(),
|
||||
remove,
|
||||
reason,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1067,10 +1144,20 @@ fn build_proxied_image_url(
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[expect(clippy::unwrap_used)]
|
||||
mod tests {
|
||||
|
||||
use super::*;
|
||||
use lemmy_db_schema::source::{
|
||||
comment::CommentInsertForm,
|
||||
community::CommunityInsertForm,
|
||||
person::PersonInsertForm,
|
||||
post::PostInsertForm,
|
||||
};
|
||||
use lemmy_db_views_moderator::structs::{
|
||||
ModRemoveCommentView,
|
||||
ModRemovePostView,
|
||||
ModlogListParams,
|
||||
};
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
||||
|
@ -1092,48 +1179,42 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_limit_ban_term() {
|
||||
fn test_limit_ban_term() -> LemmyResult<()> {
|
||||
// Ban expires in past, should throw error
|
||||
assert!(limit_expire_time(Utc::now() - Days::new(5)).is_err());
|
||||
|
||||
// Legitimate ban term, return same value
|
||||
let fourteen_days = Utc::now() + Days::new(14);
|
||||
assert_eq!(
|
||||
limit_expire_time(fourteen_days).unwrap(),
|
||||
Some(fourteen_days)
|
||||
);
|
||||
assert_eq!(limit_expire_time(fourteen_days)?, Some(fourteen_days));
|
||||
let nine_years = Utc::now() + Days::new(365 * 9);
|
||||
assert_eq!(limit_expire_time(nine_years).unwrap(), Some(nine_years));
|
||||
assert_eq!(limit_expire_time(nine_years)?, Some(nine_years));
|
||||
|
||||
// Too long ban term, changes to None (permanent ban)
|
||||
assert_eq!(
|
||||
limit_expire_time(Utc::now() + Days::new(365 * 11)).unwrap(),
|
||||
None
|
||||
);
|
||||
assert_eq!(limit_expire_time(Utc::now() + Days::new(365 * 11))?, None);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_proxy_image_link() {
|
||||
async fn test_proxy_image_link() -> LemmyResult<()> {
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
|
||||
// image from local domain is unchanged
|
||||
let local_url = Url::parse("http://lemmy-alpha/image.png").unwrap();
|
||||
let local_url = Url::parse("http://lemmy-alpha/image.png")?;
|
||||
let proxied =
|
||||
proxy_image_link_internal(local_url.clone(), PictrsImageMode::ProxyAllImages, &context)
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
assert_eq!(&local_url, proxied.inner());
|
||||
|
||||
// image from remote domain is proxied
|
||||
let remote_image = Url::parse("http://lemmy-beta/image.png").unwrap();
|
||||
let remote_image = Url::parse("http://lemmy-beta/image.png")?;
|
||||
let proxied = proxy_image_link_internal(
|
||||
remote_image.clone(),
|
||||
PictrsImageMode::ProxyAllImages,
|
||||
&context,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
.await?;
|
||||
assert_eq!(
|
||||
"https://lemmy-alpha/api/v3/image_proxy?url=http%3A%2F%2Flemmy-beta%2Fimage.png",
|
||||
proxied.as_str()
|
||||
|
@ -1146,5 +1227,159 @@ mod tests {
|
|||
.await
|
||||
.is_ok()
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_mod_remove_or_restore_data() -> LemmyResult<()> {
|
||||
let context = LemmyContext::init_test_context().await;
|
||||
let pool = &mut context.pool();
|
||||
|
||||
let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()).await?;
|
||||
|
||||
let new_mod = PersonInsertForm::test_form(inserted_instance.id, "modder");
|
||||
let inserted_mod = Person::create(pool, &new_mod).await?;
|
||||
|
||||
let new_person = PersonInsertForm::test_form(inserted_instance.id, "chrimbus");
|
||||
let inserted_person = Person::create(pool, &new_person).await?;
|
||||
|
||||
let new_community = CommunityInsertForm::new(
|
||||
inserted_instance.id,
|
||||
"mod_community crepes".to_string(),
|
||||
"nada".to_owned(),
|
||||
"pubkey".to_string(),
|
||||
);
|
||||
let inserted_community = Community::create(pool, &new_community).await?;
|
||||
|
||||
let post_form_1 = PostInsertForm::new(
|
||||
"A test post tubular".into(),
|
||||
inserted_person.id,
|
||||
inserted_community.id,
|
||||
);
|
||||
let inserted_post_1 = Post::create(pool, &post_form_1).await?;
|
||||
|
||||
let post_form_2 = PostInsertForm::new(
|
||||
"A test post radical".into(),
|
||||
inserted_person.id,
|
||||
inserted_community.id,
|
||||
);
|
||||
let inserted_post_2 = Post::create(pool, &post_form_2).await?;
|
||||
|
||||
let comment_form_1 = CommentInsertForm::new(
|
||||
inserted_person.id,
|
||||
inserted_post_1.id,
|
||||
"A test comment tubular".into(),
|
||||
);
|
||||
let _inserted_comment_1 = Comment::create(pool, &comment_form_1, None).await?;
|
||||
|
||||
let comment_form_2 = CommentInsertForm::new(
|
||||
inserted_person.id,
|
||||
inserted_post_2.id,
|
||||
"A test comment radical".into(),
|
||||
);
|
||||
let _inserted_comment_2 = Comment::create(pool, &comment_form_2, None).await?;
|
||||
|
||||
// Remove the user data
|
||||
remove_or_restore_user_data(
|
||||
inserted_mod.id,
|
||||
inserted_person.id,
|
||||
true,
|
||||
&Some("a remove reason".to_string()),
|
||||
&context,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Verify that their posts and comments are removed.
|
||||
let params = ModlogListParams {
|
||||
community_id: None,
|
||||
mod_person_id: None,
|
||||
other_person_id: None,
|
||||
post_id: None,
|
||||
comment_id: None,
|
||||
page: None,
|
||||
limit: None,
|
||||
hide_modlog_names: false,
|
||||
};
|
||||
|
||||
// Posts
|
||||
let post_modlog = ModRemovePostView::list(pool, params).await?;
|
||||
assert_eq!(2, post_modlog.len());
|
||||
|
||||
let mod_removed_posts = post_modlog
|
||||
.iter()
|
||||
.map(|p| p.mod_remove_post.removed)
|
||||
.collect::<Vec<bool>>();
|
||||
assert_eq!(vec![true, true], mod_removed_posts);
|
||||
|
||||
let removed_posts = post_modlog
|
||||
.iter()
|
||||
.map(|p| p.post.removed)
|
||||
.collect::<Vec<bool>>();
|
||||
assert_eq!(vec![true, true], removed_posts);
|
||||
|
||||
// Comments
|
||||
let comment_modlog = ModRemoveCommentView::list(pool, params).await?;
|
||||
assert_eq!(2, comment_modlog.len());
|
||||
|
||||
let mod_removed_comments = comment_modlog
|
||||
.iter()
|
||||
.map(|p| p.mod_remove_comment.removed)
|
||||
.collect::<Vec<bool>>();
|
||||
assert_eq!(vec![true, true], mod_removed_comments);
|
||||
|
||||
let removed_comments = comment_modlog
|
||||
.iter()
|
||||
.map(|p| p.comment.removed)
|
||||
.collect::<Vec<bool>>();
|
||||
assert_eq!(vec![true, true], removed_comments);
|
||||
|
||||
// Now restore the content, and make sure it got appended
|
||||
remove_or_restore_user_data(
|
||||
inserted_mod.id,
|
||||
inserted_person.id,
|
||||
false,
|
||||
&Some("a restore reason".to_string()),
|
||||
&context,
|
||||
)
|
||||
.await?;
|
||||
|
||||
// Posts
|
||||
let post_modlog = ModRemovePostView::list(pool, params).await?;
|
||||
assert_eq!(4, post_modlog.len());
|
||||
|
||||
let mod_restored_posts = post_modlog
|
||||
.iter()
|
||||
.map(|p| p.mod_remove_post.removed)
|
||||
.collect::<Vec<bool>>();
|
||||
assert_eq!(vec![false, false, true, true], mod_restored_posts);
|
||||
|
||||
let restored_posts = post_modlog
|
||||
.iter()
|
||||
.map(|p| p.post.removed)
|
||||
.collect::<Vec<bool>>();
|
||||
// All of these will be false, cause its the current state of the post
|
||||
assert_eq!(vec![false, false, false, false], restored_posts);
|
||||
|
||||
// Comments
|
||||
let comment_modlog = ModRemoveCommentView::list(pool, params).await?;
|
||||
assert_eq!(4, comment_modlog.len());
|
||||
|
||||
let mod_restored_comments = comment_modlog
|
||||
.iter()
|
||||
.map(|p| p.mod_remove_comment.removed)
|
||||
.collect::<Vec<bool>>();
|
||||
assert_eq!(vec![false, false, true, true], mod_restored_comments);
|
||||
|
||||
let restored_comments = comment_modlog
|
||||
.iter()
|
||||
.map(|p| p.comment.removed)
|
||||
.collect::<Vec<bool>>();
|
||||
assert_eq!(vec![false, false, false, false], restored_comments);
|
||||
|
||||
Instance::delete(pool, inserted_instance.id).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ use anyhow::anyhow;
|
|||
use chrono::{DateTime, Utc};
|
||||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
utils::{remove_or_restore_user_data_in_community, remove_user_data},
|
||||
utils::{remove_or_restore_user_data, remove_or_restore_user_data_in_community},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
|
@ -160,6 +160,7 @@ impl ActivityHandler for BlockUser {
|
|||
let mod_person = self.actor.dereference(context).await?;
|
||||
let blocked_person = self.object.dereference(context).await?;
|
||||
let target = self.target.dereference(context).await?;
|
||||
let reason = self.summary;
|
||||
match target {
|
||||
SiteOrCommunity::Site(_site) => {
|
||||
let blocked_person = Person::update(
|
||||
|
@ -173,14 +174,15 @@ impl ActivityHandler for BlockUser {
|
|||
)
|
||||
.await?;
|
||||
if self.remove_data.unwrap_or(false) {
|
||||
remove_user_data(blocked_person.id, context).await?;
|
||||
remove_or_restore_user_data(mod_person.id, blocked_person.id, true, &reason, context)
|
||||
.await?;
|
||||
}
|
||||
|
||||
// write mod log
|
||||
let form = ModBanForm {
|
||||
mod_person_id: mod_person.id,
|
||||
other_person_id: blocked_person.id,
|
||||
reason: self.summary,
|
||||
reason,
|
||||
banned: Some(true),
|
||||
expires,
|
||||
};
|
||||
|
@ -207,8 +209,10 @@ impl ActivityHandler for BlockUser {
|
|||
if self.remove_data.unwrap_or(false) {
|
||||
remove_or_restore_user_data_in_community(
|
||||
community.id,
|
||||
mod_person.id,
|
||||
blocked_person.id,
|
||||
true,
|
||||
&reason,
|
||||
&mut context.pool(),
|
||||
)
|
||||
.await?;
|
||||
|
@ -219,7 +223,7 @@ impl ActivityHandler for BlockUser {
|
|||
mod_person_id: mod_person.id,
|
||||
other_person_id: blocked_person.id,
|
||||
community_id: community.id,
|
||||
reason: self.summary,
|
||||
reason,
|
||||
banned: Some(true),
|
||||
expires,
|
||||
};
|
||||
|
|
|
@ -19,7 +19,7 @@ use activitypub_federation::{
|
|||
};
|
||||
use lemmy_api_common::{
|
||||
context::LemmyContext,
|
||||
utils::{remove_or_restore_user_data_in_community, restore_user_data},
|
||||
utils::{remove_or_restore_user_data, remove_or_restore_user_data_in_community},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
|
@ -120,7 +120,8 @@ impl ActivityHandler for UndoBlockUser {
|
|||
.await?;
|
||||
|
||||
if self.restore_data.unwrap_or(false) {
|
||||
restore_user_data(blocked_person.id, context).await?;
|
||||
remove_or_restore_user_data(mod_person.id, blocked_person.id, false, &None, context)
|
||||
.await?;
|
||||
}
|
||||
|
||||
// write mod log
|
||||
|
@ -144,8 +145,10 @@ impl ActivityHandler for UndoBlockUser {
|
|||
if self.restore_data.unwrap_or(false) {
|
||||
remove_or_restore_user_data_in_community(
|
||||
community.id,
|
||||
mod_person.id,
|
||||
blocked_person.id,
|
||||
false,
|
||||
&None,
|
||||
&mut context.pool(),
|
||||
)
|
||||
.await?;
|
||||
|
|
|
@ -40,12 +40,12 @@ impl Comment {
|
|||
pub async fn update_removed_for_creator(
|
||||
pool: &mut DbPool<'_>,
|
||||
for_creator_id: PersonId,
|
||||
new_removed: bool,
|
||||
removed: bool,
|
||||
) -> Result<Vec<Self>, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
diesel::update(comment::table.filter(comment::creator_id.eq(for_creator_id)))
|
||||
.set((
|
||||
comment::removed.eq(new_removed),
|
||||
comment::removed.eq(removed),
|
||||
comment::updated.eq(naive_now()),
|
||||
))
|
||||
.get_results::<Self>(conn)
|
||||
|
|
|
@ -66,6 +66,20 @@ impl Crud for ModRemovePost {
|
|||
}
|
||||
}
|
||||
|
||||
impl ModRemovePost {
|
||||
pub async fn create_multiple(
|
||||
pool: &mut DbPool<'_>,
|
||||
forms: &Vec<ModRemovePostForm>,
|
||||
) -> Result<usize, Error> {
|
||||
use crate::schema::mod_remove_post::dsl::mod_remove_post;
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(mod_remove_post)
|
||||
.values(forms)
|
||||
.execute(conn)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Crud for ModLockPost {
|
||||
type InsertForm = ModLockPostForm;
|
||||
|
@ -153,6 +167,20 @@ impl Crud for ModRemoveComment {
|
|||
}
|
||||
}
|
||||
|
||||
impl ModRemoveComment {
|
||||
pub async fn create_multiple(
|
||||
pool: &mut DbPool<'_>,
|
||||
forms: &Vec<ModRemoveCommentForm>,
|
||||
) -> Result<usize, Error> {
|
||||
use crate::schema::mod_remove_comment::dsl::mod_remove_comment;
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
insert_into(mod_remove_comment)
|
||||
.values(forms)
|
||||
.execute(conn)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl Crud for ModRemoveCommunity {
|
||||
type InsertForm = ModRemoveCommunityForm;
|
||||
|
@ -465,7 +493,6 @@ impl Crud for AdminPurgeComment {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[expect(clippy::unwrap_used)]
|
||||
mod tests {
|
||||
|
||||
use crate::{
|
||||
|
@ -499,26 +526,25 @@ mod tests {
|
|||
traits::Crud,
|
||||
utils::build_db_pool_for_tests,
|
||||
};
|
||||
use diesel::result::Error;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_crud() {
|
||||
async fn test_crud() -> Result<(), Error> {
|
||||
let pool = &build_db_pool_for_tests().await;
|
||||
let pool = &mut pool.into();
|
||||
|
||||
let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string())
|
||||
.await
|
||||
.unwrap();
|
||||
let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()).await?;
|
||||
|
||||
let new_mod = PersonInsertForm::test_form(inserted_instance.id, "the mod");
|
||||
|
||||
let inserted_mod = Person::create(pool, &new_mod).await.unwrap();
|
||||
let inserted_mod = Person::create(pool, &new_mod).await?;
|
||||
|
||||
let new_person = PersonInsertForm::test_form(inserted_instance.id, "jim2");
|
||||
|
||||
let inserted_person = Person::create(pool, &new_person).await.unwrap();
|
||||
let inserted_person = Person::create(pool, &new_person).await?;
|
||||
|
||||
let new_community = CommunityInsertForm::new(
|
||||
inserted_instance.id,
|
||||
|
@ -527,21 +553,21 @@ mod tests {
|
|||
"pubkey".to_string(),
|
||||
);
|
||||
|
||||
let inserted_community = Community::create(pool, &new_community).await.unwrap();
|
||||
let inserted_community = Community::create(pool, &new_community).await?;
|
||||
|
||||
let new_post = PostInsertForm::new(
|
||||
"A test post thweep".into(),
|
||||
inserted_person.id,
|
||||
inserted_community.id,
|
||||
);
|
||||
let inserted_post = Post::create(pool, &new_post).await.unwrap();
|
||||
let inserted_post = Post::create(pool, &new_post).await?;
|
||||
|
||||
let comment_form = CommentInsertForm::new(
|
||||
inserted_person.id,
|
||||
inserted_post.id,
|
||||
"A test comment".into(),
|
||||
);
|
||||
let inserted_comment = Comment::create(pool, &comment_form, None).await.unwrap();
|
||||
let inserted_comment = Comment::create(pool, &comment_form, None).await?;
|
||||
|
||||
// Now the actual tests
|
||||
|
||||
|
@ -552,12 +578,8 @@ mod tests {
|
|||
reason: None,
|
||||
removed: None,
|
||||
};
|
||||
let inserted_mod_remove_post = ModRemovePost::create(pool, &mod_remove_post_form)
|
||||
.await
|
||||
.unwrap();
|
||||
let read_mod_remove_post = ModRemovePost::read(pool, inserted_mod_remove_post.id)
|
||||
.await
|
||||
.unwrap();
|
||||
let inserted_mod_remove_post = ModRemovePost::create(pool, &mod_remove_post_form).await?;
|
||||
let read_mod_remove_post = ModRemovePost::read(pool, inserted_mod_remove_post.id).await?;
|
||||
let expected_mod_remove_post = ModRemovePost {
|
||||
id: inserted_mod_remove_post.id,
|
||||
post_id: inserted_post.id,
|
||||
|
@ -574,12 +596,8 @@ mod tests {
|
|||
post_id: inserted_post.id,
|
||||
locked: None,
|
||||
};
|
||||
let inserted_mod_lock_post = ModLockPost::create(pool, &mod_lock_post_form)
|
||||
.await
|
||||
.unwrap();
|
||||
let read_mod_lock_post = ModLockPost::read(pool, inserted_mod_lock_post.id)
|
||||
.await
|
||||
.unwrap();
|
||||
let inserted_mod_lock_post = ModLockPost::create(pool, &mod_lock_post_form).await?;
|
||||
let read_mod_lock_post = ModLockPost::read(pool, inserted_mod_lock_post.id).await?;
|
||||
let expected_mod_lock_post = ModLockPost {
|
||||
id: inserted_mod_lock_post.id,
|
||||
post_id: inserted_post.id,
|
||||
|
@ -596,12 +614,8 @@ mod tests {
|
|||
featured: false,
|
||||
is_featured_community: true,
|
||||
};
|
||||
let inserted_mod_feature_post = ModFeaturePost::create(pool, &mod_feature_post_form)
|
||||
.await
|
||||
.unwrap();
|
||||
let read_mod_feature_post = ModFeaturePost::read(pool, inserted_mod_feature_post.id)
|
||||
.await
|
||||
.unwrap();
|
||||
let inserted_mod_feature_post = ModFeaturePost::create(pool, &mod_feature_post_form).await?;
|
||||
let read_mod_feature_post = ModFeaturePost::read(pool, inserted_mod_feature_post.id).await?;
|
||||
let expected_mod_feature_post = ModFeaturePost {
|
||||
id: inserted_mod_feature_post.id,
|
||||
post_id: inserted_post.id,
|
||||
|
@ -619,12 +633,10 @@ mod tests {
|
|||
reason: None,
|
||||
removed: None,
|
||||
};
|
||||
let inserted_mod_remove_comment = ModRemoveComment::create(pool, &mod_remove_comment_form)
|
||||
.await
|
||||
.unwrap();
|
||||
let read_mod_remove_comment = ModRemoveComment::read(pool, inserted_mod_remove_comment.id)
|
||||
.await
|
||||
.unwrap();
|
||||
let inserted_mod_remove_comment =
|
||||
ModRemoveComment::create(pool, &mod_remove_comment_form).await?;
|
||||
let read_mod_remove_comment =
|
||||
ModRemoveComment::read(pool, inserted_mod_remove_comment.id).await?;
|
||||
let expected_mod_remove_comment = ModRemoveComment {
|
||||
id: inserted_mod_remove_comment.id,
|
||||
comment_id: inserted_comment.id,
|
||||
|
@ -643,13 +655,9 @@ mod tests {
|
|||
removed: None,
|
||||
};
|
||||
let inserted_mod_remove_community =
|
||||
ModRemoveCommunity::create(pool, &mod_remove_community_form)
|
||||
.await
|
||||
.unwrap();
|
||||
ModRemoveCommunity::create(pool, &mod_remove_community_form).await?;
|
||||
let read_mod_remove_community =
|
||||
ModRemoveCommunity::read(pool, inserted_mod_remove_community.id)
|
||||
.await
|
||||
.unwrap();
|
||||
ModRemoveCommunity::read(pool, inserted_mod_remove_community.id).await?;
|
||||
let expected_mod_remove_community = ModRemoveCommunity {
|
||||
id: inserted_mod_remove_community.id,
|
||||
community_id: inserted_community.id,
|
||||
|
@ -670,13 +678,9 @@ mod tests {
|
|||
expires: None,
|
||||
};
|
||||
let inserted_mod_ban_from_community =
|
||||
ModBanFromCommunity::create(pool, &mod_ban_from_community_form)
|
||||
.await
|
||||
.unwrap();
|
||||
ModBanFromCommunity::create(pool, &mod_ban_from_community_form).await?;
|
||||
let read_mod_ban_from_community =
|
||||
ModBanFromCommunity::read(pool, inserted_mod_ban_from_community.id)
|
||||
.await
|
||||
.unwrap();
|
||||
ModBanFromCommunity::read(pool, inserted_mod_ban_from_community.id).await?;
|
||||
let expected_mod_ban_from_community = ModBanFromCommunity {
|
||||
id: inserted_mod_ban_from_community.id,
|
||||
community_id: inserted_community.id,
|
||||
|
@ -697,8 +701,8 @@ mod tests {
|
|||
banned: None,
|
||||
expires: None,
|
||||
};
|
||||
let inserted_mod_ban = ModBan::create(pool, &mod_ban_form).await.unwrap();
|
||||
let read_mod_ban = ModBan::read(pool, inserted_mod_ban.id).await.unwrap();
|
||||
let inserted_mod_ban = ModBan::create(pool, &mod_ban_form).await?;
|
||||
let read_mod_ban = ModBan::read(pool, inserted_mod_ban.id).await?;
|
||||
let expected_mod_ban = ModBan {
|
||||
id: inserted_mod_ban.id,
|
||||
mod_person_id: inserted_mod.id,
|
||||
|
@ -717,12 +721,8 @@ mod tests {
|
|||
community_id: inserted_community.id,
|
||||
removed: None,
|
||||
};
|
||||
let inserted_mod_add_community = ModAddCommunity::create(pool, &mod_add_community_form)
|
||||
.await
|
||||
.unwrap();
|
||||
let read_mod_add_community = ModAddCommunity::read(pool, inserted_mod_add_community.id)
|
||||
.await
|
||||
.unwrap();
|
||||
let inserted_mod_add_community = ModAddCommunity::create(pool, &mod_add_community_form).await?;
|
||||
let read_mod_add_community = ModAddCommunity::read(pool, inserted_mod_add_community.id).await?;
|
||||
let expected_mod_add_community = ModAddCommunity {
|
||||
id: inserted_mod_add_community.id,
|
||||
community_id: inserted_community.id,
|
||||
|
@ -739,8 +739,8 @@ mod tests {
|
|||
other_person_id: inserted_person.id,
|
||||
removed: None,
|
||||
};
|
||||
let inserted_mod_add = ModAdd::create(pool, &mod_add_form).await.unwrap();
|
||||
let read_mod_add = ModAdd::read(pool, inserted_mod_add.id).await.unwrap();
|
||||
let inserted_mod_add = ModAdd::create(pool, &mod_add_form).await?;
|
||||
let read_mod_add = ModAdd::read(pool, inserted_mod_add.id).await?;
|
||||
let expected_mod_add = ModAdd {
|
||||
id: inserted_mod_add.id,
|
||||
mod_person_id: inserted_mod.id,
|
||||
|
@ -749,14 +749,12 @@ mod tests {
|
|||
when_: inserted_mod_add.when_,
|
||||
};
|
||||
|
||||
Comment::delete(pool, inserted_comment.id).await.unwrap();
|
||||
Post::delete(pool, inserted_post.id).await.unwrap();
|
||||
Community::delete(pool, inserted_community.id)
|
||||
.await
|
||||
.unwrap();
|
||||
Person::delete(pool, inserted_person.id).await.unwrap();
|
||||
Person::delete(pool, inserted_mod.id).await.unwrap();
|
||||
Instance::delete(pool, inserted_instance.id).await.unwrap();
|
||||
Comment::delete(pool, inserted_comment.id).await?;
|
||||
Post::delete(pool, inserted_post.id).await?;
|
||||
Community::delete(pool, inserted_community.id).await?;
|
||||
Person::delete(pool, inserted_person.id).await?;
|
||||
Person::delete(pool, inserted_mod.id).await?;
|
||||
Instance::delete(pool, inserted_instance.id).await?;
|
||||
|
||||
assert_eq!(expected_mod_remove_post, read_mod_remove_post);
|
||||
assert_eq!(expected_mod_lock_post, read_mod_lock_post);
|
||||
|
@ -767,5 +765,7 @@ mod tests {
|
|||
assert_eq!(expected_mod_ban, read_mod_ban);
|
||||
assert_eq!(expected_mod_add_community, read_mod_add_community);
|
||||
assert_eq!(expected_mod_add, read_mod_add);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,7 +145,7 @@ impl Post {
|
|||
pool: &mut DbPool<'_>,
|
||||
for_creator_id: PersonId,
|
||||
for_community_id: Option<CommunityId>,
|
||||
new_removed: bool,
|
||||
removed: bool,
|
||||
) -> Result<Vec<Self>, Error> {
|
||||
let conn = &mut get_conn(pool).await?;
|
||||
|
||||
|
@ -157,7 +157,7 @@ impl Post {
|
|||
}
|
||||
|
||||
update
|
||||
.set((post::removed.eq(new_removed), post::updated.eq(naive_now())))
|
||||
.set((post::removed.eq(removed), post::updated.eq(naive_now())))
|
||||
.get_results::<Self>(conn)
|
||||
.await
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue