Use rules permissions in views and HTMX forms

This commit is contained in:
Tobias Kunze 2025-03-20 16:57:15 +01:00
parent 21ff6fe7d0
commit 31003c5c76
4 changed files with 51 additions and 22 deletions

View file

@ -9,10 +9,12 @@
{% partialdef org-name %}
<td>
{{ form.instance.name }}
{% if has_change_permission %}
<button class="btn btn-primary"
hx-get="{{ request.path }}?fragment=org-name-edit&hx-single-field=name"
hx-target="closest td"
hx-swap="outerHTML">{% translate "Edit" %}</button>
{% endif %}
</td>
{% endpartialdef org-name %}
{% partialdef org-name-edit %}

View file

@ -1,18 +1,18 @@
from django.conf import settings
from django.urls import reverse_lazy
from django.utils.functional import cached_property
from django.views.generic import TemplateView, UpdateView
from django.views.generic import TemplateView
from servala.core.models import User
from servala.frontend.forms.profile import UserProfileForm
from servala.frontend.views.mixins import HtmxMixin
from servala.frontend.views.mixins import HtmxUpdateView
class IndexView(TemplateView):
template_name = "frontend/index.html"
class ProfileView(HtmxMixin, UpdateView):
class ProfileView(HtmxUpdateView):
template_name = "frontend/profile.html"
form_class = UserProfileForm
success_url = reverse_lazy("frontend:profile")

View file

@ -1,14 +1,34 @@
from django.utils.functional import cached_property
from django.views.generic import TemplateView
from django.views.generic import UpdateView
from rules.contrib.views import AutoPermissionRequiredMixin
class HtmxMixin(TemplateView):
class HtmxUpdateView(AutoPermissionRequiredMixin, UpdateView):
fragments = []
@cached_property
def is_htmx(self):
return self.request.headers.get("HX-Request")
@property
def permission_type(self):
if self.request.method == "POST" or getattr(
self, "_test_write_permission", False
):
return "change"
return "view"
def has_change_permission(self):
self._test_write_permission = True
permission = self.get_permission_required()[0]
self._test_write_permission = False
return self.request.user.has_perm(permission, self.get_permission_object())
def get_context_data(self, **kwargs):
result = super().get_context_data(**kwargs)
result["has_change_permission"] = self.has_change_permission()
return result
def _get_fragment(self):
if self.request.method == "POST":
fragment = self.request.POST.get("fragment")

View file

@ -1,14 +1,16 @@
from django.shortcuts import redirect
from django.utils.functional import cached_property
from django.views.generic import FormView, TemplateView, UpdateView
from django.views.generic import CreateView, DetailView
from rules.contrib.views import AutoPermissionRequiredMixin
from servala.core.models import Organization
from servala.frontend.forms import OrganizationForm
from servala.frontend.views.mixins import HtmxMixin
from servala.frontend.views.mixins import HtmxUpdateView
class OrganizationCreateView(FormView):
class OrganizationCreateView(AutoPermissionRequiredMixin, CreateView):
form_class = OrganizationForm
model = Organization
template_name = "frontend/organizations/create.html"
def form_valid(self, form):
@ -18,27 +20,32 @@ class OrganizationCreateView(FormView):
return redirect(instance.urls.base)
class OrganizationDashboardView(TemplateView):
template_name = "frontend/organizations/dashboard.html"
class OrganizationUpdateView(HtmxMixin, UpdateView):
template_name = "frontend/organizations/update.html"
form_class = OrganizationForm
fragments = ("org-name", "org-name-edit")
class OrganizationViewMixin:
model = Organization
context_object_name = "organization"
def get_success_url(self):
return self.request.path
@cached_property
def organization(self):
return self.request.organization
def get_object(self):
return self.request.organization
return self.organization
@cached_property
def object(self):
return self.get_object()
def form_valid(self, form):
form.save()
return super().form_valid(form)
class OrganizationDashboardView(
AutoPermissionRequiredMixin, OrganizationViewMixin, DetailView
):
template_name = "frontend/organizations/dashboard.html"
class OrganizationUpdateView(OrganizationViewMixin, HtmxUpdateView):
template_name = "frontend/organizations/update.html"
form_class = OrganizationForm
fragments = ("org-name", "org-name-edit")
def get_success_url(self):
return self.request.path