Compare commits

...

5 Commits

13 changed files with 114 additions and 122 deletions

View File

@ -5,7 +5,7 @@ use lemmy_api_common::{
context::LemmyContext, context::LemmyContext,
person::{BanPerson, BanPersonResponse}, person::{BanPerson, BanPersonResponse},
send_activity::{ActivityChannel, SendActivityData}, 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::{ use lemmy_db_schema::{
source::{ source::{
@ -66,11 +66,15 @@ pub async fn ban_from_site(
// Remove their data if that's desired // Remove their data if that's desired
if data.remove_or_restore_data.unwrap_or(false) { if data.remove_or_restore_data.unwrap_or(false) {
if data.ban { let removed = data.ban;
remove_user_data(local_user_view.person.id, person.id, &data.reason, &context).await?; remove_or_restore_user_data(
} else { local_user_view.person.id,
restore_user_data(local_user_view.person.id, person.id, &data.reason, &context).await?; person.id,
} removed,
&data.reason,
&context,
)
.await?;
}; };
// Mod tables // Mod tables

View File

@ -76,5 +76,7 @@ pub async fn leave_admin(
admin_oauth_providers: None, admin_oauth_providers: None,
blocked_urls, blocked_urls,
tagline, tagline,
taglines: vec![],
custom_emojis: vec![],
})) }))
} }

View File

@ -5,6 +5,7 @@ use serde_with::skip_serializing_none;
use ts_rs::TS; use ts_rs::TS;
use url::Url; use url::Url;
#[skip_serializing_none]
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
#[cfg_attr(feature = "full", derive(TS))] #[cfg_attr(feature = "full", derive(TS))]
#[cfg_attr(feature = "full", ts(export))] #[cfg_attr(feature = "full", ts(export))]

View File

