Skip to content

Commit 2fcbb07

Browse files
committed
remove unnecessary pictrs purge calls
This commit removes various cases in which Lemmy would purge images from pictrs, which would in many cases not be what admins intended. pict-rs provides aliases on upload, which allows deduplicating multiple uploads of the same file in the backend, while still providing unique URLs for uploads. As Lemmy used pictrs' purge API, this meant that not only the image alias referring to removed content was deleted, all other aliases were invalidated as well. Additionally, even alias deletion would not appropriate in many of these cases, as they were lacking validation that they were exclusively used by the content they were supposed to get removed with. This implements the following changes: 1. Purging a community no longer purges the community banner or icon from pict-rs. 2. Purging a community no longer purges all images referenced in post URLs and post thumbnails within the community from pict-rs. 3. Banning a user with content removal no longer purges their profile avatar or banner from pict-rs. 4. Banning a user with content removal no longer purges images referenced in post URLs and post thumbnails for all posts they created from pict-rs. 5. Banning a user with content removal no longer purges the community banners or icons for all communities they're the top mod of from pict-rs. 6. Banning a user with content removal now deletes all media they uploaded. 7. Purging a user no longer purges their profile avatar, banner, or images referenced in post URLs and post thumbnails for all posts they created from pict-rs. All media linked to their user account will still get deleted, which was already explicitly the case in the past. Some of the mentioned actions will still remove references to image URLs from the database, such as purging a community will still set its icon and banner to `NULL` in the db, but the associated images will no longer be purged from pict-rs. As this stops erasure of thumbnails, #5564 has been created to ensure tracking the person that triggered the creation of thumbnails, which will allow removing them like other images. The only remaining option to purge images attached to a post is now purging an individual post, which still erases the post URL and thumbnail from pict-rs entirely, including any other aliases. Purging and banning users with content removal will remove all aliases associated with them, which will end up deleting those images entirely when there are no other alias remaining. backports #5565 to 0.19 #5565 988638d
1 parent ee222d7 commit 2fcbb07

File tree

3 files changed

+5
-168
lines changed

3 files changed

+5
-168
lines changed

