mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 18:11:08 -05:00
Improve type hints and code organization in moderation views
This commit is contained in:
@@ -1,23 +1,30 @@
|
|||||||
from django.views.generic import ListView, TemplateView
|
from django.views.generic import ListView, TemplateView
|
||||||
from django.shortcuts import get_object_or_404
|
from django.shortcuts import get_object_or_404
|
||||||
from django.http import HttpResponse, JsonResponse
|
from django.http import HttpResponse, JsonResponse, HttpRequest
|
||||||
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
|
from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.template.loader import render_to_string
|
from django.template.loader import render_to_string
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.core.exceptions import PermissionDenied
|
from django.core.exceptions import PermissionDenied
|
||||||
|
from typing import Optional, Any, cast
|
||||||
|
from accounts.models import User # Import custom User model
|
||||||
|
|
||||||
from .models import EditSubmission, PhotoSubmission
|
from .models import EditSubmission, PhotoSubmission
|
||||||
|
|
||||||
class ModeratorRequiredMixin(UserPassesTestMixin):
|
MODERATOR_ROLES = ['MODERATOR', 'ADMIN', 'SUPERUSER']
|
||||||
def test_func(self):
|
|
||||||
if not hasattr(self, 'request'):
|
|
||||||
return False
|
|
||||||
if not self.request.user.is_authenticated:
|
|
||||||
return False
|
|
||||||
return getattr(self.request.user, 'role', None) in ['MODERATOR', 'ADMIN', 'SUPERUSER']
|
|
||||||
|
|
||||||
def handle_no_permission(self):
|
class ModeratorRequiredMixin(UserPassesTestMixin):
|
||||||
|
request: HttpRequest
|
||||||
|
|
||||||
|
def test_func(self) -> bool:
|
||||||
|
"""Check if user has moderator permissions."""
|
||||||
|
user = cast(User, self.request.user)
|
||||||
|
return (
|
||||||
|
user.is_authenticated and
|
||||||
|
getattr(user, 'role', None) in MODERATOR_ROLES
|
||||||
|
)
|
||||||
|
|
||||||
|
def handle_no_permission(self) -> HttpResponse:
|
||||||
if not self.request.user.is_authenticated:
|
if not self.request.user.is_authenticated:
|
||||||
return super().handle_no_permission()
|
return super().handle_no_permission()
|
||||||
raise PermissionDenied("You do not have moderator permissions.")
|
raise PermissionDenied("You do not have moderator permissions.")
|
||||||
@@ -25,7 +32,7 @@ class ModeratorRequiredMixin(UserPassesTestMixin):
|
|||||||
class DashboardView(LoginRequiredMixin, ModeratorRequiredMixin, TemplateView):
|
class DashboardView(LoginRequiredMixin, ModeratorRequiredMixin, TemplateView):
|
||||||
template_name = 'moderation/dashboard.html'
|
template_name = 'moderation/dashboard.html'
|
||||||
|
|
||||||
def get_context_data(self, **kwargs):
|
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
|
||||||
context = super().get_context_data(**kwargs)
|
context = super().get_context_data(**kwargs)
|
||||||
context['submissions'] = EditSubmission.objects.all().order_by('-created_at')[:10]
|
context['submissions'] = EditSubmission.objects.all().order_by('-created_at')[:10]
|
||||||
return context
|
return context
|
||||||
@@ -37,16 +44,13 @@ class EditSubmissionListView(LoginRequiredMixin, ModeratorRequiredMixin, ListVie
|
|||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
queryset = EditSubmission.objects.all().order_by('-created_at')
|
queryset = EditSubmission.objects.all().order_by('-created_at')
|
||||||
|
|
||||||
status = self.request.GET.get('status')
|
if status := self.request.GET.get('status'):
|
||||||
if status:
|
|
||||||
queryset = queryset.filter(status=status)
|
queryset = queryset.filter(status=status)
|
||||||
|
|
||||||
submission_type = self.request.GET.get('type')
|
if submission_type := self.request.GET.get('type'):
|
||||||
if submission_type:
|
|
||||||
queryset = queryset.filter(submission_type=submission_type)
|
queryset = queryset.filter(submission_type=submission_type)
|
||||||
|
|
||||||
content_type = self.request.GET.get('content_type')
|
if content_type := self.request.GET.get('content_type'):
|
||||||
if content_type:
|
|
||||||
queryset = queryset.filter(content_type__model=content_type)
|
queryset = queryset.filter(content_type__model=content_type)
|
||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
@@ -58,122 +62,111 @@ class PhotoSubmissionListView(LoginRequiredMixin, ModeratorRequiredMixin, ListVi
|
|||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
queryset = PhotoSubmission.objects.all().order_by('-created_at')
|
queryset = PhotoSubmission.objects.all().order_by('-created_at')
|
||||||
|
|
||||||
status = self.request.GET.get('status')
|
if status := self.request.GET.get('status'):
|
||||||
if status:
|
|
||||||
queryset = queryset.filter(status=status)
|
queryset = queryset.filter(status=status)
|
||||||
|
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
@login_required
|
def _update_submission_notes(submission: EditSubmission, notes: Optional[str]) -> None:
|
||||||
def submission_list(request):
|
"""Update submission notes if provided."""
|
||||||
"""HTMX endpoint for filtered submission list"""
|
if notes:
|
||||||
if not request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
|
submission.notes = notes
|
||||||
return HttpResponse(status=403)
|
submission.save()
|
||||||
|
|
||||||
status = request.GET.get('status')
|
def _render_submission_response(template: str, submission: Any, request: HttpRequest) -> HttpResponse:
|
||||||
submission_type = request.GET.get('type')
|
"""Render submission template response."""
|
||||||
content_type = request.GET.get('content_type')
|
context = {'submission': submission}
|
||||||
|
html = render_to_string(template, context, request=request)
|
||||||
queryset = EditSubmission.objects.all().order_by('-created_at')
|
|
||||||
|
|
||||||
if status:
|
|
||||||
queryset = queryset.filter(status=status)
|
|
||||||
if submission_type:
|
|
||||||
queryset = queryset.filter(submission_type=submission_type)
|
|
||||||
if content_type:
|
|
||||||
queryset = queryset.filter(content_type__model=content_type)
|
|
||||||
|
|
||||||
context = {
|
|
||||||
'submissions': queryset
|
|
||||||
}
|
|
||||||
|
|
||||||
html = render_to_string('moderation/partials/submission_list.html', context, request=request)
|
|
||||||
return HttpResponse(html)
|
return HttpResponse(html)
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def approve_submission(request, submission_id):
|
def submission_list(request: HttpRequest) -> HttpResponse:
|
||||||
|
"""HTMX endpoint for filtered submission list"""
|
||||||
|
user = cast(User, request.user)
|
||||||
|
if user.role not in MODERATOR_ROLES:
|
||||||
|
return HttpResponse(status=403)
|
||||||
|
|
||||||
|
queryset = EditSubmission.objects.all().order_by('-created_at')
|
||||||
|
|
||||||
|
if status := request.GET.get('status'):
|
||||||
|
queryset = queryset.filter(status=status)
|
||||||
|
if submission_type := request.GET.get('type'):
|
||||||
|
queryset = queryset.filter(submission_type=submission_type)
|
||||||
|
if content_type := request.GET.get('content_type'):
|
||||||
|
queryset = queryset.filter(content_type__model=content_type)
|
||||||
|
|
||||||
|
html = render_to_string(
|
||||||
|
'moderation/partials/submission_list.html',
|
||||||
|
{'submissions': queryset},
|
||||||
|
request=request
|
||||||
|
)
|
||||||
|
return HttpResponse(html)
|
||||||
|
|
||||||
|
@login_required
|
||||||
|
def approve_submission(request: HttpRequest, submission_id: int) -> HttpResponse:
|
||||||
"""HTMX endpoint for approving a submission"""
|
"""HTMX endpoint for approving a submission"""
|
||||||
if not request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
|
user = cast(User, request.user)
|
||||||
|
if user.role not in MODERATOR_ROLES:
|
||||||
return HttpResponse(status=403)
|
return HttpResponse(status=403)
|
||||||
|
|
||||||
submission = get_object_or_404(EditSubmission, id=submission_id)
|
submission = get_object_or_404(EditSubmission, id=submission_id)
|
||||||
notes = request.POST.get('notes', '')
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
submission.approve(request.user)
|
submission.approve(user)
|
||||||
if notes:
|
_update_submission_notes(submission, request.POST.get('notes'))
|
||||||
submission.notes = notes
|
return _render_submission_response('moderation/partials/submission_list.html', submission, request)
|
||||||
submission.save()
|
|
||||||
|
|
||||||
context = {'submission': submission}
|
|
||||||
html = render_to_string('moderation/partials/submission_list.html', context, request=request)
|
|
||||||
return HttpResponse(html)
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
return HttpResponse(str(e), status=400)
|
return HttpResponse(str(e), status=400)
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def reject_submission(request, submission_id):
|
def reject_submission(request: HttpRequest, submission_id: int) -> HttpResponse:
|
||||||
"""HTMX endpoint for rejecting a submission"""
|
"""HTMX endpoint for rejecting a submission"""
|
||||||
if not request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
|
user = cast(User, request.user)
|
||||||
|
if user.role not in MODERATOR_ROLES:
|
||||||
return HttpResponse(status=403)
|
return HttpResponse(status=403)
|
||||||
|
|
||||||
submission = get_object_or_404(EditSubmission, id=submission_id)
|
submission = get_object_or_404(EditSubmission, id=submission_id)
|
||||||
notes = request.POST.get('notes', '')
|
submission.reject(user)
|
||||||
|
_update_submission_notes(submission, request.POST.get('notes'))
|
||||||
|
|
||||||
submission.reject(request.user)
|
return _render_submission_response('moderation/partials/submission_list.html', submission, request)
|
||||||
if notes:
|
|
||||||
submission.notes = notes
|
|
||||||
submission.save()
|
|
||||||
|
|
||||||
context = {'submission': submission}
|
|
||||||
html = render_to_string('moderation/partials/submission_list.html', context, request=request)
|
|
||||||
return HttpResponse(html)
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def escalate_submission(request, submission_id):
|
def escalate_submission(request: HttpRequest, submission_id: int) -> HttpResponse:
|
||||||
"""HTMX endpoint for escalating a submission"""
|
"""HTMX endpoint for escalating a submission"""
|
||||||
if not request.user.role == 'MODERATOR':
|
user = cast(User, request.user)
|
||||||
|
if user.role != 'MODERATOR':
|
||||||
return HttpResponse(status=403)
|
return HttpResponse(status=403)
|
||||||
|
|
||||||
submission = get_object_or_404(EditSubmission, id=submission_id)
|
submission = get_object_or_404(EditSubmission, id=submission_id)
|
||||||
notes = request.POST.get('notes', '')
|
submission.escalate(user)
|
||||||
|
_update_submission_notes(submission, request.POST.get('notes'))
|
||||||
|
|
||||||
submission.escalate(request.user)
|
return _render_submission_response('moderation/partials/submission_list.html', submission, request)
|
||||||
if notes:
|
|
||||||
submission.notes = notes
|
|
||||||
submission.save()
|
|
||||||
|
|
||||||
context = {'submission': submission}
|
|
||||||
html = render_to_string('moderation/partials/submission_list.html', context, request=request)
|
|
||||||
return HttpResponse(html)
|
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def approve_photo(request, submission_id):
|
def approve_photo(request: HttpRequest, submission_id: int) -> HttpResponse:
|
||||||
"""HTMX endpoint for approving a photo submission"""
|
"""HTMX endpoint for approving a photo submission"""
|
||||||
if not request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
|
user = cast(User, request.user)
|
||||||
|
if user.role not in MODERATOR_ROLES:
|
||||||
return HttpResponse(status=403)
|
return HttpResponse(status=403)
|
||||||
|
|
||||||
submission = get_object_or_404(PhotoSubmission, id=submission_id)
|
submission = get_object_or_404(PhotoSubmission, id=submission_id)
|
||||||
notes = request.POST.get('notes', '')
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
submission.approve(request.user, notes)
|
submission.approve(user, request.POST.get('notes', ''))
|
||||||
context = {'submission': submission}
|
return _render_submission_response('moderation/partials/photo_submission.html', submission, request)
|
||||||
html = render_to_string('moderation/partials/photo_submission.html', context, request=request)
|
|
||||||
return HttpResponse(html)
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return HttpResponse(str(e), status=400)
|
return HttpResponse(str(e), status=400)
|
||||||
|
|
||||||
@login_required
|
@login_required
|
||||||
def reject_photo(request, submission_id):
|
def reject_photo(request: HttpRequest, submission_id: int) -> HttpResponse:
|
||||||
"""HTMX endpoint for rejecting a photo submission"""
|
"""HTMX endpoint for rejecting a photo submission"""
|
||||||
if not request.user.role in ['MODERATOR', 'ADMIN', 'SUPERUSER']:
|
user = cast(User, request.user)
|
||||||
|
if user.role not in MODERATOR_ROLES:
|
||||||
return HttpResponse(status=403)
|
return HttpResponse(status=403)
|
||||||
|
|
||||||
submission = get_object_or_404(PhotoSubmission, id=submission_id)
|
submission = get_object_or_404(PhotoSubmission, id=submission_id)
|
||||||
notes = request.POST.get('notes', '')
|
submission.reject(user, request.POST.get('notes', ''))
|
||||||
|
|
||||||
submission.reject(request.user, notes)
|
return _render_submission_response('moderation/partials/photo_submission.html', submission, request)
|
||||||
context = {'submission': submission}
|
|
||||||
html = render_to_string('moderation/partials/photo_submission.html', context, request=request)
|
|
||||||
return HttpResponse(html)
|
|
||||||
|
|||||||
Reference in New Issue
Block a user