Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Record report actions #2854

Merged
merged 10 commits into from
Aug 6, 2023
36 changes: 36 additions & 0 deletions bookwyrm/migrations/0179_reportcomment_comment_type.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Generated by Django 3.2.18 on 2023-05-16 16:02

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("bookwyrm", "0178_auto_20230328_2132"),
]

operations = [
migrations.AddField(
model_name="reportcomment",
name="action_type",
field=models.CharField(
choices=[
("comment", "Comment"),
("resolve", "Resolved report"),
("reopen", "Re-opened report"),
("message_reporter", "Messaged reporter"),
("message_offender", "Messaged reported user"),
("user_suspension", "Suspended user"),
("user_unsuspension", "Un-suspended user"),
("user_perms", "Changed user permission level"),
("user_deletion", "Deleted user account"),
("block_domain", "Blocked domain"),
("approve_domain", "Approved domain"),
("delete_item", "Deleted item"),
],
default="comment",
max_length=20,
),
),
migrations.RenameModel("ReportComment", "ReportAction"),
]
17 changes: 17 additions & 0 deletions bookwyrm/migrations/0180_alter_reportaction_options.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Generated by Django 3.2.18 on 2023-06-21 22:01

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("bookwyrm", "0179_reportcomment_comment_type"),
]

operations = [
migrations.AlterModelOptions(
name="reportaction",
options={"ordering": ("created_date",)},
),
]
13 changes: 13 additions & 0 deletions bookwyrm/migrations/0181_merge_20230806_2302.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Generated by Django 3.2.20 on 2023-08-06 23:02

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
("bookwyrm", "0180_alter_reportaction_options"),
("bookwyrm", "0180_alter_user_preferred_language"),
]

operations = []
2 changes: 1 addition & 1 deletion bookwyrm/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from .user import User, KeyPair
from .annual_goal import AnnualGoal
from .relationship import UserFollows, UserFollowRequest, UserBlocks
from .report import Report, ReportComment
from .report import Report, ReportAction
from .federated_server import FederatedServer

from .group import Group, GroupMember, GroupMemberInvitation
Expand Down
65 changes: 63 additions & 2 deletions bookwyrm/models/report.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,27 @@
""" flagged for moderation """
from django.core.exceptions import PermissionDenied
from django.db import models
from django.utils.translation import gettext_lazy as _

from bookwyrm.settings import DOMAIN
from .base_model import BookWyrmModel


# Report action enums
COMMENT = "comment"
RESOLVE = "resolve"
REOPEN = "reopen"
MESSAGE_REPORTER = "message_reporter"
MESSAGE_OFFENDER = "message_offender"
USER_SUSPENSION = "user_suspension"
USER_UNSUSPENSION = "user_unsuspension"
USER_DELETION = "user_deletion"
USER_PERMS = "user_perms"
BLOCK_DOMAIN = "block_domain"
APPROVE_DOMAIN = "approve_domain"
DELETE_ITEM = "delete_item"


class Report(BookWyrmModel):
"""reported status or user"""

Expand All @@ -32,20 +48,65 @@ def raise_not_editable(self, viewer):
def get_remote_id(self):
return f"https://{DOMAIN}/settings/reports/{self.id}"

def comment(self, user, note):
"""comment on a report"""
ReportAction.objects.create(
action_type=COMMENT, user=user, note=note, report=self
)

def resolve(self, user):
"""Mark a report as complete"""
self.resolved = True
self.save()
ReportAction.objects.create(action_type=RESOLVE, user=user, report=self)

def reopen(self, user):
"""Wait! This report isn't complete after all"""
self.resolved = False
self.save()
ReportAction.objects.create(action_type=REOPEN, user=user, report=self)

@classmethod
def record_action(cls, report_id: int, action: str, user):
"""Note that someone did something"""
if not report_id:
return
report = cls.objects.get(id=report_id)
ReportAction.objects.create(action_type=action, user=user, report=report)

class Meta:
"""set order by default"""

ordering = ("-created_date",)


class ReportComment(BookWyrmModel):
ReportActionTypes = [
(COMMENT, _("Comment")),
(RESOLVE, _("Resolved report")),
(REOPEN, _("Re-opened report")),
(MESSAGE_REPORTER, _("Messaged reporter")),
(MESSAGE_OFFENDER, _("Messaged reported user")),
(USER_SUSPENSION, _("Suspended user")),
(USER_UNSUSPENSION, _("Un-suspended user")),
(USER_PERMS, _("Changed user permission level")),
(USER_DELETION, _("Deleted user account")),
(BLOCK_DOMAIN, _("Blocked domain")),
(APPROVE_DOMAIN, _("Approved domain")),
(DELETE_ITEM, _("Deleted item")),
]


