mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-02-02 16:21:32 -08:00
receive federated reports from remote instances #21
This commit is contained in:
parent
a5212762f9
commit
66d05ea860
6 changed files with 107 additions and 8 deletions
|
@ -20,7 +20,8 @@ from app.activitypub.util import public_key, users_total, active_half_year, acti
|
|||
lemmy_site_data, instance_weight, is_activitypub_request, downvote_post_reply, downvote_post, upvote_post_reply, \
|
||||
upvote_post, delete_post_or_comment, community_members, \
|
||||
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
|
||||
update_post_from_activity, undo_vote, undo_downvote, post_to_page, get_redis_connection, find_reported_object, \
|
||||
process_report
|
||||
from app.utils import gibberish, get_setting, is_image_url, allowlist_html, render_template, \
|
||||
domain_from_url, markdown_to_html, community_membership, ap_datetime, ip_address, can_downvote, \
|
||||
can_upvote, can_create_post, awaken_dormant_instance, shorten_string, can_create_post_reply, sha256_digest, \
|
||||
|
@ -990,7 +991,19 @@ def process_inbox_request(request_json, activitypublog_id, ip_address):
|
|||
else:
|
||||
activity_log.exception_message = 'Cannot downvote this'
|
||||
activity_log.result = 'ignored'
|
||||
# Flush the caches of any major object that was created. To be sure.
|
||||
elif request_json['type'] == 'Flag': # Reported content
|
||||
activity_log.activity_type = 'Report'
|
||||
user_ap_id = request_json['actor']
|
||||
user = find_actor_or_create(user_ap_id)
|
||||
target_ap_id = request_json['object']
|
||||
reported = find_reported_object(target_ap_id)
|
||||
if user and reported:
|
||||
process_report(user, reported, request_json, activity_log)
|
||||
activity_log.result = 'success'
|
||||
else:
|
||||
activity_log.exception_message = 'Report ignored due to missing user or content'
|
||||
|
||||
# Flush the caches of any major object that was created. To be sure.
|
||||
if 'user' in vars() and user is not None:
|
||||
user.flush_cache()
|
||||
if user.instance_id and user.instance_id != 1:
|
||||
|
|
|
@ -12,7 +12,7 @@ from flask_babel import _
|
|||
from sqlalchemy import text, func
|
||||
from app import db, cache, constants, celery
|
||||
from app.models import User, Post, Community, BannedInstances, File, PostReply, AllowedInstances, Instance, utcnow, \
|
||||
PostVote, PostReplyVote, ActivityPubLog, Notification, Site, CommunityMember, InstanceRole
|
||||
PostVote, PostReplyVote, ActivityPubLog, Notification, Site, CommunityMember, InstanceRole, Report, Conversation
|
||||
import time
|
||||
import base64
|
||||
import requests
|
||||
|
@ -895,6 +895,21 @@ def find_liked_object(ap_id) -> Union[Post, PostReply, None]:
|
|||
return None
|
||||
|
||||
|
||||
def find_reported_object(ap_id) -> Union[User, Post, PostReply, None]:
|
||||
post = Post.get_by_ap_id(ap_id)
|
||||
if post:
|
||||
return post
|
||||
else:
|
||||
post_reply = PostReply.get_by_ap_id(ap_id)
|
||||
if post_reply:
|
||||
return post_reply
|
||||
else:
|
||||
user = find_actor_or_create(ap_id, create_if_not_found=False)
|
||||
if user:
|
||||
return user
|
||||
return None
|
||||
|
||||
|
||||
def find_instance_id(server):
|
||||
server = server.strip()
|
||||
instance = Instance.query.filter_by(domain=server).first()
|
||||
|
@ -1623,6 +1638,77 @@ def undo_vote(activity_log, comment, post, target_ap_id, user):
|
|||
return post
|
||||
|
||||
|
||||
def process_report(user, reported, request_json, activity_log):
|
||||
if len(request_json['summary']) < 15:
|
||||
reasons = request_json['summary']
|
||||
description = ''
|
||||
else:
|
||||
reasons = request_json['summary'][:15]
|
||||
description = request_json['summary'][15:]
|
||||
if isinstance(reported, User):
|
||||
if reported.reports == -1:
|
||||
return
|
||||
type = 0
|
||||
report = Report(reasons=reasons, description=description,
|
||||
type=type, reporter_id=user.id, suspect_user_id=reported.id, source_instance_id=user.instance_id)
|
||||
db.session.add(report)
|
||||
|
||||
# Notify site admin
|
||||
already_notified = set()
|
||||
for admin in Site.admins():
|
||||
if admin.id not in already_notified:
|
||||
notify = Notification(title='Reported user', url='/admin/reports', user_id=admin.id,
|
||||
author_id=user.id)
|
||||
db.session.add(notify)
|
||||
admin.unread_notifications += 1
|
||||
reported.reports += 1
|
||||
db.session.commit()
|
||||
elif isinstance(reported, Post):
|
||||
if reported.reports == -1:
|
||||
return
|
||||
type = 1
|
||||
report = Report(reasons=reasons, description=description, type=type, reporter_id=user.id,
|
||||
suspect_user_id=reported.author.id, suspect_post_id=reported.id,
|
||||
suspect_community_id=reported.community.id, in_community_id=reported.community.id,
|
||||
source_instance_id=user.instance_id)
|
||||
db.session.add(report)
|
||||
|
||||
already_notified = set()
|
||||
for mod in reported.community.moderators():
|
||||
notification = Notification(user_id=mod.user_id, title=_('A post has been reported'),
|
||||
url=f"https://{current_app.config['SERVER_NAME']}/post/{reported.id}",
|
||||
author_id=user.id)
|
||||
db.session.add(notification)
|
||||
already_notified.add(mod.user_id)
|
||||
reported.reports += 1
|
||||
db.session.commit()
|
||||
elif isinstance(reported, PostReply):
|
||||
if reported.reports == -1:
|
||||
return
|
||||
type = 2
|
||||
post = Post.query.get(reported.post_id)
|
||||
report = Report(reasons=reasons, description=description, type=type, reporter_id=user.id, suspect_post_id=post.id,
|
||||
suspect_community_id=post.community.id,
|
||||
suspect_user_id=reported.author.id, suspect_post_reply_id=reported.id,
|
||||
in_community_id=post.community.id,
|
||||
source_instance_id=user.instance_id)
|
||||
db.session.add(report)
|
||||
# Notify moderators
|
||||
already_notified = set()
|
||||
for mod in post.community.moderators():
|
||||
notification = Notification(user_id=mod.user_id, title=_('A comment has been reported'),
|
||||
url=f"https://{current_app.config['SERVER_NAME']}/comment/{reported.id}",
|
||||
author_id=user.id)
|
||||
db.session.add(notification)
|
||||
already_notified.add(mod.user_id)
|
||||
reported.reports += 1
|
||||
db.session.commit()
|
||||
elif isinstance(reported, Community):
|
||||
...
|
||||
elif isinstance(reported, Conversation):
|
||||
...
|
||||
|
||||
|
||||
def get_redis_connection() -> redis.Redis:
|
||||
connection_string = current_app.config['CACHE_REDIS_URL']
|
||||
if connection_string.startswith('unix://'):
|
||||
|
|
|
@ -405,8 +405,8 @@ class Community(db.Model):
|
|||
(or_(
|
||||
CommunityMember.is_owner,
|
||||
CommunityMember.is_moderator
|
||||
)) & CommunityMember.is_banned == False
|
||||
).all()
|
||||
))
|
||||
).filter(CommunityMember.is_banned == False).all()
|
||||
|
||||
def is_moderator(self, user=None):
|
||||
if user is None:
|
||||
|
|
|
@ -1040,7 +1040,7 @@ def post_reply_report(post_id: int, comment_id: int):
|
|||
url=f"https://{current_app.config['SERVER_NAME']}/comment/{post_reply.id}",
|
||||
author_id=current_user.id)
|
||||
db.session.add(notification)
|
||||
already_notified.add(mod.id)
|
||||
already_notified.add(mod.user_id)
|
||||
post_reply.reports += 1
|
||||
# todo: only notify admins for certain types of report
|
||||
for admin in Site.admins():
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<h1 class="mt-2">{{ _('Moderators for %(community)s', community=community.display_name()) }}</h1>
|
||||
</div>
|
||||
<p>{{ _('See and change who moderates this community') }}</p>
|
||||
<div class="col-12 col-md-2 text-right">
|
||||
<div class="col-12 text-right">
|
||||
<a class="btn btn-primary" href="{{ url_for('community.community_add_moderator', community_id=community.id) }}">{{ _('Add moderator') }}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<input type="search" name="search" value="{{ search }}">
|
||||
<input type="radio" name="local_remote" value="local" id="local_remote_local" {{ 'checked' if local_remote == 'local' }}><label for="local_remote_local"> Local</label>
|
||||
<input type="radio" name="local_remote" value="remote" id="local_remote_remote" {{ 'checked' if local_remote == 'remote' }}><label for="local_remote_remote"> Remote</label>
|
||||
<input type="submit" name="submit" value="Search" class="btn btn-primary">
|
||||
<input type="submit" name="submit" value="Search" class="btn btn-primary btn-sm">
|
||||
</form>
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
|
|
Loading…
Add table
Reference in a new issue