Merge pull request 'add more info to the modlog' (#367) from h3ndrik/pyfedi:mod4 into main

Reviewed-on: https://codeberg.org/rimu/pyfedi/pulls/367
This commit is contained in:
rimu 2024-12-05 00:50:44 +00:00
commit 4fe3778008
4 changed files with 73 additions and 66 deletions

View file

@ -24,12 +24,12 @@ from app.activitypub.util import public_key, users_total, active_half_year, acti
user_removed_from_remote_server, create_post, create_post_reply, update_post_reply_from_activity, \ user_removed_from_remote_server, create_post, create_post_reply, update_post_reply_from_activity, \
update_post_from_activity, undo_vote, undo_downvote, post_to_page, get_redis_connection, find_reported_object, \ update_post_from_activity, undo_vote, undo_downvote, post_to_page, get_redis_connection, find_reported_object, \
process_report, ensure_domains_match, can_edit, can_delete, remove_data_from_banned_user, resolve_remote_post, \ process_report, ensure_domains_match, can_edit, can_delete, remove_data_from_banned_user, resolve_remote_post, \
inform_followers_of_post_update, comment_model_to_json, restore_post_or_comment, ban_local_user, unban_local_user, \ inform_followers_of_post_update, comment_model_to_json, restore_post_or_comment, ban_user, unban_user, \
lock_post, log_incoming_ap, find_community_ap_id, site_ban_remove_data, community_ban_remove_data log_incoming_ap, find_community_ap_id, site_ban_remove_data, community_ban_remove_data
from app.utils import gibberish, get_setting, render_template, \ from app.utils import gibberish, get_setting, render_template, \
community_membership, ap_datetime, ip_address, can_downvote, \ community_membership, ap_datetime, ip_address, can_downvote, \
can_upvote, can_create_post, awaken_dormant_instance, shorten_string, can_create_post_reply, sha256_digest, \ can_upvote, can_create_post, awaken_dormant_instance, shorten_string, can_create_post_reply, sha256_digest, \
community_moderators, markdown_to_html, html_to_text community_moderators, markdown_to_html, html_to_text, add_to_modlog_activitypub
@bp.route('/testredis') @bp.route('/testredis')
@ -1094,10 +1094,14 @@ def process_inbox_request(request_json, store_ap_json):
mod = user mod = user
post_id = request_json['object']['object'] post_id = request_json['object']['object']
post = Post.query.filter_by(ap_id=post_id).first() post = Post.query.filter_by(ap_id=post_id).first()
reason = request_json['object']['summary'] if 'summary' in request_json['object'] else ''
if post: if post:
if post.community.is_moderator(mod) or post.community.is_instance_admin(mod): if post.community.is_moderator(mod) or post.community.is_instance_admin(mod):
post.comments_enabled = False post.comments_enabled = False
db.session.commit() db.session.commit()
add_to_modlog_activitypub('lock_post', mod, community_id=post.community.id,
link_text=shorten_string(post.title), link=f'post/{post.id}',
reason=reason)
log_incoming_ap(id, APLOG_LOCK, APLOG_SUCCESS, request_json if store_ap_json else None) log_incoming_ap(id, APLOG_LOCK, APLOG_SUCCESS, request_json if store_ap_json else None)
else: else:
log_incoming_ap(id, APLOG_LOCK, APLOG_FAILURE, request_json if store_ap_json else None, 'Lock: Does not have permission') log_incoming_ap(id, APLOG_LOCK, APLOG_FAILURE, request_json if store_ap_json else None, 'Lock: Does not have permission')
@ -1181,8 +1185,7 @@ def process_inbox_request(request_json, store_ap_json):
else: else:
log_incoming_ap(id, APLOG_USERBAN, APLOG_IGNORED, request_json if store_ap_json else None, 'Banned, but content retained') log_incoming_ap(id, APLOG_USERBAN, APLOG_IGNORED, request_json if store_ap_json else None, 'Banned, but content retained')
if blocked.is_local(): ban_user(blocker, blocked, community, request_json)
ban_local_user(blocker, blocked, community, request_json)
return return
if request_json['object']['type'] == 'Undo': if request_json['object']['type'] == 'Undo':
@ -1217,10 +1220,14 @@ def process_inbox_request(request_json, store_ap_json):
mod = user mod = user
post_id = request_json['object']['object']['object'] post_id = request_json['object']['object']['object']
post = Post.query.filter_by(ap_id=post_id).first() post = Post.query.filter_by(ap_id=post_id).first()
reason = request_json['object']['summary'] if 'summary' in request_json['object'] else ''
if post: if post:
if post.community.is_moderator(mod) or post.community.is_instance_admin(mod): if post.community.is_moderator(mod) or post.community.is_instance_admin(mod):
post.comments_enabled = True post.comments_enabled = True
db.session.commit() db.session.commit()
add_to_modlog_activitypub('unlock_post', mod, community_id=post.community.id,
link_text=shorten_string(post.title), link=f'post/{post.id}',
reason=reason)
log_incoming_ap(id, APLOG_LOCK, APLOG_SUCCESS, request_json if store_ap_json else None) log_incoming_ap(id, APLOG_LOCK, APLOG_SUCCESS, request_json if store_ap_json else None)
else: else:
log_incoming_ap(id, APLOG_LOCK, APLOG_FAILURE, request_json if store_ap_json else None, 'Lock: Does not have permission') log_incoming_ap(id, APLOG_LOCK, APLOG_FAILURE, request_json if store_ap_json else None, 'Lock: Does not have permission')
@ -1240,8 +1247,7 @@ def process_inbox_request(request_json, store_ap_json):
log_incoming_ap(id, APLOG_USERBAN, APLOG_FAILURE, request_json if store_ap_json else None, 'Does not have permission') log_incoming_ap(id, APLOG_USERBAN, APLOG_FAILURE, request_json if store_ap_json else None, 'Does not have permission')
return return
if blocked.is_local(): unban_user(blocker, blocked, community, request_json)
unban_local_user(blocker, blocked, community, request_json)
log_incoming_ap(id, APLOG_USERBAN, APLOG_SUCCESS, request_json if store_ap_json else None) log_incoming_ap(id, APLOG_USERBAN, APLOG_SUCCESS, request_json if store_ap_json else None)
return return

View file

@ -1343,6 +1343,7 @@ def is_activitypub_request():
def delete_post_or_comment(deletor, to_delete, store_ap_json, request_json): def delete_post_or_comment(deletor, to_delete, store_ap_json, request_json):
id = request_json['id'] id = request_json['id']
community = to_delete.community community = to_delete.community
reason = request_json['object']['summary'] if 'summary' in request_json['object'] else ''
if to_delete.user_id == deletor.id or deletor.is_admin() or community.is_moderator(deletor) or community.is_instance_admin(deletor): if to_delete.user_id == deletor.id or deletor.is_admin() or community.is_moderator(deletor) or community.is_instance_admin(deletor):
if isinstance(to_delete, Post): if isinstance(to_delete, Post):
to_delete.deleted = True to_delete.deleted = True
@ -1358,7 +1359,8 @@ def delete_post_or_comment(deletor, to_delete, store_ap_json, request_json):
db.session.commit() db.session.commit()
if to_delete.author.id != deletor.id: if to_delete.author.id != deletor.id:
add_to_modlog_activitypub('delete_post', deletor, community_id=community.id, add_to_modlog_activitypub('delete_post', deletor, community_id=community.id,
link_text=shorten_string(to_delete.title), link=f'post/{to_delete.id}') link_text=shorten_string(to_delete.title), link=f'post/{to_delete.id}',
reason=reason)
elif isinstance(to_delete, PostReply): elif isinstance(to_delete, PostReply):
to_delete.deleted = True to_delete.deleted = True
to_delete.deleted_by = deletor.id to_delete.deleted_by = deletor.id
@ -1370,7 +1372,8 @@ def delete_post_or_comment(deletor, to_delete, store_ap_json, request_json):
if to_delete.author.id != deletor.id: if to_delete.author.id != deletor.id:
add_to_modlog_activitypub('delete_post_reply', deletor, community_id=community.id, add_to_modlog_activitypub('delete_post_reply', deletor, community_id=community.id,
link_text=f'comment on {shorten_string(to_delete.post.title)}', link_text=f'comment on {shorten_string(to_delete.post.title)}',
link=f'post/{to_delete.post.id}#comment_{to_delete.id}') link=f'post/{to_delete.post.id}#comment_{to_delete.id}',
reason=reason)
log_incoming_ap(id, APLOG_DELETE, APLOG_SUCCESS, request_json if store_ap_json else None) log_incoming_ap(id, APLOG_DELETE, APLOG_SUCCESS, request_json if store_ap_json else None)
else: else:
log_incoming_ap(id, APLOG_DELETE, APLOG_FAILURE, request_json if store_ap_json else None, 'Deletor did not have permisson') log_incoming_ap(id, APLOG_DELETE, APLOG_FAILURE, request_json if store_ap_json else None, 'Deletor did not have permisson')
@ -1379,6 +1382,7 @@ def delete_post_or_comment(deletor, to_delete, store_ap_json, request_json):
def restore_post_or_comment(restorer, to_restore, store_ap_json, request_json): def restore_post_or_comment(restorer, to_restore, store_ap_json, request_json):
id = request_json['id'] id = request_json['id']
community = to_restore.community community = to_restore.community
reason = request_json['object']['summary'] if 'summary' in request_json['object'] else ''
if to_restore.user_id == restorer.id or restorer.is_admin() or community.is_moderator(restorer) or community.is_instance_admin(restorer): if to_restore.user_id == restorer.id or restorer.is_admin() or community.is_moderator(restorer) or community.is_instance_admin(restorer):
if isinstance(to_restore, Post): if isinstance(to_restore, Post):
to_restore.deleted = False to_restore.deleted = False
@ -1400,7 +1404,8 @@ def restore_post_or_comment(restorer, to_restore, store_ap_json, request_json):
db.session.commit() db.session.commit()
if to_restore.author.id != restorer.id: if to_restore.author.id != restorer.id:
add_to_modlog_activitypub('restore_post', restorer, community_id=community.id, add_to_modlog_activitypub('restore_post', restorer, community_id=community.id,
link_text=shorten_string(to_restore.title), link=f'post/{to_restore.id}') link_text=shorten_string(to_restore.title), link=f'post/{to_restore.id}',
reason=reason)
elif isinstance(to_restore, PostReply): elif isinstance(to_restore, PostReply):
to_restore.deleted = False to_restore.deleted = False
@ -1412,7 +1417,8 @@ def restore_post_or_comment(restorer, to_restore, store_ap_json, request_json):
if to_restore.author.id != restorer.id: if to_restore.author.id != restorer.id:
add_to_modlog_activitypub('restore_post_reply', restorer, community_id=community.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_text=f'comment on {shorten_string(to_restore.post.title)}',
link=f'post/{to_restore.post_id}#comment_{to_restore.id}') link=f'post/{to_restore.post_id}#comment_{to_restore.id}',
reason=reason)
log_incoming_ap(id, APLOG_UNDO_DELETE, APLOG_SUCCESS, request_json if store_ap_json else None) log_incoming_ap(id, APLOG_UNDO_DELETE, APLOG_SUCCESS, request_json if store_ap_json else None)
else: else:
log_incoming_ap(id, APLOG_UNDO_DELETE, APLOG_FAILURE, request_json if store_ap_json else None, 'Restorer did not have permisson') log_incoming_ap(id, APLOG_UNDO_DELETE, APLOG_FAILURE, request_json if store_ap_json else None, 'Restorer did not have permisson')
@ -1539,23 +1545,28 @@ def community_ban_remove_data(blocker_id, community_id, blocked):
db.session.commit() db.session.commit()
def ban_local_user(blocker, blocked, community, request_json): def ban_user(blocker, blocked, community, request_json):
existing = CommunityBan.query.filter_by(community_id=community.id, user_id=blocked.id).first() existing = CommunityBan.query.filter_by(community_id=community.id, user_id=blocked.id).first()
if not existing: if not existing:
new_ban = CommunityBan(community_id=community.id, user_id=blocked.id, banned_by=blocker.id) new_ban = CommunityBan(community_id=community.id, user_id=blocked.id, banned_by=blocker.id)
if 'summary' in request_json: if 'summary' in request_json['object']:
new_ban.reason=request_json['object']['summary'] new_ban.reason=request_json['object']['summary']
reason = request_json['object']['summary']
else:
reason = ''
if 'expires' in request_json and datetime.fromisoformat(request_json['object']['expires']) > datetime.now(timezone.utc): if 'expires' in request_json and datetime.fromisoformat(request_json['object']['expires']) > datetime.now(timezone.utc):
new_ban.ban_until = datetime.fromisoformat(request_json['object']['expires']) new_ban.ban_until = datetime.fromisoformat(request_json['object']['expires'])
elif 'endTime' in request_json and datetime.fromisoformat(request_json['object']['endTime']) > datetime.now(timezone.utc): elif 'endTime' in request_json and datetime.fromisoformat(request_json['object']['endTime']) > datetime.now(timezone.utc):
new_ban.ban_until = datetime.fromisoformat(request_json['object']['endTime']) new_ban.ban_until = datetime.fromisoformat(request_json['object']['endTime'])
db.session.add(new_ban) db.session.add(new_ban)
db.session.commit()
db.session.query(CommunityJoinRequest).filter(CommunityJoinRequest.community_id == community.id, CommunityJoinRequest.user_id == blocked.id).delete()
community_membership_record = CommunityMember.query.filter_by(community_id=community.id, user_id=blocked.id).first() community_membership_record = CommunityMember.query.filter_by(community_id=community.id, user_id=blocked.id).first()
if community_membership_record: if community_membership_record:
community_membership_record.is_banned = True community_membership_record.is_banned = True
db.session.commit()
if blocked.is_local():
db.session.query(CommunityJoinRequest).filter(CommunityJoinRequest.community_id == community.id, CommunityJoinRequest.user_id == blocked.id).delete()
# Notify banned person # Notify banned person
notify = Notification(title=shorten_string('You have been banned from ' + community.title), notify = Notification(title=shorten_string('You have been banned from ' + community.title),
@ -1575,15 +1586,18 @@ def ban_local_user(blocker, blocked, community, request_json):
cache.delete_memoized(joined_communities, blocked.id) cache.delete_memoized(joined_communities, blocked.id)
cache.delete_memoized(moderating_communities, blocked.id) cache.delete_memoized(moderating_communities, blocked.id)
add_to_modlog_activitypub('ban_user', blocker, community_id=community.id, link_text=blocked.display_name(), link=blocked.link()) add_to_modlog_activitypub('ban_user', blocker, community_id=community.id, link_text=blocked.display_name(), link=f'u/{blocked.link()}', reason=reason)
def unban_local_user(blocker, blocked, community, request_json): def unban_user(blocker, blocked, community, request_json):
reason = request_json['object']['summary'] if 'summary' in request_json['object'] else ''
db.session.query(CommunityBan).filter(CommunityBan.community_id == community.id, CommunityBan.user_id == blocked.id).delete() db.session.query(CommunityBan).filter(CommunityBan.community_id == community.id, CommunityBan.user_id == blocked.id).delete()
community_membership_record = CommunityMember.query.filter_by(community_id=community.id, user_id=blocked.id).first() community_membership_record = CommunityMember.query.filter_by(community_id=community.id, user_id=blocked.id).first()
if community_membership_record: if community_membership_record:
community_membership_record.is_banned = False community_membership_record.is_banned = False
db.session.commit()
if blocked.is_local():
# Notify unbanned person # Notify unbanned person
notify = Notification(title=shorten_string('You have been unbanned from ' + community.title), notify = Notification(title=shorten_string('You have been unbanned from ' + community.title),
url=f'/notifications', user_id=blocked.id, author_id=blocker.id) url=f'/notifications', user_id=blocked.id, author_id=blocker.id)
@ -1597,24 +1611,7 @@ def unban_local_user(blocker, blocked, community, request_json):
cache.delete_memoized(joined_communities, blocked.id) cache.delete_memoized(joined_communities, blocked.id)
cache.delete_memoized(moderating_communities, blocked.id) cache.delete_memoized(moderating_communities, blocked.id)
add_to_modlog_activitypub('unban_user', blocker, community_id=community.id, link_text=blocked.display_name(), link=blocked.link()) add_to_modlog_activitypub('unban_user', blocker, community_id=community.id, link_text=blocked.display_name(), link=f'u/{blocked.link()}', reason=reason)
def lock_post(mod_ap_id, post_id, comments_enabled):
if current_app.debug:
lock_post_task(mod_ap_id, post_id, comments_enabled)
else:
lock_post_task.delay(mod_ap_id, post_id, comments_enabled)
@celery.task
def lock_post_task(mod_ap_id, post_id, comments_enabled):
mod = find_actor_or_create(mod_ap_id, create_if_not_found=False)
post = Post.query.filter_by(ap_id=post_id).first()
if mod and post:
if post.community.is_moderator(mod) or post.community.is_instance_admin(mod):
post.comments_enabled = comments_enabled
db.session.commit()
def create_post_reply(store_ap_json, community: Community, in_reply_to, request_json: dict, user: User, announce_id=None) -> Union[PostReply, None]: def create_post_reply(store_ap_json, community: Community, in_reply_to, request_json: dict, user: User, announce_id=None) -> Union[PostReply, None]:

View file

@ -630,6 +630,7 @@ class Community(db.Model):
db.session.query(CommunityJoinRequest).filter(CommunityJoinRequest.community_id == self.id).delete() db.session.query(CommunityJoinRequest).filter(CommunityJoinRequest.community_id == self.id).delete()
db.session.query(CommunityMember).filter(CommunityMember.community_id == self.id).delete() db.session.query(CommunityMember).filter(CommunityMember.community_id == self.id).delete()
db.session.query(Report).filter(Report.suspect_community_id == self.id).delete() db.session.query(Report).filter(Report.suspect_community_id == self.id).delete()
db.session.query(ModLog).filter(ModLog.community_id == self.id).delete()
user_role = db.Table('user_role', user_role = db.Table('user_role',
@ -1020,6 +1021,7 @@ class User(UserMixin, db.Model):
db.session.query(PollChoiceVote).filter(PollChoiceVote.user_id == self.id).delete() db.session.query(PollChoiceVote).filter(PollChoiceVote.user_id == self.id).delete()
db.session.query(PostBookmark).filter(PostBookmark.user_id == self.id).delete() db.session.query(PostBookmark).filter(PostBookmark.user_id == self.id).delete()
db.session.query(PostReplyBookmark).filter(PostReplyBookmark.user_id == self.id).delete() db.session.query(PostReplyBookmark).filter(PostReplyBookmark.user_id == self.id).delete()
db.session.query(ModLog).filter(ModLog.user_id == self.id).delete()
def purge_content(self, soft=True): def purge_content(self, soft=True):
files = File.query.join(Post).filter(Post.user_id == self.id).all() files = File.query.join(Post).filter(Post.user_id == self.id).all()
@ -2285,6 +2287,8 @@ class ModLog(db.Model):
'undelete_user': _l('Restored account'), 'undelete_user': _l('Restored account'),
'ban_user': _l('Banned account'), 'ban_user': _l('Banned account'),
'unban_user': _l('Un-banned account'), 'unban_user': _l('Un-banned account'),
'lock_post': _l('Lock post'),
'unlock_post': _l('Un-lock post'),
} }
def action_to_str(self): def action_to_str(self):

View file

@ -29,12 +29,12 @@
{% elif modlog_entry.link_text -%} {% elif modlog_entry.link_text -%}
{{ modlog_entry.link_text }} {{ modlog_entry.link_text }}
{% endif -%} {% endif -%}
{% if modlog_entry.reason -%}
<br>{{ _('Reason:') }} {{ modlog_entry.reason }}
{% endif -%}
{% if modlog_entry.community_id -%} {% if modlog_entry.community_id -%}
<a href="/c/{{ modlog_entry.community.link() }}">{{ _(' in %(community_name)s', community_name='' + modlog_entry.community.display_name()) }}</a> <a href="/c/{{ modlog_entry.community.link() }}">{{ _(' in %(community_name)s', community_name='' + modlog_entry.community.display_name()) }}</a>
{% endif -%} {% endif -%}
{% if modlog_entry.reason -%}
<br>{{ _('Reason:') }} {{ modlog_entry.reason }}
{% endif -%}
</td> </td>
</tr> </tr>
{% endfor %} {% endfor %}