summaryrefslogtreecommitdiff
path: root/ishtar_common/views.py
diff options
context:
space:
mode:
authorÉtienne Loks <etienne.loks@iggdrasil.net>2023-10-26 17:03:41 +0200
committerÉtienne Loks <etienne.loks@iggdrasil.net>2024-04-16 16:38:32 +0200
commitf4f482cd4074898f5344a3a078e27800bbd060fd (patch)
tree46a317f0f5de7b0177206ac5b965be794ff2b2af /ishtar_common/views.py
parente008dd87b2eafd88cec3d75d0b3b4c92ce891f23 (diff)
downloadIshtar-f4f482cd4074898f5344a3a078e27800bbd060fd.tar.bz2
Ishtar-f4f482cd4074898f5344a3a078e27800bbd060fd.zip
✨ refactoring import permissions
Diffstat (limited to 'ishtar_common/views.py')
-rw-r--r--ishtar_common/views.py147
1 files changed, 116 insertions, 31 deletions
diff --git a/ishtar_common/views.py b/ishtar_common/views.py
index b91f3202c..cd22d62eb 100644
--- a/ishtar_common/views.py
+++ b/ishtar_common/views.py
@@ -1490,7 +1490,28 @@ class NewImportView(BaseImportView, CreateView):
page_name = _("Import: create (table)")
-class EditImportView(BaseImportView, UpdateView):
+class ImportPermissionMixin:
+ permission_full = "change_import"
+ permission_own = "change_own_import"
+
+ def dispatch(self, request, *args, **kwargs):
+ import_pk = self.kwargs["pk"]
+ user = request.user
+ if not user or not user.ishtaruser:
+ return redirect("/")
+ model = models.ImportGroup if self.kwargs.get("group", None) else models.Import
+ q = model.query_can_access(user, perm=self.permission_full).filter(pk=import_pk)
+ if not user.is_superuser and not user.ishtaruser.has_right(self.permission_full):
+ if not user.ishtaruser.has_right(self.permission_own):
+ return redirect("/")
+ q = q.filter(Q(importer_type__users__pk=user.ishtaruser.pk))
+ if not q.count():
+ return redirect("/")
+ returned = super().dispatch(request, *args, **kwargs)
+ return returned
+
+
+class EditImportView(ImportPermissionMixin, BaseImportView, UpdateView):
page_name = _("Import: edit (table)")
@@ -1544,6 +1565,21 @@ class ImportPreFormView(IshtarMixin, LoginRequiredMixin, FormView):
return HttpResponseRedirect(self.get_success_url())
+def get_permissions_for_actions(user, imprt, owns, can_edit_all, can_delete_all, can_edit_own, can_delete_own):
+ can_edit, can_delete = False, False
+ is_own = None
+ if can_edit_own or can_delete_own: # need to check owner
+ if imprt.importer_type_id not in owns:
+ # "is_own" only query once by importer type
+ owns[imprt.importer_type.pk] = imprt.importer_type.is_own(user.ishtaruser)
+ is_own = owns[imprt.importer_type_id]
+ if can_edit_all or (can_edit_own and is_own):
+ can_edit = True
+ if can_delete_all or (can_delete_own and is_own):
+ can_delete = True
+ return can_edit, can_delete
+
+
class ImportListView(IshtarMixin, LoginRequiredMixin, ListView):
template_name = "ishtar/import_list.html"
model = models.Import
@@ -1555,15 +1591,31 @@ class ImportListView(IshtarMixin, LoginRequiredMixin, ListView):
def get_queryset(self):
user = self.request.user
- if not user.pk:
+ if not user.pk or not user.ishtaruser:
raise Http404()
- q1 = self._queryset_filter(self.model.query_can_access(user))
+ q1 = self._queryset_filter(self.model.query_can_access(user, "change_import"))
q1 = q1.filter(group__isnull=True).order_by("-end_date", "-creation_date", "-pk")
- q2 = self._queryset_filter(models.ImportGroup.query_can_access(user))
+ q2 = self._queryset_filter(models.ImportGroup.query_can_access(user, "change_import"))
q2 = q2.order_by("-end_date", "-creation_date", "-pk")
- return list(reversed(sorted(list(q1) + list(q2), key=lambda x: (x.end_date or x.creation_date))))
+ values = list(reversed(sorted(list(q1) + list(q2), key=lambda x: (x.end_date or x.creation_date))))
+ can_edit_all, can_delete_all, can_edit_own, can_delete_own = models.Import.get_permissions_for_actions(
+ user, self.request.session
+ )
+ imports = []
+ owns = {}
+ for imprt in values:
+ can_edit, can_delete = get_permissions_for_actions(
+ user, imprt, owns, can_edit_all, can_delete_all, can_edit_own, can_delete_own
+ )
+ imprt.action_list = imprt.get_actions(can_edit=can_edit, can_delete=can_delete)
+ imports.append(imprt)
+ return imports
def post(self, request, *args, **kwargs):
+ can_edit_all, can_delete_all, can_edit_own, can_delete_own = models.Import.get_permissions_for_actions(
+ request.user, request.session
+ )
+ owns = {}
for field in request.POST:
if not field.startswith("import-action-") or not request.POST[field]:
continue
@@ -1576,28 +1628,26 @@ class ImportListView(IshtarMixin, LoginRequiredMixin, ListView):
imprt = model.objects.get(pk=int(field.split("-")[-1]))
except (models.Import.DoesNotExist, ValueError):
continue
- if not self.request.user.is_superuser:
- # user can only edit his own imports
- user = models.IshtarUser.objects.get(pk=self.request.user.pk)
- if imprt.user != user:
- continue
+ can_edit, can_delete = get_permissions_for_actions(
+ request.user, imprt, owns, can_edit_all, can_delete_all, can_edit_own, can_delete_own
+ )
action = request.POST[field]
- if action == "D":
+ if can_delete and action == "D":
url = "import_group_delete" if is_group else "import_delete"
return HttpResponseRedirect(
reverse(url, kwargs={"pk": imprt.pk})
)
- elif action == "ED":
+ elif can_edit and action == "ED":
url = "edit_import_group" if is_group else "edit_import"
return HttpResponseRedirect(
reverse(url, kwargs={"pk": imprt.pk})
)
- elif action == "A":
+ elif can_edit and action == "A":
imprt.initialize(
user=self.request.user.ishtaruser,
session_key=request.session.session_key,
)
- elif action == "I":
+ elif can_edit and action == "I":
if settings.USE_BACKGROUND_TASK:
imprt.delayed_importation(request, request.session.session_key)
else:
@@ -1612,12 +1662,12 @@ class ImportListView(IshtarMixin, LoginRequiredMixin, ListView):
f"{imprt} - {e}",
"warning",
)
- elif action == "CH":
+ elif can_edit and action == "CH":
if settings.USE_BACKGROUND_TASK:
imprt.delayed_check_modified(request.session.session_key)
else:
imprt.check_modified()
- elif action == "IS":
+ elif can_edit and action == "IS":
if imprt.current_line is None:
imprt.current_line = imprt.skip_lines
imprt.save()
@@ -1626,19 +1676,37 @@ class ImportListView(IshtarMixin, LoginRequiredMixin, ListView):
"import_step_by_step", args=[imprt.pk, imprt.current_line + 1]
)
)
- elif action == "AC":
+ elif can_edit and action == "AC":
imprt.archive()
- elif action in ("F", "FE"):
+ elif can_edit and action in ("F", "FE"):
imprt.unarchive(action)
return HttpResponseRedirect(reverse(self.current_url))
def get_context_data(self, **kwargs):
dct = super().get_context_data(**kwargs)
+ add_import_perm = self.request.user.ishtaruser.has_right("add_import", session=self.request.session)
+ import_type_table = models.ImporterType.objects.filter(available=True, is_import=True, type='tab')
+ import_type_gis = models.ImporterType.objects.filter(available=True, is_import=True, type='gis')
+ import_type_group = models.ImporterGroup.objects.filter(available=True)
+ if not add_import_perm and self.request.user.ishtaruser.has_right("add_own_import",
+ session=self.request.session):
+ import_type_table = import_type_table.filter(users__pk=self.request.user.ishtaruser.pk)
+ import_type_gis = import_type_gis.filter(users__pk=self.request.user.ishtaruser.pk)
+ import_type_group = import_type_group.filter(users__pk=self.request.user.ishtaruser.pk)
+ add_import_perm = True
+ has_import_table, has_import_gis, has_import_group = False, False, False
+ if add_import_perm:
+ if import_type_table.count():
+ has_import_table = True
+ if import_type_gis.count():
+ has_import_gis = True
+ if import_type_group.count():
+ has_import_group = True
dct.update({
- "autorefresh_available": settings.USE_BACKGROUND_TASK,
- "has_import_table": models.ImporterType.objects.filter(available=True, is_import=True, type='tab').count(),
- "has_import_gis": models.ImporterType.objects.filter(available=True, is_import=True, type='gis').count(),
- "has_import_group": models.ImporterGroup.objects.filter(available=True).count(),
+ "has_import_table": has_import_table,
+ "has_import_gis": has_import_gis,
+ "has_import_group": has_import_group,
+ "can_create_import": has_import_table or has_import_gis or has_import_group,
})
return dct
@@ -2083,14 +2151,23 @@ def import_get_status(request, current_right=None):
"number_of_line": item.number_of_line,
"progress_percent": item.progress_percent,
})
- item_dct["actions"] = [(key, str(lbl)) for key, lbl in item.get_actions()]
+ can_edit_all, can_delete_all, can_edit_own, can_delete_own = models.Import.get_permissions_for_actions(
+ request.user
+ )
+ can_edit, can_delete = get_permissions_for_actions(
+ request.user, item, {}, can_edit_all, can_delete_all, can_edit_own, can_delete_own
+ )
+ item_dct["actions"] = [
+ (key, str(lbl))
+ for key, lbl in item.get_actions(can_edit=can_edit, can_delete=can_delete)
+ ]
response[key].append(item_dct)
data = json.dumps(response)
return HttpResponse(data, content_type="application/json")
-class ImportLinkView(IshtarMixin, LoginRequiredMixin, ModelFormSetView):
+class ImportMatchView(ImportPermissionMixin, IshtarMixin, LoginRequiredMixin, ModelFormSetView):
template_name = "ishtar/formset_import_match.html"
model = models.TargetKey
page_name = _("Link unmatched items")
@@ -2100,9 +2177,11 @@ class ImportLinkView(IshtarMixin, LoginRequiredMixin, ModelFormSetView):
form_class = forms.TargetKeyForm
formset_class = forms.TargetKeyFormset
max_fields = 250
+ permission_full = "change_import"
+ permission_own = "change_own_import"
def get_formset_kwargs(self):
- kwargs = super(ImportLinkView, self).get_formset_kwargs()
+ kwargs = super().get_formset_kwargs()
kwargs["user"] = self.request.user
return kwargs
@@ -2126,25 +2205,29 @@ class ImportLinkView(IshtarMixin, LoginRequiredMixin, ModelFormSetView):
return reverse("import_link_unmatched", args=[self.kwargs["pk"]])
-class ImportDeleteView(IshtarMixin, LoginRequiredMixin, DeleteView):
+class ImportDeleteView(ImportPermissionMixin, IshtarMixin, LoginRequiredMixin, DeleteView):
template_name = "ishtar/import_delete.html"
model = models.Import
page_name = _("Delete import")
+ permission_full = "delete_import"
+ permission_own = "delete_own_import"
def get_success_url(self):
return reverse("current_imports")
-class ImportGroupDeleteView(IshtarMixin, LoginRequiredMixin, DeleteView):
+class ImportGroupDeleteView(ImportPermissionMixin, IshtarMixin, LoginRequiredMixin, DeleteView):
template_name = "ishtar/import_delete.html"
model = models.ImportGroup
page_name = _("Delete import")
+ permission_full = "delete_import"
+ permission_own = "delete_own_import"
def get_success_url(self):
return reverse("current_imports")
-class ImportCSVView(IshtarMixin, LoginRequiredMixin, TemplateView):
+class ImportCSVView(ImportPermissionMixin, IshtarMixin, LoginRequiredMixin, TemplateView):
template_name = "ishtar/blocks/view_import_csv.html"
ATTRIBUTES = {
"source": "get_imported_values",
@@ -2158,13 +2241,15 @@ class ImportCSVView(IshtarMixin, LoginRequiredMixin, TemplateView):
"result": ("fa fa-th", _("Result")) ,
"match": ("fa fa-arrows-h", _("Match")),
}
+ permission_full = "view_import"
+ permission_own = "view_own_import"
def get(self, request, *args, **kwargs):
user = self.request.user
if not user.pk:
raise Http404()
model = models.ImportGroup if kwargs.get("group", None) else models.Import
- q = model.query_can_access(self.request.user).filter(pk=kwargs.get("pk", -1))
+ q = model.query_can_access(self.request.user, perm=self.permission_full).filter(pk=kwargs.get("pk", -1))
if not q.count():
raise Http404()
self.import_item = q.all()[0]
@@ -2208,7 +2293,7 @@ class ImportCSVView(IshtarMixin, LoginRequiredMixin, TemplateView):
return data
-def line_error(request, line_id):
+def line_error(request, line_id, current_right=None):
"""
Set or unset ignored state of a csv error file
"""
@@ -2219,7 +2304,7 @@ def line_error(request, line_id):
if not q.count():
return
line = q.all()[0]
- q = models.Import.query_can_access(request.user).filter(pk=line.import_item_id)
+ q = models.Import.query_can_access(request.user, perm="change_import").filter(pk=line.import_item_id)
if not q.count():
raise Http404()
line.ignored = not line.ignored