From 4701374021694da72bfbddb46a95886b20188155 Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 2 Jul 2020 00:13:33 +0200 Subject: [PATCH] admin: remove duplicate code into new base classes --- passbook/admin/views/applications.py | 14 +-- passbook/admin/views/certificate_key_pair.py | 14 +-- passbook/admin/views/flows.py | 62 ++++++-------- passbook/admin/views/groups.py | 14 +-- passbook/admin/views/policies.py | 74 ++++------------ passbook/admin/views/policies_bindings.py | 17 +--- passbook/admin/views/property_mapping.py | 90 ++++---------------- passbook/admin/views/providers.py | 62 +++----------- passbook/admin/views/sources.py | 58 +++---------- passbook/admin/views/stages.py | 65 +++----------- passbook/admin/views/stages_bindings.py | 24 +----- passbook/admin/views/stages_invitations.py | 14 +-- passbook/admin/views/stages_prompts.py | 16 +--- passbook/admin/views/tokens.py | 13 +-- passbook/admin/views/users.py | 11 +-- passbook/admin/views/utils.py | 73 ++++++++++++++++ 16 files changed, 195 insertions(+), 426 deletions(-) create mode 100644 passbook/admin/views/utils.py diff --git a/passbook/admin/views/applications.py b/passbook/admin/views/applications.py index 8850b8998..741cf0e50 100644 --- a/passbook/admin/views/applications.py +++ b/passbook/admin/views/applications.py @@ -1,5 +1,4 @@ """passbook Application administration""" -from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import ( PermissionRequiredMixin as DjangoPermissionRequiredMixin, @@ -7,9 +6,10 @@ from django.contrib.auth.mixins import ( from django.contrib.messages.views import SuccessMessageMixin from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, ListView, UpdateView +from django.views.generic import ListView, UpdateView from guardian.mixins import PermissionListMixin, PermissionRequiredMixin +from passbook.admin.views.utils import DeleteMessageView from passbook.core.forms.applications import ApplicationForm from passbook.core.models import Application from passbook.lib.views import CreateAssignPermView @@ -41,10 +41,6 @@ class ApplicationCreateView( success_url = reverse_lazy("passbook_admin:applications") success_message = _("Successfully created Application") - def get_context_data(self, **kwargs): - kwargs["type"] = "Application" - return super().get_context_data(**kwargs) - class ApplicationUpdateView( SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView @@ -61,7 +57,7 @@ class ApplicationUpdateView( class ApplicationDeleteView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView + LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView ): """Delete application""" @@ -71,7 +67,3 @@ class ApplicationDeleteView( template_name = "generic/delete.html" success_url = reverse_lazy("passbook_admin:applications") success_message = _("Successfully deleted Application") - - def delete(self, request, *args, **kwargs): - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) diff --git a/passbook/admin/views/certificate_key_pair.py b/passbook/admin/views/certificate_key_pair.py index 716434b84..79e1c5a47 100644 --- a/passbook/admin/views/certificate_key_pair.py +++ b/passbook/admin/views/certificate_key_pair.py @@ -1,5 +1,4 @@ """passbook CertificateKeyPair administration""" -from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import ( PermissionRequiredMixin as DjangoPermissionRequiredMixin, @@ -7,9 +6,10 @@ from django.contrib.auth.mixins import ( from django.contrib.messages.views import SuccessMessageMixin from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, ListView, UpdateView +from django.views.generic import ListView, UpdateView from guardian.mixins import PermissionListMixin, PermissionRequiredMixin +from passbook.admin.views.utils import DeleteMessageView from passbook.crypto.forms import CertificateKeyPairForm from passbook.crypto.models import CertificateKeyPair from passbook.lib.views import CreateAssignPermView @@ -41,10 +41,6 @@ class CertificateKeyPairCreateView( success_url = reverse_lazy("passbook_admin:certificate_key_pair") success_message = _("Successfully created CertificateKeyPair") - def get_context_data(self, **kwargs): - kwargs["type"] = "Certificate-Key Pair" - return super().get_context_data(**kwargs) - class CertificateKeyPairUpdateView( SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView @@ -61,7 +57,7 @@ class CertificateKeyPairUpdateView( class CertificateKeyPairDeleteView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView + LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView ): """Delete certificatekeypair""" @@ -71,7 +67,3 @@ class CertificateKeyPairDeleteView( template_name = "generic/delete.html" success_url = reverse_lazy("passbook_admin:certificate_key_pair") success_message = _("Successfully deleted Certificate-Key Pair") - - def delete(self, request, *args, **kwargs): - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) diff --git a/passbook/admin/views/flows.py b/passbook/admin/views/flows.py index 0585c11b7..91e2910d6 100644 --- a/passbook/admin/views/flows.py +++ b/passbook/admin/views/flows.py @@ -1,5 +1,4 @@ """passbook Flow administration""" -from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import ( PermissionRequiredMixin as DjangoPermissionRequiredMixin, @@ -8,9 +7,10 @@ from django.contrib.messages.views import SuccessMessageMixin from django.http import HttpRequest, HttpResponse from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, DetailView, ListView, UpdateView +from django.views.generic import DetailView, ListView, UpdateView from guardian.mixins import PermissionListMixin, PermissionRequiredMixin +from passbook.admin.views.utils import DeleteMessageView from passbook.flows.forms import FlowForm from passbook.flows.models import Flow from passbook.flows.planner import PLAN_CONTEXT_PENDING_USER @@ -45,9 +45,30 @@ class FlowCreateView( success_url = reverse_lazy("passbook_admin:flows") success_message = _("Successfully created Flow") - def get_context_data(self, **kwargs): - kwargs["type"] = "Flow" - return super().get_context_data(**kwargs) + +class FlowUpdateView( + SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView +): + """Update flow""" + + model = Flow + form_class = FlowForm + permission_required = "passbook_flows.change_flow" + + template_name = "generic/update.html" + success_url = reverse_lazy("passbook_admin:flows") + success_message = _("Successfully updated Flow") + + +class FlowDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView): + """Delete flow""" + + model = Flow + permission_required = "passbook_flows.delete_flow" + + template_name = "generic/delete.html" + success_url = reverse_lazy("passbook_admin:flows") + success_message = _("Successfully deleted Flow") class FlowDebugExecuteView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): @@ -67,34 +88,3 @@ class FlowDebugExecuteView(LoginRequiredMixin, PermissionRequiredMixin, DetailVi return redirect_with_qs( "passbook_flows:flow-executor-shell", self.request.GET, flow_slug=flow.slug, ) - - -class FlowUpdateView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView -): - """Update flow""" - - model = Flow - form_class = FlowForm - permission_required = "passbook_flows.change_flow" - - template_name = "generic/update.html" - success_url = reverse_lazy("passbook_admin:flows") - success_message = _("Successfully updated Flow") - - -class FlowDeleteView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView -): - """Delete flow""" - - model = Flow - permission_required = "passbook_flows.delete_flow" - - template_name = "generic/delete.html" - success_url = reverse_lazy("passbook_admin:flows") - success_message = _("Successfully deleted Flow") - - def delete(self, request, *args, **kwargs): - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) diff --git a/passbook/admin/views/groups.py b/passbook/admin/views/groups.py index 4a5c91357..833949fd3 100644 --- a/passbook/admin/views/groups.py +++ b/passbook/admin/views/groups.py @@ -1,5 +1,4 @@ """passbook Group administration""" -from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import ( PermissionRequiredMixin as DjangoPermissionRequiredMixin, @@ -7,9 +6,10 @@ from django.contrib.auth.mixins import ( from django.contrib.messages.views import SuccessMessageMixin from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, ListView, UpdateView +from django.views.generic import ListView, UpdateView from guardian.mixins import PermissionListMixin, PermissionRequiredMixin +from passbook.admin.views.utils import DeleteMessageView from passbook.core.forms.groups import GroupForm from passbook.core.models import Group from passbook.lib.views import CreateAssignPermView @@ -41,10 +41,6 @@ class GroupCreateView( success_url = reverse_lazy("passbook_admin:groups") success_message = _("Successfully created Group") - def get_context_data(self, **kwargs): - kwargs["type"] = "Group" - return super().get_context_data(**kwargs) - class GroupUpdateView( SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView @@ -60,7 +56,7 @@ class GroupUpdateView( success_message = _("Successfully updated Group") -class GroupDeleteView(SuccessMessageMixin, LoginRequiredMixin, DeleteView): +class GroupDeleteView(LoginRequiredMixin, DeleteMessageView): """Delete group""" model = Group @@ -68,7 +64,3 @@ class GroupDeleteView(SuccessMessageMixin, LoginRequiredMixin, DeleteView): template_name = "generic/delete.html" success_url = reverse_lazy("passbook_admin:groups") success_message = _("Successfully deleted Group") - - def delete(self, request, *args, **kwargs): - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) diff --git a/passbook/admin/views/policies.py b/passbook/admin/views/policies.py index 76196e70e..ac04ef537 100644 --- a/passbook/admin/views/policies.py +++ b/passbook/admin/views/policies.py @@ -8,22 +8,25 @@ from django.contrib.auth.mixins import ( ) from django.contrib.messages.views import SuccessMessageMixin from django.db.models import QuerySet -from django.forms import Form -from django.http import Http404, HttpRequest, HttpResponse +from django.http import HttpResponse from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, FormView, ListView, UpdateView +from django.views.generic import FormView from django.views.generic.detail import DetailView from guardian.mixins import PermissionListMixin, PermissionRequiredMixin from passbook.admin.forms.policies import PolicyTestForm -from passbook.lib.utils.reflection import all_subclasses, path_to_class -from passbook.lib.views import CreateAssignPermView +from passbook.admin.views.utils import ( + DeleteMessageView, + InheritanceCreateView, + InheritanceListView, + InheritanceUpdateView, +) from passbook.policies.models import Policy, PolicyBinding from passbook.policies.process import PolicyProcess, PolicyRequest -class PolicyListView(LoginRequiredMixin, PermissionListMixin, ListView): +class PolicyListView(LoginRequiredMixin, PermissionListMixin, InheritanceListView): """Show list of all policies""" model = Policy @@ -32,19 +35,12 @@ class PolicyListView(LoginRequiredMixin, PermissionListMixin, ListView): ordering = "name" template_name = "administration/policy/list.html" - def get_context_data(self, **kwargs: Any) -> Dict[str, Any]: - kwargs["types"] = {x.__name__: x for x in all_subclasses(Policy)} - return super().get_context_data(**kwargs) - - def get_queryset(self) -> QuerySet: - return super().get_queryset().select_subclasses() - class PolicyCreateView( SuccessMessageMixin, LoginRequiredMixin, DjangoPermissionRequiredMixin, - CreateAssignPermView, + InheritanceCreateView, ): """Create new Policy""" @@ -55,24 +51,12 @@ class PolicyCreateView( success_url = reverse_lazy("passbook_admin:policies") success_message = _("Successfully created Policy") - def get_context_data(self, **kwargs: Any) -> Dict[str, Any]: - kwargs = super().get_context_data(**kwargs) - form_cls = self.get_form_class() - if hasattr(form_cls, "template_name"): - kwargs["base_template"] = form_cls.template_name - return kwargs - - def get_form_class(self) -> Form: - policy_type = self.request.GET.get("type") - try: - model = next(x for x in all_subclasses(Policy) if x.__name__ == policy_type) - except StopIteration as exc: - raise Http404 from exc - return path_to_class(model.form) - class PolicyUpdateView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView + SuccessMessageMixin, + LoginRequiredMixin, + PermissionRequiredMixin, + InheritanceUpdateView, ): """Update policy""" @@ -83,27 +67,8 @@ class PolicyUpdateView( success_url = reverse_lazy("passbook_admin:policies") success_message = _("Successfully updated Policy") - def get_context_data(self, **kwargs: Any) -> Dict[str, Any]: - kwargs = super().get_context_data(**kwargs) - form_cls = self.get_form_class() - if hasattr(form_cls, "template_name"): - kwargs["base_template"] = form_cls.template_name - return kwargs - def get_form_class(self) -> Form: - form_class_path = self.get_object().form - form_class = path_to_class(form_class_path) - return form_class - - def get_object(self, queryset=None) -> Policy: - return ( - Policy.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first() - ) - - -class PolicyDeleteView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView -): +class PolicyDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView): """Delete policy""" model = Policy @@ -113,15 +78,6 @@ class PolicyDeleteView( success_url = reverse_lazy("passbook_admin:policies") success_message = _("Successfully deleted Policy") - def get_object(self, queryset=None) -> Policy: - return ( - Policy.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first() - ) - - def delete(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) - class PolicyTestView(LoginRequiredMixin, DetailView, PermissionRequiredMixin, FormView): """View to test policy(s)""" diff --git a/passbook/admin/views/policies_bindings.py b/passbook/admin/views/policies_bindings.py index b2d34045c..058f78ef1 100644 --- a/passbook/admin/views/policies_bindings.py +++ b/passbook/admin/views/policies_bindings.py @@ -1,5 +1,4 @@ """passbook PolicyBinding administration""" -from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import ( PermissionRequiredMixin as DjangoPermissionRequiredMixin, @@ -7,9 +6,10 @@ from django.contrib.auth.mixins import ( from django.contrib.messages.views import SuccessMessageMixin from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, ListView, UpdateView +from django.views.generic import ListView, UpdateView from guardian.mixins import PermissionListMixin, PermissionRequiredMixin +from passbook.admin.views.utils import DeleteMessageView from passbook.lib.views import CreateAssignPermView from passbook.policies.forms import PolicyBindingForm from passbook.policies.models import PolicyBinding @@ -55,16 +55,9 @@ class PolicyBindingUpdateView( success_url = reverse_lazy("passbook_admin:policies-bindings") success_message = _("Successfully updated PolicyBinding") - def get_context_data(self, **kwargs): - kwargs = super().get_context_data(**kwargs) - form_cls = self.get_form_class() - if hasattr(form_cls, "template_name"): - kwargs["base_template"] = form_cls.template_name - return kwargs - class PolicyBindingDeleteView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView + LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView ): """Delete policybinding""" @@ -74,7 +67,3 @@ class PolicyBindingDeleteView( template_name = "generic/delete.html" success_url = reverse_lazy("passbook_admin:policies-bindings") success_message = _("Successfully deleted PolicyBinding") - - def delete(self, request, *args, **kwargs): - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) diff --git a/passbook/admin/views/property_mapping.py b/passbook/admin/views/property_mapping.py index 0f3d9ffa9..3ba8ad47e 100644 --- a/passbook/admin/views/property_mapping.py +++ b/passbook/admin/views/property_mapping.py @@ -1,22 +1,25 @@ """passbook PropertyMapping administration""" -from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import ( PermissionRequiredMixin as DjangoPermissionRequiredMixin, ) from django.contrib.messages.views import SuccessMessageMixin -from django.http import Http404 from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, ListView, UpdateView from guardian.mixins import PermissionListMixin, PermissionRequiredMixin +from passbook.admin.views.utils import ( + DeleteMessageView, + InheritanceCreateView, + InheritanceListView, + InheritanceUpdateView, +) from passbook.core.models import PropertyMapping -from passbook.lib.utils.reflection import all_subclasses, path_to_class -from passbook.lib.views import CreateAssignPermView -class PropertyMappingListView(LoginRequiredMixin, PermissionListMixin, ListView): +class PropertyMappingListView( + LoginRequiredMixin, PermissionListMixin, InheritanceListView +): """Show list of all property_mappings""" model = PropertyMapping @@ -25,19 +28,12 @@ class PropertyMappingListView(LoginRequiredMixin, PermissionListMixin, ListView) ordering = "name" paginate_by = 40 - def get_context_data(self, **kwargs): - kwargs["types"] = {x.__name__: x for x in all_subclasses(PropertyMapping)} - return super().get_context_data(**kwargs) - - def get_queryset(self): - return super().get_queryset().select_subclasses() - class PropertyMappingCreateView( SuccessMessageMixin, LoginRequiredMixin, DjangoPermissionRequiredMixin, - CreateAssignPermView, + InheritanceCreateView, ): """Create new PropertyMapping""" @@ -48,38 +44,12 @@ class PropertyMappingCreateView( success_url = reverse_lazy("passbook_admin:property-mappings") success_message = _("Successfully created Property Mapping") - def get_context_data(self, **kwargs): - kwargs = super().get_context_data(**kwargs) - property_mapping_type = self.request.GET.get("type") - try: - model = next( - x - for x in all_subclasses(PropertyMapping) - if x.__name__ == property_mapping_type - ) - except StopIteration as exc: - raise Http404 from exc - kwargs["type"] = model._meta.verbose_name - form_cls = self.get_form_class() - if hasattr(form_cls, "template_name"): - kwargs["base_template"] = form_cls.template_name - return kwargs - - def get_form_class(self): - property_mapping_type = self.request.GET.get("type") - try: - model = next( - x - for x in all_subclasses(PropertyMapping) - if x.__name__ == property_mapping_type - ) - except StopIteration as exc: - raise Http404 from exc - return path_to_class(model.form) - class PropertyMappingUpdateView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView + SuccessMessageMixin, + LoginRequiredMixin, + PermissionRequiredMixin, + InheritanceUpdateView, ): """Update property_mapping""" @@ -90,28 +60,9 @@ class PropertyMappingUpdateView( success_url = reverse_lazy("passbook_admin:property-mappings") success_message = _("Successfully updated Property Mapping") - def get_context_data(self, **kwargs): - kwargs = super().get_context_data(**kwargs) - form_cls = self.get_form_class() - if hasattr(form_cls, "template_name"): - kwargs["base_template"] = form_cls.template_name - return kwargs - - def get_form_class(self): - form_class_path = self.get_object().form - form_class = path_to_class(form_class_path) - return form_class - - def get_object(self, queryset=None): - return ( - PropertyMapping.objects.filter(pk=self.kwargs.get("pk")) - .select_subclasses() - .first() - ) - class PropertyMappingDeleteView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView + LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView ): """Delete property_mapping""" @@ -121,14 +72,3 @@ class PropertyMappingDeleteView( template_name = "generic/delete.html" success_url = reverse_lazy("passbook_admin:property-mappings") success_message = _("Successfully deleted Property Mapping") - - def get_object(self, queryset=None): - return ( - PropertyMapping.objects.filter(pk=self.kwargs.get("pk")) - .select_subclasses() - .first() - ) - - def delete(self, request, *args, **kwargs): - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) diff --git a/passbook/admin/views/providers.py b/passbook/admin/views/providers.py index da9a1c761..e4dffa264 100644 --- a/passbook/admin/views/providers.py +++ b/passbook/admin/views/providers.py @@ -1,22 +1,23 @@ """passbook Provider administration""" -from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import ( PermissionRequiredMixin as DjangoPermissionRequiredMixin, ) from django.contrib.messages.views import SuccessMessageMixin -from django.http import Http404 from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, ListView, UpdateView from guardian.mixins import PermissionListMixin, PermissionRequiredMixin +from passbook.admin.views.utils import ( + DeleteMessageView, + InheritanceCreateView, + InheritanceListView, + InheritanceUpdateView, +) from passbook.core.models import Provider -from passbook.lib.utils.reflection import all_subclasses, path_to_class -from passbook.lib.views import CreateAssignPermView -class ProviderListView(LoginRequiredMixin, PermissionListMixin, ListView): +class ProviderListView(LoginRequiredMixin, PermissionListMixin, InheritanceListView): """Show list of all providers""" model = Provider @@ -25,19 +26,12 @@ class ProviderListView(LoginRequiredMixin, PermissionListMixin, ListView): paginate_by = 10 ordering = "id" - def get_context_data(self, **kwargs): - kwargs["types"] = {x.__name__: x for x in all_subclasses(Provider)} - return super().get_context_data(**kwargs) - - def get_queryset(self): - return super().get_queryset().select_subclasses() - class ProviderCreateView( SuccessMessageMixin, LoginRequiredMixin, DjangoPermissionRequiredMixin, - CreateAssignPermView, + InheritanceCreateView, ): """Create new Provider""" @@ -48,19 +42,12 @@ class ProviderCreateView( success_url = reverse_lazy("passbook_admin:providers") success_message = _("Successfully created Provider") - def get_form_class(self): - provider_type = self.request.GET.get("type") - try: - model = next( - x for x in all_subclasses(Provider) if x.__name__ == provider_type - ) - except StopIteration as exc: - raise Http404 from exc - return path_to_class(model.form) - class ProviderUpdateView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView + SuccessMessageMixin, + LoginRequiredMixin, + PermissionRequiredMixin, + InheritanceUpdateView, ): """Update provider""" @@ -71,21 +58,9 @@ class ProviderUpdateView( success_url = reverse_lazy("passbook_admin:providers") success_message = _("Successfully updated Provider") - def get_form_class(self): - form_class_path = self.get_object().form - form_class = path_to_class(form_class_path) - return form_class - - def get_object(self, queryset=None): - return ( - Provider.objects.filter(pk=self.kwargs.get("pk")) - .select_subclasses() - .first() - ) - class ProviderDeleteView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView + LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView ): """Delete provider""" @@ -95,14 +70,3 @@ class ProviderDeleteView( template_name = "generic/delete.html" success_url = reverse_lazy("passbook_admin:providers") success_message = _("Successfully deleted Provider") - - def get_object(self, queryset=None): - return ( - Provider.objects.filter(pk=self.kwargs.get("pk")) - .select_subclasses() - .first() - ) - - def delete(self, request, *args, **kwargs): - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) diff --git a/passbook/admin/views/sources.py b/passbook/admin/views/sources.py index a8751be9f..41a87aa68 100644 --- a/passbook/admin/views/sources.py +++ b/passbook/admin/views/sources.py @@ -1,22 +1,23 @@ """passbook Source administration""" -from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import ( PermissionRequiredMixin as DjangoPermissionRequiredMixin, ) from django.contrib.messages.views import SuccessMessageMixin -from django.http import Http404 from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, ListView, UpdateView from guardian.mixins import PermissionListMixin, PermissionRequiredMixin +from passbook.admin.views.utils import ( + DeleteMessageView, + InheritanceCreateView, + InheritanceListView, + InheritanceUpdateView, +) from passbook.core.models import Source -from passbook.lib.utils.reflection import all_subclasses, path_to_class -from passbook.lib.views import CreateAssignPermView -class SourceListView(LoginRequiredMixin, PermissionListMixin, ListView): +class SourceListView(LoginRequiredMixin, PermissionListMixin, InheritanceListView): """Show list of all sources""" model = Source @@ -25,19 +26,12 @@ class SourceListView(LoginRequiredMixin, PermissionListMixin, ListView): paginate_by = 40 template_name = "administration/source/list.html" - def get_context_data(self, **kwargs): - kwargs["types"] = {x.__name__: x for x in all_subclasses(Source)} - return super().get_context_data(**kwargs) - - def get_queryset(self): - return super().get_queryset().select_subclasses() - class SourceCreateView( SuccessMessageMixin, LoginRequiredMixin, DjangoPermissionRequiredMixin, - CreateAssignPermView, + InheritanceCreateView, ): """Create new Source""" @@ -48,17 +42,12 @@ class SourceCreateView( success_url = reverse_lazy("passbook_admin:sources") success_message = _("Successfully created Source") - def get_form_class(self): - source_type = self.request.GET.get("type") - try: - model = next(x for x in all_subclasses(Source) if x.__name__ == source_type) - except StopIteration as exc: - raise Http404 from exc - return path_to_class(model.form) - class SourceUpdateView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView + SuccessMessageMixin, + LoginRequiredMixin, + PermissionRequiredMixin, + InheritanceUpdateView, ): """Update source""" @@ -69,20 +58,8 @@ class SourceUpdateView( success_url = reverse_lazy("passbook_admin:sources") success_message = _("Successfully updated Source") - def get_form_class(self): - form_class_path = self.get_object().form - form_class = path_to_class(form_class_path) - return form_class - def get_object(self, queryset=None): - return ( - Source.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first() - ) - - -class SourceDeleteView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView -): +class SourceDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView): """Delete source""" model = Source @@ -91,12 +68,3 @@ class SourceDeleteView( template_name = "generic/delete.html" success_url = reverse_lazy("passbook_admin:sources") success_message = _("Successfully deleted Source") - - def get_object(self, queryset=None): - return ( - Source.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first() - ) - - def delete(self, request, *args, **kwargs): - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) diff --git a/passbook/admin/views/stages.py b/passbook/admin/views/stages.py index 03ee9f549..9451cb2d0 100644 --- a/passbook/admin/views/stages.py +++ b/passbook/admin/views/stages.py @@ -1,22 +1,23 @@ """passbook Stage administration""" -from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import ( PermissionRequiredMixin as DjangoPermissionRequiredMixin, ) from django.contrib.messages.views import SuccessMessageMixin -from django.http import Http404 from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, ListView, UpdateView from guardian.mixins import PermissionListMixin, PermissionRequiredMixin +from passbook.admin.views.utils import ( + DeleteMessageView, + InheritanceCreateView, + InheritanceListView, + InheritanceUpdateView, +) from passbook.flows.models import Stage -from passbook.lib.utils.reflection import all_subclasses, path_to_class -from passbook.lib.views import CreateAssignPermView -class StageListView(LoginRequiredMixin, PermissionListMixin, ListView): +class StageListView(LoginRequiredMixin, PermissionListMixin, InheritanceListView): """Show list of all stages""" model = Stage @@ -25,19 +26,12 @@ class StageListView(LoginRequiredMixin, PermissionListMixin, ListView): ordering = "name" paginate_by = 40 - def get_context_data(self, **kwargs): - kwargs["types"] = {x.__name__: x for x in all_subclasses(Stage)} - return super().get_context_data(**kwargs) - - def get_queryset(self): - return super().get_queryset().select_subclasses() - class StageCreateView( SuccessMessageMixin, LoginRequiredMixin, DjangoPermissionRequiredMixin, - CreateAssignPermView, + InheritanceCreateView, ): """Create new Stage""" @@ -48,24 +42,12 @@ class StageCreateView( success_url = reverse_lazy("passbook_admin:stages") success_message = _("Successfully created Stage") - def get_context_data(self, **kwargs): - kwargs = super().get_context_data(**kwargs) - stage_type = self.request.GET.get("type") - model = next(x for x in all_subclasses(Stage) if x.__name__ == stage_type) - kwargs["type"] = model._meta.verbose_name - return kwargs - - def get_form_class(self): - stage_type = self.request.GET.get("type") - try: - model = next(x for x in all_subclasses(Stage) if x.__name__ == stage_type) - except StopIteration as exc: - raise Http404 from exc - return path_to_class(model.form) - class StageUpdateView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView + SuccessMessageMixin, + LoginRequiredMixin, + PermissionRequiredMixin, + InheritanceUpdateView, ): """Update stage""" @@ -75,20 +57,8 @@ class StageUpdateView( success_url = reverse_lazy("passbook_admin:stages") success_message = _("Successfully updated Stage") - def get_form_class(self): - form_class_path = self.get_object().form - form_class = path_to_class(form_class_path) - return form_class - def get_object(self, queryset=None): - return ( - Stage.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first() - ) - - -class StageDeleteView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView -): +class StageDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView): """Delete stage""" model = Stage @@ -96,12 +66,3 @@ class StageDeleteView( permission_required = "passbook_flows.delete_stage" success_url = reverse_lazy("passbook_admin:stages") success_message = _("Successfully deleted Stage") - - def get_object(self, queryset=None): - return ( - Stage.objects.filter(pk=self.kwargs.get("pk")).select_subclasses().first() - ) - - def delete(self, request, *args, **kwargs): - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) diff --git a/passbook/admin/views/stages_bindings.py b/passbook/admin/views/stages_bindings.py index 65433a179..cfe86816c 100644 --- a/passbook/admin/views/stages_bindings.py +++ b/passbook/admin/views/stages_bindings.py @@ -1,5 +1,4 @@ """passbook StageBinding administration""" -from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import ( PermissionRequiredMixin as DjangoPermissionRequiredMixin, @@ -7,9 +6,10 @@ from django.contrib.auth.mixins import ( from django.contrib.messages.views import SuccessMessageMixin from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, ListView, UpdateView +from django.views.generic import ListView, UpdateView from guardian.mixins import PermissionListMixin, PermissionRequiredMixin +from passbook.admin.views.utils import DeleteMessageView from passbook.flows.forms import FlowStageBindingForm from passbook.flows.models import FlowStageBinding from passbook.lib.views import CreateAssignPermView @@ -41,13 +41,6 @@ class StageBindingCreateView( success_url = reverse_lazy("passbook_admin:stage-bindings") success_message = _("Successfully created StageBinding") - def get_context_data(self, **kwargs): - kwargs = super().get_context_data(**kwargs) - form_cls = self.get_form_class() - if hasattr(form_cls, "template_name"): - kwargs["base_template"] = form_cls.template_name - return kwargs - class StageBindingUpdateView( SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView @@ -62,16 +55,9 @@ class StageBindingUpdateView( success_url = reverse_lazy("passbook_admin:stage-bindings") success_message = _("Successfully updated StageBinding") - def get_context_data(self, **kwargs): - kwargs = super().get_context_data(**kwargs) - form_cls = self.get_form_class() - if hasattr(form_cls, "template_name"): - kwargs["base_template"] = form_cls.template_name - return kwargs - class StageBindingDeleteView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView + LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView ): """Delete FlowStageBinding""" @@ -81,7 +67,3 @@ class StageBindingDeleteView( template_name = "generic/delete.html" success_url = reverse_lazy("passbook_admin:stage-bindings") success_message = _("Successfully deleted FlowStageBinding") - - def delete(self, request, *args, **kwargs): - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) diff --git a/passbook/admin/views/stages_invitations.py b/passbook/admin/views/stages_invitations.py index 255c12d84..cfca9e5ae 100644 --- a/passbook/admin/views/stages_invitations.py +++ b/passbook/admin/views/stages_invitations.py @@ -1,5 +1,4 @@ """passbook Invitation administration""" -from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import ( PermissionRequiredMixin as DjangoPermissionRequiredMixin, @@ -8,9 +7,10 @@ from django.contrib.messages.views import SuccessMessageMixin from django.http import HttpResponseRedirect from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, ListView +from django.views.generic import ListView from guardian.mixins import PermissionListMixin, PermissionRequiredMixin +from passbook.admin.views.utils import DeleteMessageView from passbook.core.signals import invitation_created from passbook.lib.views import CreateAssignPermView from passbook.stages.invitation.forms import InvitationForm @@ -43,10 +43,6 @@ class InvitationCreateView( success_url = reverse_lazy("passbook_admin:stage-invitations") success_message = _("Successfully created Invitation") - def get_context_data(self, **kwargs): - kwargs["type"] = "Invitation" - return super().get_context_data(**kwargs) - def form_valid(self, form): obj = form.save(commit=False) obj.created_by = self.request.user @@ -56,7 +52,7 @@ class InvitationCreateView( class InvitationDeleteView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView + LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView ): """Delete invitation""" @@ -66,7 +62,3 @@ class InvitationDeleteView( template_name = "generic/delete.html" success_url = reverse_lazy("passbook_admin:stage-invitations") success_message = _("Successfully deleted Invitation") - - def delete(self, request, *args, **kwargs): - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) diff --git a/passbook/admin/views/stages_prompts.py b/passbook/admin/views/stages_prompts.py index 5614f206b..74b3c3aff 100644 --- a/passbook/admin/views/stages_prompts.py +++ b/passbook/admin/views/stages_prompts.py @@ -1,5 +1,4 @@ """passbook Prompt administration""" -from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import ( PermissionRequiredMixin as DjangoPermissionRequiredMixin, @@ -7,9 +6,10 @@ from django.contrib.auth.mixins import ( from django.contrib.messages.views import SuccessMessageMixin from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, ListView, UpdateView +from django.views.generic import ListView, UpdateView from guardian.mixins import PermissionListMixin, PermissionRequiredMixin +from passbook.admin.views.utils import DeleteMessageView from passbook.lib.views import CreateAssignPermView from passbook.stages.prompt.forms import PromptAdminForm from passbook.stages.prompt.models import Prompt @@ -41,10 +41,6 @@ class PromptCreateView( success_url = reverse_lazy("passbook_admin:stage-prompts") success_message = _("Successfully created Prompt") - def get_context_data(self, **kwargs): - kwargs["type"] = "Prompt" - return super().get_context_data(**kwargs) - class PromptUpdateView( SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, UpdateView @@ -60,9 +56,7 @@ class PromptUpdateView( success_message = _("Successfully updated Prompt") -class PromptDeleteView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView -): +class PromptDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView): """Delete prompt""" model = Prompt @@ -71,7 +65,3 @@ class PromptDeleteView( template_name = "generic/delete.html" success_url = reverse_lazy("passbook_admin:stage-prompts") success_message = _("Successfully deleted Prompt") - - def delete(self, request, *args, **kwargs): - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) diff --git a/passbook/admin/views/tokens.py b/passbook/admin/views/tokens.py index 58cf70f46..7b8e1c4b2 100644 --- a/passbook/admin/views/tokens.py +++ b/passbook/admin/views/tokens.py @@ -1,12 +1,11 @@ """passbook Token administration""" -from django.contrib import messages from django.contrib.auth.mixins import LoginRequiredMixin -from django.contrib.messages.views import SuccessMessageMixin from django.urls import reverse_lazy from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, ListView +from django.views.generic import ListView from guardian.mixins import PermissionListMixin, PermissionRequiredMixin +from passbook.admin.views.utils import DeleteMessageView from passbook.core.models import Token @@ -20,9 +19,7 @@ class TokenListView(LoginRequiredMixin, PermissionListMixin, ListView): template_name = "administration/token/list.html" -class TokenDeleteView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView -): +class TokenDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView): """Delete token""" model = Token @@ -31,7 +28,3 @@ class TokenDeleteView( template_name = "generic/delete.html" success_url = reverse_lazy("passbook_admin:tokens") success_message = _("Successfully deleted Token") - - def delete(self, request, *args, **kwargs): - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) diff --git a/passbook/admin/views/users.py b/passbook/admin/views/users.py index 6b010aea4..0e0d262d1 100644 --- a/passbook/admin/views/users.py +++ b/passbook/admin/views/users.py @@ -10,7 +10,7 @@ from django.shortcuts import redirect from django.urls import reverse, reverse_lazy from django.utils.http import urlencode from django.utils.translation import ugettext as _ -from django.views.generic import DeleteView, DetailView, ListView, UpdateView +from django.views.generic import DetailView, ListView, UpdateView from guardian.mixins import ( PermissionListMixin, PermissionRequiredMixin, @@ -18,6 +18,7 @@ from guardian.mixins import ( ) from passbook.admin.forms.users import UserForm +from passbook.admin.views.utils import DeleteMessageView from passbook.core.models import Token, User from passbook.lib.views import CreateAssignPermView @@ -68,9 +69,7 @@ class UserUpdateView( success_message = _("Successfully updated User") -class UserDeleteView( - SuccessMessageMixin, LoginRequiredMixin, PermissionRequiredMixin, DeleteView -): +class UserDeleteView(LoginRequiredMixin, PermissionRequiredMixin, DeleteMessageView): """Delete user""" model = User @@ -82,10 +81,6 @@ class UserDeleteView( success_url = reverse_lazy("passbook_admin:users") success_message = _("Successfully deleted User") - def delete(self, request: HttpRequest, *args, **kwargs) -> HttpResponse: - messages.success(self.request, self.success_message) - return super().delete(request, *args, **kwargs) - class UserPasswordResetView(LoginRequiredMixin, PermissionRequiredMixin, DetailView): """Get Password reset link for user""" diff --git a/passbook/admin/views/utils.py b/passbook/admin/views/utils.py new file mode 100644 index 000000000..1c2f5e74b --- /dev/null +++ b/passbook/admin/views/utils.py @@ -0,0 +1,73 @@ +"""passbook admin util views""" +from typing import Any, Dict + +from django.contrib import messages +from django.contrib.messages.views import SuccessMessageMixin +from django.http import Http404 +from django.views.generic import DeleteView, ListView, UpdateView + +from passbook.lib.utils.reflection import all_subclasses, path_to_class +from passbook.lib.views import CreateAssignPermView + + +class DeleteMessageView(SuccessMessageMixin, DeleteView): + """DeleteView which shows `self.success_message` on successful deletion""" + + def delete(self, request, *args, **kwargs): + messages.success(self.request, self.success_message) + return super().delete(request, *args, **kwargs) + + +class InheritanceListView(ListView): + """ListView for objects using InheritanceManager""" + + def get_context_data(self, **kwargs): + kwargs["types"] = {x.__name__: x for x in all_subclasses(self.model)} + return super().get_context_data(**kwargs) + + def get_queryset(self): + return super().get_queryset().select_subclasses() + + +class InheritanceCreateView(CreateAssignPermView): + """CreateView for objects using InheritanceManager""" + + def get_form_class(self): + provider_type = self.request.GET.get("type") + try: + model = next( + x for x in all_subclasses(self.model) if x.__name__ == provider_type + ) + except StopIteration as exc: + raise Http404 from exc + return path_to_class(model.form) + + def get_context_data(self, **kwargs: Any) -> Dict[str, Any]: + kwargs = super().get_context_data(**kwargs) + form_cls = self.get_form_class() + if hasattr(form_cls, "template_name"): + kwargs["base_template"] = form_cls.template_name + return kwargs + + +class InheritanceUpdateView(UpdateView): + """UpdateView for objects using InheritanceManager""" + + def get_context_data(self, **kwargs: Any) -> Dict[str, Any]: + kwargs = super().get_context_data(**kwargs) + form_cls = self.get_form_class() + if hasattr(form_cls, "template_name"): + kwargs["base_template"] = form_cls.template_name + return kwargs + + def get_form_class(self): + form_class_path = self.get_object().form + form_class = path_to_class(form_class_path) + return form_class + + def get_object(self, queryset=None): + return ( + self.model.objects.filter(pk=self.kwargs.get("pk")) + .select_subclasses() + .first() + )