class ReportAction(BookWyrmModel):
"""updates on a report"""

user = models.ForeignKey("User", on_delete=models.PROTECT)
action_type = models.CharField(
max_length=20, blank=False, default="comment", choices=ReportActionTypes
)
note = models.TextField()
report = models.ForeignKey(Report, on_delete=models.PROTECT)

class Meta:
"""sort comments"""

ordering = ("-created_date",)
ordering = ("created_date",)
76 changes: 53 additions & 23 deletions bookwyrm/templates/settings/reports/report.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{% extends 'settings/layout.html' %}
{% load i18n %}
{% load humanize %}
{% load utilities %}
{% load feed_page_tags %}

{% block title %}
Expand All @@ -21,7 +22,7 @@
<div class="block">
<details class="details-panel box">
<summary>
<span class="title is-4">{% trans "Message reporter" %}</span>
<span class="title is-6">{% trans "Message reporter" %}</span>
<span class="details-close icon icon-x" aria-hidden="true"></span>
</summary>
<div class="box">
Expand Down Expand Up @@ -61,30 +62,59 @@ <h3 class="title is-4">{% trans "Reported links" %}</h3>
{% include 'settings/users/user_moderation_actions.html' with user=report.user %}
{% endif %}

<div class="block">
<h3 class="title is-4">{% trans "Moderator Comments" %}</h3>
{% for comment in report.reportcomment_set.all %}
<div class="card block">
<p class="card-content">{{ comment.note }}</p>
<div class="card-footer">
<div class="card-footer-item">
<a href="{{ comment.user.local_path }}">{{ comment.user.display_name }}</a>
<div class="block content">
<h3 class="title is-4">{% trans "Moderation Activity" %}</h3>

<div class="box">
<ul class="mt-0">
<li class="mb-2">
<div class="is-flex">
<p class="mb-0 is-flex-grow-1">
{% blocktrans trimmed with user=report.reporter|username user_link=report.reporter.local_path %}
<a href="{{ user_link }}">{{ user}}</a> opened this report
{% endblocktrans %}
</p>
<span class="tag">{{ report.created_date }}</span>
</div>
</li>

{% for comment in report.reportaction_set.all %}
<li class="mb-2">
<div class="is-flex">
<p class="mb-0 is-flex-grow-1">
{% if comment.action_type == "comment" %}
{% blocktrans trimmed with user=comment.user|username user_link=comment.user.local_path %}
<a href="{{ user_link }}">{{ user}}</a> commented on this report:
{% endblocktrans %}
{% else %}
{% blocktrans trimmed with user=comment.user|username user_link=comment.user.local_path %}
<a href="{{ user_link }}">{{ user}}</a> took an action on this report:
{% endblocktrans %}
<span class="has-text-weight-bold">
{{ comment.get_action_type_display }}
</span>
{% endif %}
</p>
<span class="tag">{{ comment.created_date }}</span>
</div>

{% if comment.note %}
<blockquote>{{ comment.note }}</blockquote>
{% endif %}
</li>
{% endfor %}
</ul>

<form class="block" name="report-comment" method="post" action="{% url 'settings-report' report.id %}">
{% csrf_token %}
<div class="field">
<label for="report_comment" class="label">Comment on report</label>
<textarea name="note" id="report_comment" class="textarea"></textarea>
</div>
<div class="card-footer-item">
{{ comment.created_date|naturaltime }}
<div class="field">
<button class="button">{% trans "Comment" %}</button>
</div>
</div>
</form>
</div>
{% endfor %}
<form class="block" name="report-comment" method="post" action="{% url 'settings-report' report.id %}">
{% csrf_token %}
<div class="field">
<label for="report_comment" class="label">Comment on report</label>
<textarea name="note" id="report_comment" class="textarea"></textarea>
</div>
<div class="field">
<button class="button">{% trans "Comment" %}</button>
</div>
</form>
</div>
{% endblock %}
12 changes: 11 additions & 1 deletion bookwyrm/templates/settings/reports/report_links_table.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,18 @@
</a>
</td>
<td>
<form>
{% if link.domain.status != "approved" %}
<form method="POST" action="{% url 'settings-link-domain-status' link.domain.id 'approved' report.id %}">
{% csrf_token %}
<button type="submit" class="button is-success is-light">{% trans "Approve domain" %}</button>
</form>
{% endif %}

