mirror of
https://codeberg.org/rimu/pyfedi
synced 2025-01-24 03:43:42 -08:00
escalate or resolve reports #21
This commit is contained in:
parent
84d98e2e55
commit
090b6d5a68
6 changed files with 105 additions and 6 deletions
|
@ -4,7 +4,7 @@ from time import sleep
|
||||||
from flask import request, flash, json, url_for, current_app, redirect, g
|
from flask import request, flash, json, url_for, current_app, redirect, g
|
||||||
from flask_login import login_required, current_user
|
from flask_login import login_required, current_user
|
||||||
from flask_babel import _
|
from flask_babel import _
|
||||||
from sqlalchemy import text, desc
|
from sqlalchemy import text, desc, or_
|
||||||
|
|
||||||
from app import db, celery, cache
|
from app import db, celery, cache
|
||||||
from app.activitypub.routes import process_inbox_request, process_delete_request
|
from app.activitypub.routes import process_inbox_request, process_delete_request
|
||||||
|
@ -15,6 +15,7 @@ from app.admin.forms import FederationForm, SiteMiscForm, SiteProfileForm, EditC
|
||||||
from app.admin.util import unsubscribe_from_everything_then_delete, unsubscribe_from_community, send_newsletter, \
|
from app.admin.util import unsubscribe_from_everything_then_delete, unsubscribe_from_community, send_newsletter, \
|
||||||
topic_tree, topics_for_form
|
topic_tree, topics_for_form
|
||||||
from app.community.util import save_icon_file, save_banner_file
|
from app.community.util import save_icon_file, save_banner_file
|
||||||
|
from app.constants import REPORT_STATE_NEW, REPORT_STATE_ESCALATED
|
||||||
from app.models import AllowedInstances, BannedInstances, ActivityPubLog, utcnow, Site, Community, CommunityMember, \
|
from app.models import AllowedInstances, BannedInstances, ActivityPubLog, utcnow, Site, Community, CommunityMember, \
|
||||||
User, Instance, File, Report, Topic, UserRegistration, Role, Post
|
User, Instance, File, Report, Topic, UserRegistration, Role, Post
|
||||||
from app.utils import render_template, permission_required, set_setting, get_setting, gibberish, markdown_to_html, \
|
from app.utils import render_template, permission_required, set_setting, get_setting, gibberish, markdown_to_html, \
|
||||||
|
@ -674,7 +675,7 @@ def admin_reports():
|
||||||
search = request.args.get('search', '')
|
search = request.args.get('search', '')
|
||||||
local_remote = request.args.get('local_remote', '')
|
local_remote = request.args.get('local_remote', '')
|
||||||
|
|
||||||
reports = Report.query.filter_by(status=0)
|
reports = Report.query.filter(or_(Report.status == REPORT_STATE_NEW, Report.status == REPORT_STATE_ESCALATED))
|
||||||
if local_remote == 'local':
|
if local_remote == 'local':
|
||||||
reports = reports.filter_by(ap_id=None)
|
reports = reports.filter_by(ap_id=None)
|
||||||
if local_remote == 'remote':
|
if local_remote == 'remote':
|
||||||
|
|
|
@ -61,6 +61,17 @@ class AddModeratorForm(FlaskForm):
|
||||||
submit = SubmitField(_l('Add'))
|
submit = SubmitField(_l('Add'))
|
||||||
|
|
||||||
|
|
||||||
|
class EscalateReportForm(FlaskForm):
|
||||||
|
reason = StringField(_l('Amend the report description if necessary'), validators=[DataRequired()])
|
||||||
|
submit = SubmitField(_l('Escalate report'))
|
||||||
|
|
||||||
|
|
||||||
|
class ResolveReportForm(FlaskForm):
|
||||||
|
note = StringField(_l('Note for mod log'), validators=[Optional()])
|
||||||
|
also_resolve_others = BooleanField(_l('Also resolve all other reports about the same thing.'), default=True)
|
||||||
|
submit = SubmitField(_l('Resolve report'))
|
||||||
|
|
||||||
|
|
||||||
class SearchRemoteCommunity(FlaskForm):
|
class SearchRemoteCommunity(FlaskForm):
|
||||||
address = StringField(_l('Community address'), render_kw={'placeholder': 'e.g. !name@server', 'autofocus': True}, validators=[DataRequired()])
|
address = StringField(_l('Community address'), render_kw={'placeholder': 'e.g. !name@server', 'autofocus': True}, validators=[DataRequired()])
|
||||||
submit = SubmitField(_l('Search'))
|
submit = SubmitField(_l('Search'))
|
||||||
|
|
|
@ -5,19 +5,20 @@ from random import randint
|
||||||
from flask import redirect, url_for, flash, request, make_response, session, Markup, current_app, abort, g, json
|
from flask import redirect, url_for, flash, request, make_response, session, Markup, current_app, abort, g, json
|
||||||
from flask_login import current_user, login_required
|
from flask_login import current_user, login_required
|
||||||
from flask_babel import _
|
from flask_babel import _
|
||||||
from sqlalchemy import or_, desc
|
from sqlalchemy import or_, desc, text
|
||||||
|
|
||||||
from app import db, constants, cache
|
from app import db, constants, cache
|
||||||
from app.activitypub.signature import RsaKeys, post_request
|
from app.activitypub.signature import RsaKeys, post_request
|
||||||
from app.activitypub.util import default_context, notify_about_post, find_actor_or_create, make_image_sizes
|
from app.activitypub.util import default_context, notify_about_post, find_actor_or_create, make_image_sizes
|
||||||
from app.chat.util import send_message
|
from app.chat.util import send_message
|
||||||
from app.community.forms import SearchRemoteCommunity, CreatePostForm, ReportCommunityForm, \
|
from app.community.forms import SearchRemoteCommunity, CreatePostForm, ReportCommunityForm, \
|
||||||
DeleteCommunityForm, AddCommunityForm, EditCommunityForm, AddModeratorForm, BanUserCommunityForm
|
DeleteCommunityForm, AddCommunityForm, EditCommunityForm, AddModeratorForm, BanUserCommunityForm, \
|
||||||
|
EscalateReportForm, ResolveReportForm
|
||||||
from app.community.util import search_for_community, community_url_exists, actor_to_community, \
|
from app.community.util import search_for_community, community_url_exists, actor_to_community, \
|
||||||
opengraph_parse, url_to_thumbnail_file, save_post, save_icon_file, save_banner_file, send_to_remote_instance, \
|
opengraph_parse, url_to_thumbnail_file, save_post, save_icon_file, save_banner_file, send_to_remote_instance, \
|
||||||
delete_post_from_community, delete_post_reply_from_community
|
delete_post_from_community, delete_post_reply_from_community
|
||||||
from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_OWNER, POST_TYPE_LINK, POST_TYPE_ARTICLE, POST_TYPE_IMAGE, \
|
from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_OWNER, POST_TYPE_LINK, POST_TYPE_ARTICLE, POST_TYPE_IMAGE, \
|
||||||
SUBSCRIPTION_PENDING, SUBSCRIPTION_MODERATOR
|
SUBSCRIPTION_PENDING, SUBSCRIPTION_MODERATOR, REPORT_STATE_NEW, REPORT_STATE_ESCALATED, REPORT_STATE_RESOLVED
|
||||||
from app.inoculation import inoculation
|
from app.inoculation import inoculation
|
||||||
from app.models import User, Community, CommunityMember, CommunityJoinRequest, CommunityBan, Post, \
|
from app.models import User, Community, CommunityMember, CommunityJoinRequest, CommunityBan, Post, \
|
||||||
File, PostVote, utcnow, Report, Notification, InstanceBlock, ActivityPubLog, Topic, Conversation, PostReply
|
File, PostVote, utcnow, Report, Notification, InstanceBlock, ActivityPubLog, Topic, Conversation, PostReply
|
||||||
|
@ -965,3 +966,48 @@ def community_moderate_banned(actor):
|
||||||
abort(401)
|
abort(401)
|
||||||
else:
|
else:
|
||||||
abort(404)
|
abort(404)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/community/<int:community_id>/moderate_report/<int:report_id>/escalate', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def community_moderate_report_escalate(community_id, report_id):
|
||||||
|
community = Community.query.get_or_404(community_id)
|
||||||
|
if community.is_moderator() or current_user.is_admin():
|
||||||
|
report = Report.query.filter_by(in_community_id=community.id, id=report_id, status=REPORT_STATE_NEW).first()
|
||||||
|
if report:
|
||||||
|
form = EscalateReportForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
notify = Notification(title='Escalated report', url='/admin/reports', user_id=1,
|
||||||
|
author_id=current_user.id)
|
||||||
|
db.session.add(notify)
|
||||||
|
report.description = form.reason.data
|
||||||
|
report.status = REPORT_STATE_ESCALATED
|
||||||
|
db.session.commit()
|
||||||
|
flash(_('Admin has been notified about this report.'))
|
||||||
|
# todo: remove unread notifications about this report
|
||||||
|
# todo: append to mod log
|
||||||
|
return redirect(url_for('community.community_moderate', actor=community.link()))
|
||||||
|
else:
|
||||||
|
form.reason.data = report.description
|
||||||
|
return render_template('community/community_moderate_report_escalate.html', form=form)
|
||||||
|
else:
|
||||||
|
abort(401)
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route('/community/<int:community_id>/moderate_report/<int:report_id>/resolve', methods=['GET', 'POST'])
|
||||||
|
@login_required
|
||||||
|
def community_moderate_report_resolve(community_id, report_id):
|
||||||
|
community = Community.query.get_or_404(community_id)
|
||||||
|
if community.is_moderator() or current_user.is_admin():
|
||||||
|
report = Report.query.filter_by(in_community_id=community.id, id=report_id).first()
|
||||||
|
if report:
|
||||||
|
form = ResolveReportForm()
|
||||||
|
if form.validate_on_submit():
|
||||||
|
report.status = REPORT_STATE_RESOLVED
|
||||||
|
db.session.commit()
|
||||||
|
# todo: remove unread notifications about this report
|
||||||
|
# todo: append to mod log
|
||||||
|
flash(_('Report resolved.'))
|
||||||
|
return redirect(url_for('community.community_moderate', actor=community.link()))
|
||||||
|
else:
|
||||||
|
return render_template('community/community_moderate_report_resolve.html', form=form)
|
||||||
|
|
|
@ -57,7 +57,9 @@
|
||||||
<a href="/post/{{ report.suspect_post_id }}">View</a>
|
<a href="/post/{{ report.suspect_post_id }}">View</a>
|
||||||
{% elif report.suspect_user_id %}
|
{% elif report.suspect_user_id %}
|
||||||
<a href="/user/{{ report.suspect_user_id }}">View</a>
|
<a href="/user/{{ report.suspect_user_id }}">View</a>
|
||||||
{% endif %}
|
{% endif %} |
|
||||||
|
<a href="{{ url_for('community.community_moderate_report_escalate', community_id=community.id, report_id=report.id) }}">{{ _('Escalate') }}</a> |
|
||||||
|
<a href="{{ url_for('community.community_moderate_report_resolve', community_id=community.id, report_id=report.id) }}">{{ _('Resolve') }}</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
{% if theme() and file_exists('app/templates/themes/' + theme() + '/base.html') %}
|
||||||
|
{% extends 'themes/' + theme() + '/base.html' %}
|
||||||
|
{% else %}
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% endif %} %}
|
||||||
|
{% from 'bootstrap/form.html' import render_form %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-login mx-auto">
|
||||||
|
<div class="card mt-5">
|
||||||
|
<div class="card-body p-6">
|
||||||
|
<div class="card-title">{{ _('Escalate report to admins') }}</div>
|
||||||
|
<p>{{ _('For reports that could potentially involve legal issues or where you are unsure how to respond, you may prefer to let admins handle it.') }}</p>
|
||||||
|
{{ render_form(form) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
|
@ -0,0 +1,19 @@
|
||||||
|
{% if theme() and file_exists('app/templates/themes/' + theme() + '/base.html') %}
|
||||||
|
{% extends 'themes/' + theme() + '/base.html' %}
|
||||||
|
{% else %}
|
||||||
|
{% extends "base.html" %}
|
||||||
|
{% endif %} %}
|
||||||
|
{% from 'bootstrap/form.html' import render_form %}
|
||||||
|
|
||||||
|
{% block app_content %}
|
||||||
|
<div class="row">
|
||||||
|
<div class="col col-login mx-auto">
|
||||||
|
<div class="card mt-5">
|
||||||
|
<div class="card-body p-6">
|
||||||
|
<div class="card-title">{{ _('Resolve report') }}</div>
|
||||||
|
{{ render_form(form) }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
Loading…
Add table
Reference in a new issue