Try to implement federated user deletion (fixes #1284)

This commit is contained in:
Felix Ableitner 2020-11-27 17:46:46 +01:00
parent c986f5961c
commit c2adaea5c1
2 changed files with 40 additions and 4 deletions

View file

@ -13,7 +13,7 @@ use anyhow::Context;
use bcrypt::verify; use bcrypt::verify;
use captcha::{gen, Difficulty}; use captcha::{gen, Difficulty};
use chrono::Duration; use chrono::Duration;
use lemmy_apub::ApubObjectType; use lemmy_apub::{ActorType, ApubObjectType};
use lemmy_db::{ use lemmy_db::{
comment::*, comment::*,
comment_report::CommentReportView, comment_report::CommentReportView,
@ -877,6 +877,9 @@ impl Perform for DeleteAccount {
return Err(APIError::err("password_incorrect").into()); return Err(APIError::err("password_incorrect").into());
} }
// Send activity to delete user on federated instances
user.send_delete(context).await?;
// Comments // Comments
let user_id = user.id; let user_id = user.id;
let permadelete = move |conn: &'_ _| Comment::permadelete_for_creator(conn, user_id); let permadelete = move |conn: &'_ _| Comment::permadelete_for_creator(conn, user_id);

View file

@ -5,13 +5,16 @@ use crate::{
}; };
use activitystreams::{ use activitystreams::{
activity::{ activity::{
kind::{FollowType, UndoType}, kind::{DeleteType, FollowType, UndoType},
Delete,
Follow, Follow,
Undo, Undo,
}, },
base::{AnyBase, BaseExt, ExtendsExt}, base::{AnyBase, BaseExt, ExtendsExt},
object::ObjectExt, object::ObjectExt,
public,
}; };
use itertools::Itertools;
use lemmy_db::{ use lemmy_db::{
community::{Community, CommunityFollower, CommunityFollowerForm}, community::{Community, CommunityFollower, CommunityFollowerForm},
user::User_, user::User_,
@ -105,8 +108,38 @@ impl ActorType for User_ {
unimplemented!() unimplemented!()
} }
async fn send_delete(&self, _context: &LemmyContext) -> Result<(), LemmyError> { /// The user has deleted their account
unimplemented!() async fn send_delete(&self, context: &LemmyContext) -> Result<(), LemmyError> {
let mut delete = Delete::new(self.actor_id()?, self.actor_id()?);
delete
.set_context(activitystreams::context())
.set_id(generate_activity_id(DeleteType::Delete)?)
.set_to(public())
// TODO: who is `cc`? all the communities the user has posted to? our inbox code can only
// handle activities for one activity. sending separate activities would work, but
// would also create a lot of traffic.
.set_many_ccs(vec![self.get_followers_url()?]);
// TODO: should directly get distinct shared_inboxes from federated communites from db
// (once we store that)
let distinct_communities = blocking(context.pool(), move |conn| {
Community::distinct_federated_communities(conn)
})
.await??;
let shared_inboxes = distinct_communities
.iter()
.map(|actor_id| Url::parse(actor_id).ok())
.flatten()
.map(|url| url.host_str().map(|u| u.to_string()))
.flatten()
.unique()
.map(|c| format!("{}/inbox", c))
.collect::<Vec<String>>();
// TODO: maybe we should add a separate function `send_activity_multi_dest()`
for s in &shared_inboxes {
send_activity_single_dest(delete.to_owned(), self, Url::parse(s)?, context).await?;
}
Ok(())
} }
async fn send_undo_delete(&self, _context: &LemmyContext) -> Result<(), LemmyError> { async fn send_undo_delete(&self, _context: &LemmyContext) -> Result<(), LemmyError> {