From af3bc4f0dd143bc1de272f497fa76599ec9a3cf3 Mon Sep 17 00:00:00 2001 From: freamon Date: Mon, 21 Oct 2024 22:17:51 +0000 Subject: [PATCH] post-reply soft-deletion: activitypub restorations --- app/activitypub/routes.py | 24 ++++++++++++++++++++-- app/activitypub/util.py | 42 +++++++++++++++++++++++++++++++++------ 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/app/activitypub/routes.py b/app/activitypub/routes.py index 2cbb6e06..de0de540 100644 --- a/app/activitypub/routes.py +++ b/app/activitypub/routes.py @@ -853,8 +853,7 @@ def process_inbox_request(request_json, activitypublog_id, ip_address): post = undo_vote(activity_log, comment, post, target_ap_id, user) elif request_json['object']['object']['type'] == 'Delete': if 'object' in request_json and 'object' in request_json['object']: - restore_post_or_comment(request_json['object']['object']) - activity_log.result = 'success' + restore_post_or_comment(request_json['object']['object'], activity_log.id) elif request_json['object']['object']['type'] == 'Block': activity_log.activity_type = 'Undo User Ban' deletor_ap_id = request_json['object']['object']['actor'] @@ -1080,6 +1079,27 @@ def process_inbox_request(request_json, activitypublog_id, ip_address): if user_ap_id.startswith('https://' + current_app.config['SERVER_NAME']): unban_local_user(deletor_ap_id, user_ap_id, target) activity_log.result = 'success' + elif request_json['object']['type'] == 'Delete': # undoing a delete + activity_log.activity_type = 'Restore' + reply = PostReply.query.filter_by(ap_id=request_json['object']['object']).first() + if reply: + deletor = find_actor_or_create(request_json['object']['actor'], create_if_not_found=False) + if deletor: + if reply.author.id == deletor.id or reply.community.is_moderator(deletor) or reply.community.is_instance_admin(deletor): + reply.deleted = False + reply.deleted_by = None + if not reply.author.bot: + reply.post.reply_count += 1 + reply.author.post_reply_count += 1 + announce_activity_to_followers(reply.community, reply.author, request_json) + db.session.commit() + activity_log.result = 'success' + else: + activity_log.exception_message = 'Restore attempt denied' + else: + activity_log.exception_message = 'Restorer did not already exist' + else: + activity_log.exception_message = 'Reply not found, or object was not a reply' elif request_json['type'] == 'Delete': if isinstance(request_json['object'], str): ap_id = request_json['object'] # lemmy diff --git a/app/activitypub/util.py b/app/activitypub/util.py index 2f6cd1e6..2615cda7 100644 --- a/app/activitypub/util.py +++ b/app/activitypub/util.py @@ -1358,21 +1358,30 @@ def delete_post_or_comment_task(user_ap_id, community_ap_id, to_be_deleted_ap_id aplog.exception_message = 'Unable to resolve deletor, community, or target' -def restore_post_or_comment(object_json): +def restore_post_or_comment(object_json, aplog_id): if current_app.debug: - restore_post_or_comment_task(object_json) + restore_post_or_comment_task(object_json, aplog_id) else: - restore_post_or_comment_task.delay(object_json) + restore_post_or_comment_task.delay(object_json, aplog_id) @celery.task -def restore_post_or_comment_task(object_json): +def restore_post_or_comment_task(object_json, aplog_id): restorer = find_actor_or_create(object_json['actor']) if 'actor' in object_json else None community = find_actor_or_create(object_json['audience'], community_only=True) if 'audience' in object_json else None to_restore = find_liked_object(object_json['object']) if 'object' in object_json else None + if to_restore and not community: + community = to_restore.community + aplog = ActivityPubLog.query.get(aplog_id) + + if to_restore and not to_restore.deleted: + if aplog: + aplog.result = 'ignored' + aplog.exception_message = 'Activity about local content which is already restored' + return if restorer and community and to_restore: - if restorer.is_admin() or community.is_moderator(restorer) or community.is_instance_admin(restorer) or to_restore.author.id == restorer.id: + if to_restore.author.id == restorer.id or restorer.is_admin() or community.is_moderator(restorer) or community.is_instance_admin(restorer): if isinstance(to_restore, Post): # TODO: restore_dependencies() to_restore.deleted = False @@ -1384,7 +1393,28 @@ def restore_post_or_comment_task(object_json): add_to_modlog_activitypub('restore_post', restorer, community_id=community.id, link_text=shorten_string(to_restore.title), link=f'post/{to_restore.id}') - # TODO: if isinstance(to_restore, PostReply): + elif isinstance(to_restore, PostReply): + to_restore.deleted = False + to_restore.deleted_by = None + if not to_restore.author.bot: + to_restore.post.reply_count += 1 + to_restore.author.post_reply_count += 1 + db.session.commit() + if to_restore.author.id != restorer.id: + add_to_modlog_activitypub('restore_post_reply', restorer, community_id=community.id, + link_text=f'comment on {shorten_string(to_restore.post.title)}', + link=f'post/{to_restore.post_id}#comment_{to_restore.id}') + + if aplog: + aplog.result = 'success' + else: + if aplog: + aplog.result = 'failure' + aplog.exception_message = 'Restorer did not have permission' + else: + if aplog: + aplog.result = 'failure' + aplog.exception_message = 'Unable to resolve restorer, community, or target' def remove_data_from_banned_user(deletor_ap_id, user_ap_id, target):