Extension page should be 404 for everyone unless publicly listed #167

Merged
Anna Sirota merged 5 commits from extension-detail-page-listed-only into main 2024-06-05 12:12:14 +02:00
6 changed files with 113 additions and 29 deletions
Showing only changes of commit 8d8a650a96 - Show all commits

View File

@ -0,0 +1,18 @@
# Generated by Django 4.2.11 on 2024-06-05 09:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('abuse', '0007_alter_abusereport_status'),
]
operations = [
migrations.AlterField(
model_name='abusereport',
name='reason',
field=models.PositiveSmallIntegerField(choices=[(127, 'Other'), (1, 'Damages computer and/or data'), (2, 'Creates spam or advertising'), (3, "Doesn't work, breaks Blender, or slows it down"), (4, 'Hateful, violent, or illegal content'), (5, "Pretends to be something it's not")], default=127),
),
]

View File

@ -55,7 +55,7 @@ class AbuseReport(CreatedModifiedMixin, TrackChangesMixin, models.Model):
rating = models.ForeignKey('ratings.Rating', blank=True, null=True, on_delete=models.CASCADE) rating = models.ForeignKey('ratings.Rating', blank=True, null=True, on_delete=models.CASCADE)
message = models.TextField(blank=True) message = models.TextField(blank=True)
reason = models.PositiveSmallIntegerField( reason = models.PositiveSmallIntegerField(
default=REASONS[0][1], choices=REASONS.choices, blank=False, null=False default=REASONS.OTHER, choices=REASONS.choices, blank=False, null=False
) )
version = extensions.fields.VersionStringField( version = extensions.fields.VersionStringField(
max_length=64, max_length=64,

View File

@ -21,24 +21,30 @@
<h1>{{ object.get_type_display }} Report</h1> <h1>{{ object.get_type_display }} Report</h1>
<div class="hero-subtitle d-flex"> <div class="hero-subtitle d-flex">
<div class="ext-detail-tagline"> {% if extension %}
<a href="{{ extension.get_absolute_url }}">{{ extension.name }}</a> <div class="ext-detail-tagline">
</div> <a href="{{ extension.get_absolute_url }}">{{ extension.name }}</a>
<div class="ext-detail-authors ms-3"> </div>
<a href="{% url 'extensions:by-type' type_slug=extension.type_slug %}"> <div class="ext-detail-authors ms-3">
{{ extension.get_type_display }} <a href="{% url 'extensions:by-type' type_slug=extension.type_slug %}">
</a> {{ extension.get_type_display }}
</a>
{% if extension.team %} {% if extension.team %}
{% with team=extension.team %} {% with team=extension.team %}
{% blocktranslate with absolute_url=team.get_absolute_url name=team.name %} {% blocktranslate with absolute_url=team.get_absolute_url name=team.name %}
by <a href="{{ absolute_url }}" title="{{ name }}">{{ name }}</a> by <a href="{{ absolute_url }}" title="{{ name }}">{{ name }}</a>
{% endblocktranslate %} {% endblocktranslate %}
{% endwith %} {% endwith %}
{% elif extension.authors.count %} {% elif extension.authors.count %}
{% trans 'by' %} {% include "extensions/components/authors.html" %} {% trans 'by' %} {% include "extensions/components/authors.html" %}
{% endif %} {% endif %}
</div> </div>
{% else %}
<div class="ext-detail-tagline">
Reported user: {{ object.name }}
</div>
{% endif %}
</div> </div>
</div> </div>
@ -93,11 +99,11 @@
</div> </div>
<div class="dl-row"> <div class="dl-row">
<div class="dl-col"> <div class="dl-col">
{% if object.extension %} {% if extension %}
<dt>{{ object.extension.get_type_display }}</dt> <dt>{{ extension.get_type_display }}</dt>
<dd> <dd>
<a href="{{ object.extension.get_absolute_url }}"> <a href="{{ extension.get_absolute_url }}">
{{ object.extension.name }} {{ extension.name }}
</a> </a>
</dd> </dd>
{% else %} {% else %}
@ -124,9 +130,13 @@
<div class="dl-col"> <div class="dl-col">
<dt>by</dt> <dt>by</dt>
<dd> <dd>
<a href="{% url "extensions:by-author" user_id=object.reporter.pk %}"> {% if object.reporter %}
{{ object.reporter }} <a href="{% url "extensions:by-author" user_id=object.reporter.pk %}">
</a> {{ object.reporter }}
</a>
{% else %}
unknown
{% endif %}
</dd> </dd>
</div> </div>
</div> </div>

View File

@ -1,7 +1,8 @@
from django.test import TestCase from django.test import TestCase
from common.tests.factories.abuse import AbuseReportFactory
from common.tests.factories.extensions import create_approved_version from common.tests.factories.extensions import create_approved_version
from common.tests.factories.users import UserFactory from common.tests.factories.users import UserFactory, create_moderator
POST_DATA = { POST_DATA = {
'message': 'test message', 'message': 'test message',
@ -19,3 +20,44 @@ class ReportTest(TestCase):
_ = self.client.post(url, POST_DATA) _ = self.client.post(url, POST_DATA)
response = self.client.get(url, follow=True) response = self.client.get(url, follow=True)
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
def test_only_reporter_and_moderator_can_view_report_abt_user(self):
reported_user = UserFactory()
report = AbuseReportFactory(user=reported_user)
self.assertIsNone(report.extension)
report_url = report.get_absolute_url()
# Check that anonymous gets redirected (to login)
self.assertEqual(self.client.get(report_url).status_code, 302)
# Check that reported user cannot view the report
self.client.force_login(reported_user)
self.assertEqual(self.client.get(report_url).status_code, 404)
# Check that reporter and moderator can view the report
for account, role in (
(report.reporter, 'reporter'),
(create_moderator(), 'moderator'),
):
with self.subTest(role=role):
self.client.logout()
self.client.force_login(account)
self.assertEqual(self.client.get(report_url).status_code, 200)
def test_only_reporter_and_moderator_can_view_report_abt_extension(self):
report = AbuseReportFactory(user=None, extension=create_approved_version().extension)
self.assertIsNone(report.user)
report_url = report.get_absolute_url()
# Check that anonymous gets redirected (to login)
self.assertEqual(self.client.get(report_url).status_code, 302)
# Check that reporter and moderator can view the report
for account, role in (
(report.reporter, 'reporter'),
(create_moderator(), 'moderator'),
):
with self.subTest(role=role):
self.client.logout()
self.client.force_login(account)
self.assertEqual(self.client.get(report_url).status_code, 200)

View File

@ -128,6 +128,8 @@ class ReportView(LoginRequiredMixin, DetailView):
def get_object(self, *args, **kwargs): def get_object(self, *args, **kwargs):
obj = super().get_object(*args, **kwargs) obj = super().get_object(*args, **kwargs)
if obj.reporter.pk != self.request.user.pk and not self.request.user.is_moderator: if self.request.user.is_authenticated and (
raise Http404() obj.reporter_id == self.request.user.pk or self.request.user.is_moderator
return obj ):
return obj
raise Http404()

View File

@ -0,0 +1,12 @@
from factory.django import DjangoModelFactory
import factory
import abuse.models
class AbuseReportFactory(DjangoModelFactory):
class Meta:
model = abuse.models.AbuseReport
reporter = factory.SubFactory('common.tests.factories.users.UserFactory')
user = factory.SubFactory('common.tests.factories.users.UserFactory')