extensions-website/abuse/views.py
Oleg Komarov a2a16cf004 Reject rating when an abuse report gets resolved (#223)
See #217

This PR adds logic for automatically setting `Rating.status`
to `REJECTED` when a corresponding AbuseReport gets resolved.

Reviewed-on: #223
Reviewed-by: Anna Sirota <annasirota@noreply.localhost>
2024-07-22 13:42:54 +02:00

165 lines
5.3 KiB
Python

import logging
from actstream import action
from django.contrib.auth.mixins import UserPassesTestMixin, LoginRequiredMixin
from django.db import transaction
from django.http import Http404, HttpResponseForbidden
from django.views.generic.list import ListView
from django.views.generic.edit import CreateView, UpdateView
from django.shortcuts import get_object_or_404, redirect
from .forms import ReportExtensionForm, ReportRatingForm, ResolveReportForm
from constants.activity import Verb
from constants.base import ABUSE_TYPE_EXTENSION, ABUSE_TYPE_RATING
from abuse.models import AbuseReport
from ratings.models import Rating
from extensions.models import Extension, Version
import extensions.views.mixins
log = logging.getLogger(__name__)
class ReportList(
LoginRequiredMixin,
UserPassesTestMixin,
ListView,
):
model = AbuseReport
paginate_by = 100
def test_func(self) -> bool:
return self.request.user.is_moderator
def get_queryset(self):
return AbuseReport.objects.all().order_by('status', '-date_created')
template_name = 'abuse/abusereport_list.html'
class ReportExtensionView(
LoginRequiredMixin,
extensions.views.mixins.ListedExtensionMixin,
CreateView,
):
model = AbuseReport
form_class = ReportExtensionForm
def get(self, request, *args, **kwargs):
extension = get_object_or_404(Extension.objects.listed, slug=self.kwargs['slug'])
report = AbuseReport.objects.filter(
reporter_id=self.request.user.pk, extension_id=extension.id
).first()
if report is not None:
return redirect('abuse:view-report', pk=report.pk)
else:
return super().get(request, *args, **kwargs)
def form_valid(self, form):
"""Link newly created rating to latest version and current user."""
form.instance.reporter = self.request.user
form.instance.extension = self.extension
form.instance.extension_version = self.extension.latest_version.version
form.instance.type = ABUSE_TYPE_EXTENSION
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['extension'] = self.extension
return context
def get_success_url(self) -> str:
return self.object.get_absolute_url()
class ReportRatingView(
LoginRequiredMixin,
extensions.views.mixins.ListedExtensionMixin,
UserPassesTestMixin,
CreateView,
):
model = AbuseReport
form_class = ReportRatingForm
def test_func(self) -> bool:
# TODO: best to redirect to existing report or show a friendly message
return not AbuseReport.exists(
user_id=self.request.user.pk, extension_id=self.extension.id, rating_id=self.rating.id
)
def dispatch(self, *args, **kwargs):
self.extension = get_object_or_404(Extension.objects.listed, slug=self.kwargs['slug'])
self.version = get_object_or_404(
Version,
version=self.kwargs['version'],
extension=self.extension,
)
self.rating = get_object_or_404(
Rating,
extension=self.extension,
version=self.version,
id=self.kwargs['rating'],
)
return super().dispatch(*args, **kwargs)
def form_valid(self, form):
"""Link newly created rating to latest version and current user."""
form.instance.reporter = self.request.user
form.instance.extension = self.extension
form.instance.rating = self.rating
form.instance.extension_version = self.version.version
form.instance.type = ABUSE_TYPE_RATING
return super().form_valid(form)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['extension'] = self.extension
context['version'] = self.version
context['rating'] = self.rating
return context
def get_success_url(self) -> str:
return self.object.get_absolute_url()
class ReportView(LoginRequiredMixin, UpdateView):
model = AbuseReport
template_name = 'abuse/abusereport_detail.html'
def get_object(self, *args, **kwargs):
obj = super().get_object(*args, **kwargs)
if self.request.user.is_authenticated and (
obj.reporter_id == self.request.user.pk or self.request.user.is_moderator
):
return obj
raise Http404()
def get_form(self):
return ResolveReportForm(**self.get_form_kwargs(), request=self.request)
@transaction.atomic
def form_valid(self, form):
if 'dismiss' in form.data:
verb = Verb.DISMISSED_ABUSE_REPORT
if 'resolve' in form.data:
verb = Verb.RESOLVED_ABUSE_REPORT
if form.instance.type == ABUSE_TYPE_RATING:
rating = form.instance.rating
rating.status = Rating.STATUSES.REJECTED
rating.save(update_fields={'status'})
response = super().form_valid(form)
action.send(
self.request.user,
verb=verb,
target=form.instance,
)
return response
def post(self, *args, **kwargs):
if not self.request.user.is_moderator:
raise HttpResponseForbidden()
return super().post(*args, **kwargs)