summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2025-01-10 15:56:33 +0100
committerÉtienne Loks <etienne.loks@iggdrasil.net>2025-02-19 14:45:56 +0100
commit819c4386b554545ddcb5bddce6413e078335e7e4 (patch)
treeefd7bd03f457b764c9f475c02aa0b06255267fc5
parentf097ada4ae660c83aaebeffb3dbe2220bf9847c5 (diff)
downloadIshtar-819c4386b554545ddcb5bddce6413e078335e7e4.tar.bz2
Ishtar-819c4386b554545ddcb5bddce6413e078335e7e4.zip
🐛 permissions: manage quick add/modify forms (fix #6101)
-rw-r--r--ishtar_common/forms.py11
-rw-r--r--ishtar_common/views_item.py27
-rw-r--r--ishtar_common/widgets.py41
3 files changed, 60 insertions, 19 deletions
diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py
index b29c49c64..ffe44298c 100644
--- a/ishtar_common/forms.py
+++ b/ishtar_common/forms.py
@@ -41,7 +41,7 @@ from django.utils.safestring import mark_safe
from django.utils.text import slugify
from django.utils.translation import ugettext_lazy as _
-from bootstrap_datepicker.widgets import DatePicker, DATE_FORMAT, DateField
+from bootstrap_datepicker.widgets import DatePicker, DATE_FORMAT
from ishtar_common import models
from ishtar_common import widgets
from ishtar_common.utils import MultiValueDict
@@ -225,6 +225,15 @@ class CustomForm(BSForm):
self.base_field_keys = []
if not self._explicit_ordering:
self.custom_form_ordering()
+ self.autocomplete_widget_add_user()
+
+ def autocomplete_widget_add_user(self):
+ if not hasattr(self, "fields"):
+ return
+ for k in self.fields:
+ if not isinstance(self.fields[k].widget, widgets.JQueryAutoComplete):
+ continue
+ self.fields[k].widget.user = self.current_user
def _remove_fields(self, field_names):
"""
diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py
index 9f5755eaf..ae8c1cd47 100644
--- a/ishtar_common/views_item.py
+++ b/ishtar_common/views_item.py
@@ -216,11 +216,19 @@ def get_autocomplete_item(model, extra=None):
def check_permission(request, action_slug, obj=None):
+ if not request.user.ishtaruser:
+ return False
main_menu = Menu(request.user)
main_menu.init()
if action_slug not in main_menu.items:
- # TODO
- return True
+ # not an action -> a classic permission
+ if request.user.ishtaruser.has_permission(action_slug):
+ return True
+ if not obj:
+ return False
+ parts = action_slug.split("_")
+ action_slug = f"{parts[0]}_own_{'_'.join(parts[1:])}"
+ return request.user.ishtaruser.has_permission(action_slug, obj)
if obj:
return main_menu.items[action_slug].is_available(
request.user, obj
@@ -233,15 +241,17 @@ def new_qa_item(
callback=None
):
def func(request, parent_name, limits=""):
- model_name = model._meta.object_name
not_permitted_msg = ugettext("Operation not permitted.")
- if not check_permission(request, "add_" + model_name.lower()):
+ meta = model._meta
+ permission = f"{meta.app_label}.add_{meta.model_name}"
+ if not check_permission(request, permission):
return HttpResponse(not_permitted_msg)
slug = model.SLUG
if model.SLUG == "site":
slug = "archaeologicalsite"
url_slug = "new-" + slug
current_page_name = page_name[:]
+ model_name = model._meta.object_name
if not current_page_name:
current_page_name = _("New %s" % model_name.lower())
dct = {
@@ -276,13 +286,14 @@ def new_qa_item(
def get_short_html_detail(model):
def func(request, pk):
- model_name = model._meta.object_name
not_permitted_msg = ugettext("Operation not permitted.")
try:
item = model.objects.get(pk=pk)
except model.DoesNotExist:
return HttpResponse(not_permitted_msg)
- if not check_permission(request, "view_" + model_name.lower(), item):
+ meta = model._meta
+ permission = f"{meta.app_label}.view_{meta.model_name}"
+ if not check_permission(request, permission, item):
return HttpResponse(not_permitted_msg)
html = item.get_short_html_detail()
return HttpResponse(html)
@@ -299,7 +310,9 @@ def modify_qa_item(model, frm, callback=None):
item = model.objects.get(pk=pk)
except model.DoesNotExist:
return HttpResponse(not_permitted_msg)
- if not check_permission(request, "change_" + model_name.lower(), item):
+ meta = model._meta
+ permission = f"{meta.app_label}.change_{meta.model_name}"
+ if not check_permission(request, permission, item):
return HttpResponse(not_permitted_msg)
slug = model.SLUG
if model.SLUG == "site":
diff --git a/ishtar_common/widgets.py b/ishtar_common/widgets.py
index b9166f361..992ae533d 100644
--- a/ishtar_common/widgets.py
+++ b/ishtar_common/widgets.py
@@ -709,6 +709,7 @@ class JQueryAutoComplete(forms.TextInput):
self.source = source
self.associated_model = associated_model
self.tips = tips
+ self.user = None
self.options = None
if options and len(options) > 0:
@@ -849,16 +850,34 @@ class JQueryAutoComplete(forms.TextInput):
""".format(
attrs_hidden["id"], tips
)
- if self.modify:
- new += """
- <span class="input-group-append">
- <a href="#" id="{}-modify" class="modify-button input-group-text"
- onclick="{}_modify();">
- <i class="fa fa-pencil"></i></a>
- </span>""".format(
- attrs_hidden["id"], name.replace("-", "_")
- )
- if self.new:
+ meta = ""
+ if self.associated_model:
+ meta = self.associated_model._meta
+ base_permission = f"{meta.app_label}.{{}}_{meta.model_name}"
+ permission = base_permission.format("change")
+ own_permission = base_permission.format("change_own")
+ if self.modify and self.associated_model and self.user:
+ modify_ok = False
+ if self.user.has_permission(permission):
+ modify_ok = True
+ else:
+ try:
+ obj = self.associated_model.objects.get(pk=attrs_hidden["id"])
+ modify_ok = self.user.has_permission(own_permission, obj)
+ except self.associated_model.DoesNotExist:
+ pass
+ if modify_ok:
+ new += """
+ <span class="input-group-append">
+ <a href="#" id="{}-modify" class="modify-button input-group-text"
+ onclick="{}_modify();">
+ <i class="fa fa-pencil"></i></a>
+ </span>""".format(
+ attrs_hidden["id"], name.replace("-", "_")
+ )
+ permission = base_permission.format("add")
+ if self.new and self.associated_model and self.user and \
+ self.user.has_permission(permission):
limits = []
for k in self.limit:
limits.append(k + "__" + "-".join([str(v) for v in self.limit[k]]))
@@ -875,7 +894,7 @@ class JQueryAutoComplete(forms.TextInput):
onclick="dt_qa_open('{}', 'modal-dynamic-form-{}');">+</a>
</span>
""".format(
- url_new, model_name, model_name
+ url_new, model_name
)
new += "</div>"
detail = ""