{% if link.domain.status != "blocked" %}
<form method="POST" action="{% url 'settings-link-domain-status' link.domain.id 'blocked' report.id %}">
{% csrf_token %}
<button type="submit" class="button is-danger is-light">{% trans "Block domain" %}</button>
</form>
{% endif %}
</td>
{% endblock %}
2 changes: 1 addition & 1 deletion bookwyrm/templates/settings/users/delete_user_form.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
{% endblock %}

{% block form %}
<form name="delete-user" action="{% url 'settings-delete-user' user.id %}" method="post">
<form name="delete-user" action="{% url 'settings-delete-user' user.id report.id %}" method="post">
{% csrf_token %}
<p>
{% blocktrans trimmed with username=user.localname %}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ <h3>{% trans "User Actions" %}</h3>
</form>
{% endif %}
{% if user.is_active or user.deactivation_reason == "pending" %}
<form name="suspend" method="post" action="{% url 'settings-report-suspend' user.id %}" class="mr-1">
<form name="suspend" method="post" action="{% url 'settings-report-suspend' user.id report.id %}" class="mr-1">
{% csrf_token %}
<button type="submit" class="button is-danger is-light">{% trans "Suspend user" %}</button>
</form>
{% else %}
<form name="unsuspend" method="post" action="{% url 'settings-report-unsuspend' user.id %}" class="mr-1">
<form name="unsuspend" method="post" action="{% url 'settings-report-unsuspend' user.id report.id %}" class="mr-1">
{% csrf_token %}
<button class="button">{% trans "Un-suspend user" %}</button>
</form>
Expand All @@ -49,7 +49,7 @@ <h3>{% trans "User Actions" %}</h3>

{% if user.local %}
<div>
<form name="permission" method="post" action="{% url 'settings-user' user.id %}">
<form name="permission" method="post" action="{% url 'settings-user' user.id report.id %}">
mouse-reeve marked this conversation as resolved.
Show resolved Hide resolved
{% csrf_token %}
<label class="label" for="id_user_group">{% trans "Access level:" %}</label>
{% if group_form.non_field_errors %}
Expand Down
2 changes: 1 addition & 1 deletion bookwyrm/templates/snippets/status/layout.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

<div class="card-footer-item">
{# moderation options #}
<form name="delete-{{ status.id }}" action="/delete-status/{{ status.id }}" method="post">
<form name="delete-{{ status.id }}" action="/delete-status/{{ status.id }}/{{ report.id }}" method="post">
{% csrf_token %}
<button class="button is-danger is-light" type="submit">
{% trans "Delete status" %}
Expand Down
28 changes: 22 additions & 6 deletions bookwyrm/tests/views/admin/test_reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,24 +78,26 @@ def test_report_page(self):
validate_html(result.render())
self.assertEqual(result.status_code, 200)

def test_report_comment(self):
"""comment on a report"""
def test_report_action(self):
"""action on a report"""
view = views.ReportAdmin.as_view()
request = self.factory.post("", {"note": "hi"})
request.user = self.local_user
report = models.Report.objects.create(reporter=self.local_user, user=self.rat)

view(request, report.id)

comment = models.ReportComment.objects.get()
self.assertEqual(comment.user, self.local_user)
self.assertEqual(comment.note, "hi")
self.assertEqual(comment.report, report)
action = models.ReportAction.objects.get()
self.assertEqual(action.user, self.local_user)
self.assertEqual(action.note, "hi")
self.assertEqual(action.report, report)
self.assertEqual(action.action_type, "comment")

def test_resolve_report(self):
"""toggle report resolution status"""
report = models.Report.objects.create(reporter=self.local_user, user=self.rat)
self.assertFalse(report.resolved)
self.assertFalse(models.ReportAction.objects.exists())
request = self.factory.post("")
request.user = self.local_user

Expand All @@ -104,11 +106,25 @@ def test_resolve_report(self):
report.refresh_from_db()
self.assertTrue(report.resolved)

# check that the action was noted
self.assertTrue(
models.ReportAction.objects.filter(
report=report, action_type="resolve", user=self.local_user
).exists()
)

# un-resolve
views.resolve_report(request, report.id)
report.refresh_from_db()
self.assertFalse(report.resolved)

# check that the action was noted
self.assertTrue(
models.ReportAction.objects.filter(
report=report, action_type="reopen", user=self.local_user
).exists()
)

@patch("bookwyrm.suggested_users.rerank_suggestions_task.delay")
@patch("bookwyrm.activitystreams.populate_stream_task.delay")
@patch("bookwyrm.suggested_users.remove_user_task.delay")
Expand Down
Loading