crates/api/src/site/purge/community.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,9 @@ use activitypub_federation::config::Data;
22
use actix_web::web::Json;
33
use lemmy_api_common::{
44
context::LemmyContext,
5-
request::purge_image_from_pictrs,
65
send_activity::{ActivityChannel, SendActivityData},
76
site::PurgeCommunity,
8-
utils::{is_admin, purge_image_posts_for_community},
7+
utils::is_admin,
98
SuccessResponse,
109
};
1110
use lemmy_db_schema::{
@@ -50,16 +49,6 @@ pub async fn purge_community(
5049
)
5150
.await?;
5251

53-
if let Some(banner) = &community.banner {
54-
purge_image_from_pictrs(banner, &context).await.ok();
55-
}
56-
57-
if let Some(icon) = &community.icon {
58-
purge_image_from_pictrs(icon, &context).await.ok();
59-
}
60-
61-
purge_image_posts_for_community(data.community_id, &context).await?;
62-
6352
Community::delete(&mut context.pool(), data.community_id).await?;
6453

6554
// Mod tables

crates/api_common/src/utils.rs

Lines changed: 3 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
use crate::{
22
context::LemmyContext,
3-
request::{
4-
delete_image_from_pictrs,
5-
fetch_pictrs_proxied_image_details,
6-
purge_image_from_pictrs,
7-
},
3+
request::{delete_image_from_pictrs, fetch_pictrs_proxied_image_details},
84
site::{FederatedInstances, InstanceWithFederationState},
95
};
106
use chrono::{DateTime, Days, Local, TimeZone, Utc};
@@ -628,26 +624,6 @@ pub async fn read_site_for_actor(
628624
Ok(site)
629625
}
630626

631-
pub async fn purge_image_posts_for_person(
632-
banned_person_id: PersonId,
633-
context: &LemmyContext,
634-
) -> LemmyResult<()> {
635-
let pool = &mut context.pool();
636-
let posts = Post::fetch_pictrs_posts_for_creator(pool, banned_person_id).await?;
637-
for post in posts {
638-
if let Some(url) = post.url {
639-
purge_image_from_pictrs(&url, context).await.ok();
640-
}
641-
if let Some(thumbnail_url) = post.thumbnail_url {
642-
purge_image_from_pictrs(&thumbnail_url, context).await.ok();
643-
}
644-
}
645-
646-
Post::remove_pictrs_post_images_and_thumbnails_for_creator(pool, banned_person_id).await?;
647-
648-
Ok(())
649-
}
650-
651627
/// Delete a local_user's images
652628
async fn delete_local_user_images(person_id: PersonId, context: &LemmyContext) -> LemmyResult<()> {
653629
if let Ok(Some(local_user)) = LocalUserView::read_person(&mut context.pool(), person_id).await {
@@ -669,41 +645,11 @@ async fn delete_local_user_images(person_id: PersonId, context: &LemmyContext) -
669645
Ok(())
670646
}
671647

672-
pub async fn purge_image_posts_for_community(
673-
banned_community_id: CommunityId,
674-
context: &LemmyContext,
675-
) -> LemmyResult<()> {
676-
let pool = &mut context.pool();
677-
let posts = Post::fetch_pictrs_posts_for_community(pool, banned_community_id).await?;
678-
for post in posts {
679-
if let Some(url) = post.url {
680-
purge_image_from_pictrs(&url, context).await.ok();
681-
}
682-
if let Some(thumbnail_url) = post.thumbnail_url {
683-
purge_image_from_pictrs(&thumbnail_url, context).await.ok();
684-
}
685-
}
686-
687-
Post::remove_pictrs_post_images_and_thumbnails_for_community(pool, banned_community_id).await?;
688-
689-
Ok(())
690-
}
691-
692648
pub async fn remove_user_data(
693649
banned_person_id: PersonId,
694650
context: &LemmyContext,
695651
) -> LemmyResult<()> {
696652
let pool = &mut context.pool();
697-
// Purge user images
698-
let person = Person::read(pool, banned_person_id)
699-
.await?
700-
.ok_or(LemmyErrorType::CouldntFindPerson)?;
701-
if let Some(avatar) = person.avatar {
702-
purge_image_from_pictrs(&avatar, context).await.ok();
703-
}
704-
if let Some(banner) = person.banner {
705-
purge_image_from_pictrs(&banner, context).await.ok();
706-
}
707653

708654
// Update the fields to None
709655
Person::update(
@@ -721,8 +667,7 @@ pub async fn remove_user_data(
721667
// Posts
722668
Post::update_removed_for_creator(pool, banned_person_id, None, true).await?;
723669

724-
// Purge image posts
725-
purge_image_posts_for_person(banned_person_id, context).await?;
670+
delete_local_user_images(banned_person_id, context).await?;
726671

727672
// Communities
728673
// Remove all communities where they're the top mod
@@ -747,13 +692,6 @@ pub async fn remove_user_data(
747692
)
748693
.await?;
749694

750-
// Delete the community images
751-
if let Some(icon) = first_mod_community.community.icon {
752-
purge_image_from_pictrs(&icon, context).await.ok();
753-
}
754-
if let Some(banner) = first_mod_community.community.banner {
755-
purge_image_from_pictrs(&banner, context).await.ok();
756-
}
757695
// Update the fields to None
758696
Community::update(
759697
pool,
@@ -813,23 +751,9 @@ pub async fn remove_user_data_in_community(
813751
pub async fn purge_user_account(person_id: PersonId, context: &LemmyContext) -> LemmyResult<()> {
814752
let pool = &mut context.pool();
815753

816-
let person = Person::read(pool, person_id)
817-
.await?
818-
.ok_or(LemmyErrorType::CouldntFindPerson)?;
819-
820754
// Delete their local images, if they're a local user
821-
delete_local_user_images(person_id, context).await.ok();
822-
823755
// No need to update avatar and banner, those are handled in Person::delete_account
824-
if let Some(avatar) = person.avatar {
825-
purge_image_from_pictrs(&avatar, context).await.ok();
826-
}
827-
if let Some(banner) = person.banner {
828-
purge_image_from_pictrs(&banner, context).await.ok();
829-
}
830-
831-
// Purge image posts
832-
purge_image_posts_for_person(person_id, context).await.ok();
756+
delete_local_user_images(person_id, context).await.ok();
833757

834758
// Comments
835759
Comment::permadelete_for_creator(pool, person_id)

crates/db_schema/src/impls/post.rs

Lines changed: 1 addition & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,7 @@ use crate::{
2929
};
3030
use ::url::Url;
3131
use chrono::{DateTime, Utc};
32-
use diesel::{
33-
dsl::insert_into,
34-
result::Error,
35-
DecoratableTarget,
36-
ExpressionMethods,
37-
QueryDsl,
38-
TextExpressionMethods,
39-
};
32+
use diesel::{dsl::insert_into, result::Error, DecoratableTarget, ExpressionMethods, QueryDsl};
4033
use diesel_async::RunQueryDsl;
4134
use std::collections::HashSet;
4235

@@ -173,75 +166,6 @@ impl Post {
173166
.await
174167
.optional()
175168
}
176-
177-
pub async fn fetch_pictrs_posts_for_creator(
178-
pool: &mut DbPool<'_>,
179-
for_creator_id: PersonId,
180-
) -> Result<Vec<Self>, Error> {
181-
let conn = &mut get_conn(pool).await?;
182-
let pictrs_search = "%pictrs/image%";
183-
184-
post::table
185-
.filter(post::creator_id.eq(for_creator_id))
186-
.filter(post::url.like(pictrs_search))
187-
.load::<Self>(conn)
188-
.await
189-
}
190-
191-
/// Sets the url and thumbnails fields to None
192-
pub async fn remove_pictrs_post_images_and_thumbnails_for_creator(
193-
pool: &mut DbPool<'_>,
194-
for_creator_id: PersonId,
195-
) -> Result<Vec<Self>, Error> {
196-
let conn = &mut get_conn(pool).await?;
197-
let pictrs_search = "%pictrs/image%";
198-
199-
diesel::update(
200-
post::table
201-
.filter(post::creator_id.eq(for_creator_id))
202-
.filter(post::url.like(pictrs_search)),
203-
)
204-
.set((
205-
post::url.eq::<Option<String>>(None),
206-
post::thumbnail_url.eq::<Option<String>>(None),
207-
))
208-
.get_results::<Self>(conn)
209-
.await
210-
}
211-
212-
pub async fn fetch_pictrs_posts_for_community(
213-
pool: &mut DbPool<'_>,
214-
for_community_id: CommunityId,
215-
) -> Result<Vec<Self>, Error> {
216-
let conn = &mut get_conn(pool).await?;
217-
let pictrs_search = "%pictrs/image%";
218-
post::table
219-
.filter(post::community_id.eq(for_community_id))
220-
.filter(post::url.like(pictrs_search))
221-
.load::<Self>(conn)
222-
.await
223-
}
224-
225-
/// Sets the url and thumbnails fields to None
226-
pub async fn remove_pictrs_post_images_and_thumbnails_for_community(
227-
pool: &mut DbPool<'_>,
228-
for_community_id: CommunityId,
229-
) -> Result<Vec<Self>, Error> {
230-
let conn = &mut get_conn(pool).await?;
231-
let pictrs_search = "%pictrs/image%";
232-
233-
diesel::update(
234-
post::table
235-
.filter(post::community_id.eq(for_community_id))
236-
.filter(post::url.like(pictrs_search)),
237-
)
238-
.set((
239-
post::url.eq::<Option<String>>(None),
240-
post::thumbnail_url.eq::<Option<String>>(None),
241-
))
242-
.get_results::<Self>(conn)
243-
.await
244-
}
245169
}
246170

247171
#[async_trait]

0 commit comments

Comments
 (0)