federate user delete properly

This commit is contained in:
rimu 2024-02-25 15:31:16 +13:00
parent 1d4ac12528
commit 106ceba33f
4 changed files with 60 additions and 43 deletions

View file

@ -759,18 +759,33 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
else:
ap_id = request_json['object']['id'] # kbin
post = Post.query.filter_by(ap_id=ap_id).first()
# Delete post
if post:
post.delete_dependencies()
post.community.post_count -= 1
db.session.delete(post)
db.session.commit()
activity_log.result = 'success'
else:
# Delete PostReply
reply = PostReply.query.filter_by(ap_id=ap_id).first()
if reply:
reply.body_html = '<p><em>deleted</em></p>'
reply.body = 'deleted'
reply.post.reply_count -= 1
db.session.commit()
activity_log.result = 'success'
db.session.commit()
activity_log.result = 'success'
else:
# Delete User
user = find_actor_or_create(ap_id, create_if_not_found=False)
if user:
user.deleted = True
user.delete_dependencies()
db.session.commit()
activity_log.result = 'success'
else:
activity_log.exception_message = 'Delete: cannot find ' + ap_id
elif request_json['type'] == 'Like': # Upvote
activity_log.activity_type = request_json['type']
user_ap_id = request_json['actor']

View file

@ -196,7 +196,7 @@ def instance_allowed(host: str) -> bool:
return instance is not None
def find_actor_or_create(actor: str) -> Union[User, Community, None]:
def find_actor_or_create(actor: str, create_if_not_found=True) -> Union[User, Community, None]:
actor = actor.strip().lower()
user = None
# actor parameter must be formatted as https://server/u/actor or https://server/c/actor
@ -238,42 +238,43 @@ def find_actor_or_create(actor: str) -> Union[User, Community, None]:
refresh_instance_profile(user.instance_id)
return user
else: # User does not exist in the DB, it's going to need to be created from it's remote home instance
if actor.startswith('https://'):
try:
actor_data = get_request(actor, headers={'Accept': 'application/activity+json'})
except requests.exceptions.ReadTimeout:
time.sleep(randint(3, 10))
actor_data = get_request(actor, headers={'Accept': 'application/activity+json'})
if actor_data.status_code == 200:
actor_json = actor_data.json()
actor_data.close()
return actor_json_to_model(actor_json, address, server)
else:
# retrieve user details via webfinger, etc
try:
webfinger_data = get_request(f"https://{server}/.well-known/webfinger",
params={'resource': f"acct:{address}@{server}"})
except requests.exceptions.ReadTimeout:
time.sleep(randint(3, 10))
webfinger_data = get_request(f"https://{server}/.well-known/webfinger",
params={'resource': f"acct:{address}@{server}"})
if webfinger_data.status_code == 200:
webfinger_json = webfinger_data.json()
webfinger_data.close()
for links in webfinger_json['links']:
if 'rel' in links and links['rel'] == 'self': # this contains the URL of the activitypub profile
type = links['type'] if 'type' in links else 'application/activity+json'
# retrieve the activitypub profile
try:
actor_data = get_request(links['href'], headers={'Accept': type})
except requests.exceptions.ReadTimeout:
time.sleep(randint(3, 10))
actor_data = get_request(links['href'], headers={'Accept': type})
# to see the structure of the json contained in actor_data, do a GET to https://lemmy.world/c/technology with header Accept: application/activity+json
if actor_data.status_code == 200:
actor_json = actor_data.json()
actor_data.close()
return actor_json_to_model(actor_json, address, server)
if create_if_not_found:
if actor.startswith('https://'):
try:
actor_data = get_request(actor, headers={'Accept': 'application/activity+json'})
except requests.exceptions.ReadTimeout:
time.sleep(randint(3, 10))
actor_data = get_request(actor, headers={'Accept': 'application/activity+json'})
if actor_data.status_code == 200:
actor_json = actor_data.json()
actor_data.close()
return actor_json_to_model(actor_json, address, server)
else:
# retrieve user details via webfinger, etc
try:
webfinger_data = get_request(f"https://{server}/.well-known/webfinger",
params={'resource': f"acct:{address}@{server}"})
except requests.exceptions.ReadTimeout:
time.sleep(randint(3, 10))
webfinger_data = get_request(f"https://{server}/.well-known/webfinger",
params={'resource': f"acct:{address}@{server}"})
if webfinger_data.status_code == 200:
webfinger_json = webfinger_data.json()
webfinger_data.close()
for links in webfinger_json['links']:
if 'rel' in links and links['rel'] == 'self': # this contains the URL of the activitypub profile
type = links['type'] if 'type' in links else 'application/activity+json'
# retrieve the activitypub profile
try:
actor_data = get_request(links['href'], headers={'Accept': type})
except requests.exceptions.ReadTimeout:
time.sleep(randint(3, 10))
actor_data = get_request(links['href'], headers={'Accept': type})
# to see the structure of the json contained in actor_data, do a GET to https://lemmy.world/c/technology with header Accept: application/activity+json
if actor_data.status_code == 200:
actor_json = actor_data.json()
actor_data.close()
return actor_json_to_model(actor_json, address, server)
return None
@ -732,6 +733,8 @@ def refresh_instance_profile_task(instance_id: int):
software = 'Kbin'
elif instance_json['name'].lower() == 'mbin':
software = 'Mbin'
elif instance_json['name'].lower() == 'piefed':
software = 'PieFed'
else:
software = 'Lemmy'
instance.inbox = instance_json['inbox']

View file

@ -463,13 +463,13 @@ def ban_purge_profile(actor):
# federate deletion
if user.is_local():
purge_user_then_delete(user.id)
flash(f'{actor} has been banned, deleted and all their content deleted. This might take a few minutes.')
else:
user.deleted = True
user.delete_dependencies()
user.purge_content()
db.session.commit()
flash(f'{actor} has been banned, deleted and all their content deleted.')
flash(f'{actor} has been banned, deleted and all their content deleted.')
else:
abort(401)

View file

@ -82,8 +82,7 @@ def purge_user_then_delete_task(user_id):
}
for instance in instances:
if instance.inbox and instance.id != 1:
post_request(instance.inbox, payload, site.private_key,
f"https://{current_app.config['SERVER_NAME']}#main-key")
post_request(instance.inbox, payload, user.private_key, user.ap_profile_id + '#main-key')
sleep(100) # wait a while for any related activitypub traffic to die down.
user.deleted = True