@ -306,6 +306,8 @@ pub struct EditSite {
/// The response for a site. /// The response for a site.
pub struct SiteResponse { pub struct SiteResponse {
pub site_view: SiteView, pub site_view: SiteView,
/// deprecated, use field `tagline` or /api/v3/tagline/list
pub taglines: Vec<()>,
} }
#[skip_serializing_none] #[skip_serializing_none]
@ -320,6 +322,10 @@ pub struct GetSiteResponse {
pub my_user: Option<MyUserInfo>, pub my_user: Option<MyUserInfo>,
pub all_languages: Vec<Language>, pub all_languages: Vec<Language>,
pub discussion_languages: Vec<LanguageId>, pub discussion_languages: Vec<LanguageId>,
/// deprecated, use field `tagline` or /api/v3/tagline/list
pub taglines: Vec<()>,
/// deprecated, use /api/v3/custom_emoji/list
pub custom_emojis: Vec<()>,
/// If the site has any taglines, a random one is included here for displaying /// If the site has any taglines, a random one is included here for displaying
pub tagline: Option<Tagline>, pub tagline: Option<Tagline>,
/// A list of external auth methods your site supports. /// A list of external auth methods your site supports.

View File

@ -668,139 +668,106 @@ pub async fn purge_image_posts_for_community(
Ok(()) Ok(())
} }
pub async fn remove_user_data( /// Removes or restores user data.
pub async fn remove_or_restore_user_data(
mod_person_id: PersonId, mod_person_id: PersonId,
banned_person_id: PersonId, banned_person_id: PersonId,
removed: bool,
reason: &Option<String>, reason: &Option<String>,
context: &LemmyContext, context: &LemmyContext,
) -> LemmyResult<()> { ) -> LemmyResult<()> {
let pool = &mut context.pool(); let pool = &mut context.pool();
let removed = true;
// Purge user images // Only these actions are possible when removing, not restoring
let person = Person::read(pool, banned_person_id).await?; if removed {
if let Some(avatar) = person.avatar { // Purge user images
purge_image_from_pictrs(&avatar, context).await.ok(); let person = Person::read(pool, banned_person_id).await?;
} if let Some(avatar) = person.avatar {
if let Some(banner) = person.banner { purge_image_from_pictrs(&avatar, context).await.ok();
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?;
// Posts
let removed_posts =
Post::update_removed_for_creator(pool, banned_person_id, None, removed).await?;
create_modlog_entries_for_removed_or_restored_posts(
pool,
mod_person_id,
removed_posts.iter().map(|r| r.id).collect(),
removed,
reason,
)
.await?;
// Purge image posts
purge_image_posts_for_person(banned_person_id, context).await?;
// Comments
let removed_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_comments.iter().map(|r| r.id).collect(),
removed,
reason,
)
.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 { if let Some(banner) = person.banner {
purge_image_from_pictrs(&banner, context).await.ok(); purge_image_from_pictrs(&banner, context).await.ok();
} }
// Update the fields to None // Update the fields to None
Community::update( Person::update(
pool, pool,
community_id, banned_person_id,
&CommunityUpdateForm { &PersonUpdateForm {
icon: Some(None), avatar: Some(None),
banner: Some(None), banner: Some(None),
bio: Some(None),
..Default::default() ..Default::default()
}, },
) )
.await?; .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?;
}
} }
Ok(())
}
/// We can't restore their images, but we can unremove their posts and comments
pub async fn restore_user_data(
mod_person_id: PersonId,
banned_person_id: PersonId,
reason: &Option<String>,
context: &LemmyContext,
) -> LemmyResult<()> {
let pool = &mut context.pool();
let removed = false;
// Posts // Posts
let restored_posts = let removed_or_restored_posts =
Post::update_removed_for_creator(pool, banned_person_id, None, removed).await?; Post::update_removed_for_creator(pool, banned_person_id, None, removed).await?;
create_modlog_entries_for_removed_or_restored_posts( create_modlog_entries_for_removed_or_restored_posts(
pool, pool,
mod_person_id, mod_person_id,
restored_posts.iter().map(|r| r.id).collect(), removed_or_restored_posts.iter().map(|r| r.id).collect(),
removed, removed,
reason, reason,
) )
.await?; .await?;
// Comments // Comments
let restored_comments = let removed_or_restored_comments =
Comment::update_removed_for_creator(pool, banned_person_id, removed).await?; Comment::update_removed_for_creator(pool, banned_person_id, removed).await?;
create_modlog_entries_for_removed_or_restored_comments( create_modlog_entries_for_removed_or_restored_comments(
pool, pool,
mod_person_id, mod_person_id,
restored_comments.iter().map(|r| r.id).collect(), removed_or_restored_comments.iter().map(|r| r.id).collect(),
removed, removed,
reason, reason,
) )
@ -813,7 +780,7 @@ async fn create_modlog_entries_for_removed_or_restored_posts(
pool: &mut DbPool<'_>, pool: &mut DbPool<'_>,
mod_person_id: PersonId, mod_person_id: PersonId,
post_ids: Vec<PostId>, post_ids: Vec<PostId>,
new_removed: bool, removed: bool,
reason: &Option<String>, reason: &Option<String>,
) -> LemmyResult<()> { ) -> LemmyResult<()> {
// Build the forms // Build the forms
@ -822,7 +789,7 @@ async fn create_modlog_entries_for_removed_or_restored_posts(
.map(|&post_id| ModRemovePostForm { .map(|&post_id| ModRemovePostForm {
mod_person_id, mod_person_id,
post_id, post_id,
removed: Some(new_removed), removed: Some(removed),
reason: reason.clone(), reason: reason.clone(),
}) })
.collect(); .collect();
@ -836,7 +803,7 @@ async fn create_modlog_entries_for_removed_or_restored_comments(
pool: &mut DbPool<'_>, pool: &mut DbPool<'_>,
mod_person_id: PersonId, mod_person_id: PersonId,
comment_ids: Vec<CommentId>, comment_ids: Vec<CommentId>,
new_removed: bool, removed: bool,
reason: &Option<String>, reason: &Option<String>,
) -> LemmyResult<()> { ) -> LemmyResult<()> {
// Build the forms // Build the forms
@ -845,7 +812,7 @@ async fn create_modlog_entries_for_removed_or_restored_comments(
.map(|&comment_id| ModRemoveCommentForm { .map(|&comment_id| ModRemoveCommentForm {
mod_person_id, mod_person_id,
comment_id, comment_id,
removed: Some(new_removed), removed: Some(removed),
reason: reason.clone(), reason: reason.clone(),
}) })
.collect(); .collect();
@ -1316,9 +1283,10 @@ mod tests {
let _inserted_comment_2 = Comment::create(pool, &comment_form_2, None).await?; let _inserted_comment_2 = Comment::create(pool, &comment_form_2, None).await?;
// Remove the user data // Remove the user data
remove_user_data( remove_or_restore_user_data(
inserted_mod.id, inserted_mod.id,
inserted_person.id, inserted_person.id,
true,
&Some("a remove reason".to_string()), &Some("a remove reason".to_string()),
&context, &context,
) )
@ -1369,9 +1337,10 @@ mod tests {
assert_eq!(vec![true, true], removed_comments); assert_eq!(vec![true, true], removed_comments);
// Now restore the content, and make sure it got appended // Now restore the content, and make sure it got appended
restore_user_data( remove_or_restore_user_data(
inserted_mod.id, inserted_mod.id,
inserted_person.id, inserted_person.id,
false,
&Some("a restore reason".to_string()), &Some("a restore reason".to_string()),
&context, &context,
) )

View File

@ -139,7 +139,10 @@ pub async fn create_site(
local_site_rate_limit_to_rate_limit_config(&site_view.local_site_rate_limit); local_site_rate_limit_to_rate_limit_config(&site_view.local_site_rate_limit);
context.rate_limit_cell().set_config(rate_limit_config); context.rate_limit_cell().set_config(rate_limit_config);
Ok(Json(SiteResponse { site_view })) Ok(Json(SiteResponse {
site_view,
taglines: vec![],
}))
} }
fn validate_create_payload(local_site: &LocalSite, create_site: &CreateSite) -> LemmyResult<()> { fn validate_create_payload(local_site: &LocalSite, create_site: &CreateSite) -> LemmyResult<()> {

View File

@ -59,6 +59,8 @@ pub async fn get_site(
tagline, tagline,
oauth_providers: Some(oauth_providers), oauth_providers: Some(oauth_providers),
admin_oauth_providers: Some(admin_oauth_providers), admin_oauth_providers: Some(admin_oauth_providers),
taglines: vec![],
custom_emojis: vec![],
}) })
}) })
.await .await

View File

@ -193,7 +193,10 @@ pub async fn update_site(
local_site_rate_limit_to_rate_limit_config(&site_view.local_site_rate_limit); local_site_rate_limit_to_rate_limit_config(&site_view.local_site_rate_limit);
context.rate_limit_cell().set_config(rate_limit_config); context.rate_limit_cell().set_config(rate_limit_config);
Ok(Json(SiteResponse { site_view })) Ok(Json(SiteResponse {
site_view,
taglines: vec![],
}))
} }
fn validate_update_payload(local_site: &LocalSite, edit_site: &EditSite) -> LemmyResult<()> { fn validate_update_payload(local_site: &LocalSite, edit_site: &EditSite) -> LemmyResult<()> {

View File

@ -23,7 +23,7 @@ use anyhow::anyhow;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, 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::{ use lemmy_db_schema::{
source::{ source::{
@ -174,7 +174,8 @@ impl ActivityHandler for BlockUser {
) )
.await?; .await?;
if self.remove_data.unwrap_or(false) { if self.remove_data.unwrap_or(false) {
remove_user_data(mod_person.id, blocked_person.id, &reason, context).await?; remove_or_restore_user_data(mod_person.id, blocked_person.id, true, &reason, context)
.await?;
} }
// write mod log // write mod log

View File

@ -19,7 +19,7 @@ use activitypub_federation::{
}; };
use lemmy_api_common::{ use lemmy_api_common::{
context::LemmyContext, 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::{ use lemmy_db_schema::{
source::{ source::{
@ -120,7 +120,8 @@ impl ActivityHandler for UndoBlockUser {
.await?; .await?;
if self.restore_data.unwrap_or(false) { if self.restore_data.unwrap_or(false) {
restore_user_data(mod_person.id, blocked_person.id, &None, context).await?; remove_or_restore_user_data(mod_person.id, blocked_person.id, false, &None, context)
.await?;
} }
// write mod log // write mod log

View File

@ -40,12 +40,12 @@ impl Comment {
pub async fn update_removed_for_creator( pub async fn update_removed_for_creator(
pool: &mut DbPool<'_>, pool: &mut DbPool<'_>,
for_creator_id: PersonId, for_creator_id: PersonId,
new_removed: bool, removed: bool,
) -> Result<Vec<Self>, Error> { ) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(pool).await?; let conn = &mut get_conn(pool).await?;
diesel::update(comment::table.filter(comment::creator_id.eq(for_creator_id))) diesel::update(comment::table.filter(comment::creator_id.eq(for_creator_id)))
.set(( .set((
comment::removed.eq(new_removed), comment::removed.eq(removed),
comment::updated.eq(naive_now()), comment::updated.eq(naive_now()),
)) ))
.get_results::<Self>(conn) .get_results::<Self>(conn)

View File

@ -145,7 +145,7 @@ impl Post {
pool: &mut DbPool<'_>, pool: &mut DbPool<'_>,
for_creator_id: PersonId, for_creator_id: PersonId,
for_community_id: Option<CommunityId>, for_community_id: Option<CommunityId>,
new_removed: bool, removed: bool,
) -> Result<Vec<Self>, Error> { ) -> Result<Vec<Self>, Error> {
let conn = &mut get_conn(pool).await?; let conn = &mut get_conn(pool).await?;
@ -157,7 +157,7 @@ impl Post {
} }
update 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) .get_results::<Self>(conn)
.await .await
} }

View File

@ -769,7 +769,7 @@ diesel::table! {
featured_local -> Bool, featured_local -> Bool,
url_content_type -> Nullable<Text>, url_content_type -> Nullable<Text>,
alt_text -> Nullable<Text>, alt_text -> Nullable<Text>,
scheduled_publish_time -> Nullable<Timestamptz> scheduled_publish_time -> Nullable<Timestamptz>,
} }
} }