mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-23 19:36:56 -08:00
post soft-deletion: add options to restore or purge deleted posts
This commit is contained in:
parent
9a033522d1
commit
502e6ff0f6
4 changed files with 90 additions and 38 deletions
|
@ -619,6 +619,7 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
|
|||
post = create_post(activity_log, community, request_json, user)
|
||||
if post:
|
||||
announce_activity_to_followers(community, user, request_json)
|
||||
activity_log.result = 'success'
|
||||
except TypeError as e:
|
||||
activity_log.exception_message = 'TypeError. See log file.'
|
||||
current_app.logger.error('TypeError: ' + str(request_json))
|
||||
|
@ -1081,17 +1082,16 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
|
|||
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:
|
||||
post = Post.query.filter_by(ap_id=request_json['object']['object']).first()
|
||||
if post:
|
||||
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)
|
||||
if post.author.id == deletor.id or post.community.is_moderator(deletor) or post.community.is_instance_admin(deletor):
|
||||
post.deleted = False
|
||||
post.deleted_by = None
|
||||
post.author.post_count += 1
|
||||
post.community.post_count += 1
|
||||
announce_activity_to_followers(post.community, post.author, request_json)
|
||||
db.session.commit()
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
|
@ -1099,7 +1099,25 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
|
|||
else:
|
||||
activity_log.exception_message = 'Restorer did not already exist'
|
||||
else:
|
||||
activity_log.exception_message = 'Reply not found, or object was not a reply'
|
||||
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 = 'Object not found, or object was not a post or a reply'
|
||||
elif request_json['type'] == 'Delete':
|
||||
if isinstance(request_json['object'], str):
|
||||
ap_id = request_json['object'] # lemmy
|
||||
|
|
|
@ -1381,7 +1381,6 @@ def restore_post_or_comment_task(object_json, aplog_id):
|
|||
if restorer and community and to_restore:
|
||||
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
|
||||
to_restore.deleted_by = None
|
||||
community.post_count += 1
|
||||
|
|
|
@ -670,9 +670,13 @@ def add_reply(post_id: int, comment_id: int):
|
|||
@bp.route('/post/<int:post_id>/options', methods=['GET'])
|
||||
def post_options(post_id: int):
|
||||
post = Post.query.get_or_404(post_id)
|
||||
if current_user.is_anonymous or not current_user.is_admin():
|
||||
if post.deleted:
|
||||
if post.deleted:
|
||||
if current_user.is_anonymous:
|
||||
abort(404)
|
||||
if (not post.community.is_moderator() and
|
||||
not current_user.is_admin() and
|
||||
(post.deleted_by is not None and post.deleted_by != current_user.id)):
|
||||
abort(401)
|
||||
|
||||
existing_bookmark = []
|
||||
if current_user.is_authenticated:
|
||||
|
@ -1092,14 +1096,19 @@ def post_delete_post(community: Community, post: Post, user_id: int, federate_al
|
|||
@login_required
|
||||
def post_restore(post_id: int):
|
||||
post = Post.query.get_or_404(post_id)
|
||||
if post.community.is_moderator() or post.community.is_owner() or current_user.is_admin():
|
||||
if post.user_id == current_user.id or post.community.is_moderator() or post.community.is_owner() or current_user.is_admin():
|
||||
if post.deleted_by == post.user_id:
|
||||
was_mod_deletion = False
|
||||
else:
|
||||
was_mod_deletion = True
|
||||
post.deleted = False
|
||||
post.deleted_by = None
|
||||
post.author.post_count += 1
|
||||
post.community.post_count += 1
|
||||
db.session.commit()
|
||||
|
||||
# Federate un-delete
|
||||
if post.is_local():
|
||||
if not post.community.local_only:
|
||||
delete_json = {
|
||||
"actor": current_user.public_url(),
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
|
@ -1115,31 +1124,40 @@ def post_restore(post_id: int):
|
|||
],
|
||||
'object': post.ap_id,
|
||||
'uri': post.ap_id,
|
||||
"summary": "bad post",
|
||||
},
|
||||
"cc": [post.community.public_url()],
|
||||
"audience": post.author.public_url(),
|
||||
"audience": post.community.public_url(),
|
||||
"type": "Undo",
|
||||
"id": f"https://{current_app.config['SERVER_NAME']}/activities/undo/{gibberish(15)}"
|
||||
}
|
||||
if was_mod_deletion:
|
||||
delete_json['object']['summary'] = "Deleted by mod"
|
||||
|
||||
announce = {
|
||||
"id": f"https://{current_app.config['SERVER_NAME']}/activities/announce/{gibberish(15)}",
|
||||
"type": 'Announce',
|
||||
"to": [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"actor": post.community.public_url(),
|
||||
"cc": [
|
||||
post.community.ap_followers_url
|
||||
],
|
||||
'@context': default_context(),
|
||||
'object': delete_json
|
||||
}
|
||||
if not post.community.is_local(): # this is a remote community, send it to the instance that hosts it
|
||||
if not was_mod_deletion or (was_mod_deletion and post.community.is_moderator(current_user)):
|
||||
success = post_request(post.community.ap_inbox_url, delete_json, current_user.private_key,
|
||||
current_user.public_url() + '#main-key')
|
||||
if success is False or isinstance(success, str):
|
||||
flash('Failed to send delete to remote server', 'error')
|
||||
|
||||
for instance in post.community.following_instances():
|
||||
if instance.inbox and not current_user.has_blocked_instance(instance.id) and not instance_banned(instance.domain):
|
||||
send_to_remote_instance(instance.id, post.community.id, announce)
|
||||
else: # local community - send it to followers on remote instances
|
||||
announce = {
|
||||
"id": f"https://{current_app.config['SERVER_NAME']}/activities/announce/{gibberish(15)}",
|
||||
"type": 'Announce',
|
||||
"to": [
|
||||
"https://www.w3.org/ns/activitystreams#Public"
|
||||
],
|
||||
"actor": post.community.public_url(),
|
||||
"cc": [
|
||||
post.community.ap_followers_url
|
||||
],
|
||||
'@context': default_context(),
|
||||
'object': delete_json
|
||||
}
|
||||
|
||||
for instance in post.community.following_instances():
|
||||
if instance.inbox and not current_user.has_blocked_instance(instance.id) and not instance_banned(instance.domain):
|
||||
send_to_remote_instance(instance.id, post.community.id, announce)
|
||||
|
||||
if post.user_id != current_user.id:
|
||||
add_to_modlog('restore_post', community_id=post.community.id, link_text=shorten_string(post.title),
|
||||
|
@ -1149,6 +1167,23 @@ def post_restore(post_id: int):
|
|||
return redirect(url_for('activitypub.post_ap', post_id=post.id))
|
||||
|
||||
|
||||
@bp.route('/post/<int:post_id>/purge', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def post_purge(post_id: int):
|
||||
post = Post.query.get_or_404(post_id)
|
||||
if not post.deleted:
|
||||
abort(404)
|
||||
if post.deleted_by == current_user.id or post.community.is_moderator() or current_user.is_admin():
|
||||
post.delete_dependencies()
|
||||
db.session.delete(post)
|
||||
db.session.commit()
|
||||
flash(_('Post purged.'))
|
||||
else:
|
||||
abort(401)
|
||||
|
||||
return redirect(url_for('user.show_profile_by_id', user_id=post.user_id))
|
||||
|
||||
|
||||
@bp.route('/post/<int:post_id>/bookmark', methods=['GET', 'POST'])
|
||||
@login_required
|
||||
def post_bookmark(post_id: int):
|
||||
|
@ -1749,9 +1784,7 @@ def post_reply_purge(post_id: int, comment_id: int):
|
|||
post_reply = PostReply.query.get_or_404(comment_id)
|
||||
if not post_reply.deleted:
|
||||
abort(404)
|
||||
if post_reply.user_id == current_user.id and (post_reply.deleted_by is None or post_reply.deleted_by != post_reply.user_id):
|
||||
abort(401)
|
||||
if post_reply.user_id == current_user.id or post.community.is_moderator() or current_user.is_admin():
|
||||
if post_reply.deleted_by == current_user.id or post.community.is_moderator() or current_user.is_admin():
|
||||
if not post_reply.has_replies():
|
||||
post_reply.delete_dependencies()
|
||||
db.session.delete(post_reply)
|
||||
|
|
|
@ -19,8 +19,10 @@
|
|||
{% endif -%}
|
||||
{% if post.user_id == current_user.id or post.community.is_moderator() or post.community.is_owner() or current_user.is_admin() -%}
|
||||
{% if post.deleted -%}
|
||||
<li><a href="{{ url_for('post.post_restore', post_id=post.id) }}" class="no-underline confirm_first" rel="nofollow"><span class="fe fe-delete"></span>
|
||||
<li><a href="{{ url_for('post.post_restore', post_id=post.id) }}" class="no-underline confirm_first" rel="nofollow"><span class="fe fe-arrow-up"></span>
|
||||
{{ _('Restore') }}</a></li>
|
||||
<li><a href="{{ url_for('post.post_purge', post_id=post.id) }}" class="no-underline confirm_first" rel="nofollow"><span class="fe fe-delete red"></span>
|
||||
{{ _('Purge') }}</a></li>
|
||||
{% else -%}
|
||||
<li><a href="{{ url_for('post.post_delete', post_id=post.id) }}" class="no-underline confirm_first" rel="nofollow"><span class="fe fe-delete"></span>
|
||||
{{ _('Delete') }}</a></li>
|
||||
|
|
Loading…
Add table
Reference in a new issue