extensions-website/extensions/views/mixins.py
Dalai Felinto d00bcc585a Draft: Make sure extensions always have a user (#54)
When submitting a file the created extension gets a user right away.
This makes sure there are no orphans extensions.

The extension is then incomplete until the draft is saved once (which
means finalizing the extension upload process, by adding a description
and thumbnails).

Any attempt to edit or submit a new extension will lead the user to the
editing draft page.

Note: We could add a new option to [x] Send for Review. The front-end
even has a half-baked code for that. But should be tackled separately.

------------

Patch notes:
* Originally when trying to finish an upload as a different user we woudl get a 403, now we get a 404.

Reviewed-on: #54
Reviewed-by: Francesco Siddi <fsiddi@noreply.localhost>
2024-03-14 18:36:03 +01:00

85 lines
2.9 KiB
Python

from django.contrib.auth.mixins import UserPassesTestMixin
from django.shortcuts import get_object_or_404, redirect
from django.core.exceptions import BadRequest
from extensions.models import Extension
from files.models import File
class OwnsFileMixin(UserPassesTestMixin):
def dispatch(self, *args, **kwargs):
self.file = get_object_or_404(File, pk=self.kwargs['pk'])
self.extension = self._get_extension()
return super().dispatch(*args, **kwargs)
def test_func(self) -> bool:
return self.file.user == self.request.user
class ExtensionQuerysetMixin:
"""Add reusable methods to class-based views handling Extensions."""
def get_extension_queryset(self):
"""Return queryset with unlisted add-ons for logged in users under certain conditions."""
if self.request.user.is_staff:
return Extension.objects.all()
if self.request.user.is_authenticated:
return Extension.objects.listed_or_authored_by(user_id=self.request.user.pk)
return Extension.objects.listed
class MaintainedExtensionMixin:
"""Fetch an extension by slug if current user is a maintainer."""
def dispatch(self, *args, **kwargs):
self.extension = get_object_or_404(
Extension.objects.authored_by(user_id=self.request.user.pk),
slug=self.kwargs['slug'],
)
return super().dispatch(*args, **kwargs)
class ListedExtensionMixin:
"""Fetch a publicly listed extension by slug in the URL before dispatching the view."""
def dispatch(self, *args, **kwargs):
self.extension = get_object_or_404(Extension.objects.listed, slug=self.kwargs['slug'])
return super().dispatch(*args, **kwargs)
class ExtensionMixin:
"""Fetch an extension by slug in the URL before dispatching the view."""
def dispatch(self, *args, **kwargs):
self.extension = get_object_or_404(
Extension.objects.exclude_deleted, slug=self.kwargs['slug']
)
return super().dispatch(*args, **kwargs)
class DraftVersionMixin:
"""Fetch the version object which is being edited as a draft."""
def dispatch(self, *args, **kwargs):
self.version = self.extension.versions.first()
if self.version is None:
error_message = f'Extension "{self.extension.name}" has no versions.'
raise BadRequest(error_message)
return super().dispatch(*args, **kwargs)
class DraftMixin:
"""If the extension is incomplete, returns the FinalizeDraftView"""
def dispatch(self, request, *args, **kwargs):
extension = (
Extension.objects.listed_or_authored_by(user_id=self.request.user.pk)
.filter(status=Extension.STATUSES.INCOMPLETE)
.first()
)
if not extension:
return super().dispatch(request, *args, **kwargs)
return redirect(extension.get_draft_url())