diff options
author | Étienne Loks <etienne.loks@iggdrasil.net> | 2024-10-16 17:57:13 +0200 |
---|---|---|
committer | Étienne Loks <etienne.loks@iggdrasil.net> | 2025-02-19 14:43:48 +0100 |
commit | c93dd3812c53d21ab8517dc7af72e1d4b70a1b04 (patch) | |
tree | 2153d8fd121f7ecd08a31e4867d58a2eb3c9aab7 | |
parent | b8eef9b6aaed7ee097f8ea86174067f9ca42abd8 (diff) | |
download | Ishtar-c93dd3812c53d21ab8517dc7af72e1d4b70a1b04.tar.bz2 Ishtar-c93dd3812c53d21ab8517dc7af72e1d4b70a1b04.zip |
♻ permissions refactoring: refactor has_permission methods
41 files changed, 1331 insertions, 869 deletions
diff --git a/archaeological_context_records/ishtar_menu.py b/archaeological_context_records/ishtar_menu.py index 6d4ae1a57..488897aa9 100644 --- a/archaeological_context_records/ishtar_menu.py +++ b/archaeological_context_records/ishtar_menu.py @@ -23,7 +23,7 @@ from ishtar_common.menu_base import SectionItem, MenuItem from . import models -# be carreful: each access_controls must be relevant with check_rights in urls +# be carreful: each access_controls must be relevant with check_permissions in urls MENU_SECTIONS = [ ( @@ -38,21 +38,27 @@ MENU_SECTIONS = [ "record_search", _("Search"), model=models.ContextRecord, - access_controls=["view_contextrecord", "view_own_contextrecord"], + access_controls=[ + "archaeological_context_records.view_contextrecord", + "archaeological_context_records.view_own_contextrecord" + ], ), MenuItem( "record_creation", _("Creation"), model=models.ContextRecord, - access_controls=["add_contextrecord", "add_own_contextrecord"], + access_controls=[ + "archaeological_context_records.add_contextrecord", + "archaeological_context_records.add_own_contextrecord" + ], ), MenuItem( "record_modification", _("Modification"), model=models.ContextRecord, access_controls=[ - "change_contextrecord", - "change_own_contextrecord", + "archaeological_context_records.change_contextrecord", + "archaeological_context_records.change_own_contextrecord", ], ), MenuItem( @@ -60,8 +66,8 @@ MENU_SECTIONS = [ _("Deletion"), model=models.ContextRecord, access_controls=[ - "delete_contextrecord", - "delete_own_contextrecord", + "archaeological_context_records.delete_contextrecord", + "archaeological_context_records.delete_own_contextrecord", ], ), ], diff --git a/archaeological_context_records/models.py b/archaeological_context_records/models.py index ccc145c48..2611b7dfd 100644 --- a/archaeological_context_records/models.py +++ b/archaeological_context_records/models.py @@ -791,14 +791,20 @@ class ContextRecord( icon_class="fa fa-lock", text=_("Lock/Unlock"), target="many", - rights=["change_contextrecord", "change_own_contextrecord"], + rights=[ + "archaeological_context_records.change_contextrecord", + "archaeological_context_records.change_own_contextrecord" + ], ) QA_EDIT = QuickAction( url="contextrecord-qa-bulk-update", icon_class="fa fa-pencil", text=_("Bulk update"), target="many", - rights=["change_contextrecord", "change_own_contextrecord"], + rights=[ + "archaeological_context_records.change_contextrecord", + "archaeological_context_records.change_own_contextrecord" + ], ) QUICK_ACTIONS = [ QA_EDIT, @@ -808,7 +814,10 @@ class ContextRecord( icon_class="fa fa-clone", text=_("Duplicate"), target="one", - rights=["change_contextrecord", "change_own_contextrecord"], + rights=[ + "archaeological_context_records.change_contextrecord", + "archaeological_context_records.change_own_contextrecord" + ], ), ] SERIALIZE_EXCLUDE = MainItem.SERIALIZE_EXCLUDE + ["contextrecord"] @@ -1159,12 +1168,15 @@ class ContextRecord( actions = super().get_extra_actions(request) is_locked = hasattr(self, "is_locked") and self.is_locked(request.user) - can_edit_cr = self.can_do(request, "change_contextrecord") + can_edit_cr = self.can_do( + request, "archaeological_context_records.change_contextrecord" + ) profile = get_current_profile() - can_add_geo = profile.mapping and self.can_do(request, "add_geovectordata") + can_add_geo = profile.mapping and \ + self.can_do(request, "ishtar_common.add_geovectordata") if can_add_geo: actions.append(self.get_add_geo_action()) - can_create_find = self.can_do(request, "add_find") + can_create_find = self.can_do(request, "archaeological_finds.add_find") if can_create_find: actions += [ ( diff --git a/archaeological_context_records/urls.py b/archaeological_context_records/urls.py index 2b95db086..338f5bb2a 100644 --- a/archaeological_context_records/urls.py +++ b/archaeological_context_records/urls.py @@ -20,38 +20,42 @@ from django.conf.urls import url from django.urls import path -from ishtar_common.utils import check_rights +from ishtar_common.utils import check_permissions from archaeological_context_records import models, views, views_api -# be careful: each check_rights must be relevant with ishtar_menu +# be careful: each check_permissions must be relevant with ishtar_menu # forms urlpatterns = [ # Context records url( r"record_search/(?P<step>.+)?$", - check_rights(["view_contextrecord", "view_own_contextrecord"])( + check_permissions(["archaeological_context_records.view_contextrecord", + "archaeological_context_records.view_own_contextrecord"])( views.record_search_wizard ), name="record_search", ), url( r"contextrecord_search/(?P<step>.+)?$", - check_rights(["view_contextrecord", "view_own_contextrecord"])( + check_permissions(["archaeological_context_records.view_contextrecord", + "archaeological_context_records.view_own_contextrecord"])( views.record_search_wizard ), name="contextrecord_search", ), url( r"record_creation/(?P<step>.+)?$", - check_rights(["add_contextrecord", "add_own_contextrecord"])( + check_permissions(["archaeological_context_records.add_contextrecord", + "archaeological_context_records.add_own_contextrecord"])( views.record_creation_wizard ), name="record_creation", ), url( r"record_modification/(?P<step>.+)?$", - check_rights(["change_contextrecord", "change_own_contextrecord"])( + check_permissions(["archaeological_context_records.change_contextrecord", + "archaeological_context_records.change_own_contextrecord"])( views.record_modification_wizard ), name="record_modification", @@ -59,7 +63,8 @@ urlpatterns = [ url(r"record_modify/(?P<pk>.+)/$", views.record_modify, name="record_modify"), url( r"record_deletion/(?P<step>.+)?$", - check_rights(["change_contextrecord", "change_own_contextrecord"])( + check_permissions(["archaeological_context_records.change_contextrecord", + "archaeological_context_records.change_own_contextrecord"])( views.record_deletion_wizard ), name="record_deletion", @@ -151,14 +156,16 @@ urlpatterns = [ ), url( r"^context-record-relations-modify/(?P<pk>.+)/$", - check_rights(["change_contextrecord", "change_own_contextrecord"])( + check_permissions(["archaeological_context_records.change_contextrecord", + "archaeological_context_records.change_own_contextrecord"])( views.context_record_modify_relations ), name="context-record-relation-modify", ), url( r"^operation-qa-contextrecord/(?P<pks>[0-9]+)/$", - check_rights(["add_contextrecord", "add_own_contextrecord"])( + check_permissions(["archaeological_context_records.add_contextrecord", + "archaeological_context_records.add_own_contextrecord"])( views.QAOperationContextRecordView.as_view() ), name="operation-qa-contextrecord", @@ -171,21 +178,24 @@ urlpatterns = [ ), url( r"^contextrecord-qa-duplicate/(?P<pks>[0-9-]+)?/$", - check_rights(["change_contextrecord", "change_own_contextrecord"])( + check_permissions(["archaeological_context_records.change_contextrecord", + "archaeological_context_records.change_own_contextrecord"])( views.QAContextRecordDuplicateFormView.as_view() ), name="contextrecord-qa-duplicate", ), url( r"^contextrecord-qa-bulk-update/(?P<pks>[0-9-]+)?/$", - check_rights(["change_contextrecord", "change_own_contextrecord"])( + check_permissions(["archaeological_context_records.change_contextrecord", + "archaeological_context_records.change_own_contextrecord"])( views.QAContextRecordForm.as_view() ), name="contextrecord-qa-bulk-update", ), url( r"^contextrecord-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$", - check_rights(["change_contextrecord", "change_own_contextrecord"])( + check_permissions(["archaeological_context_records.change_contextrecord", + "archaeological_context_records.change_own_contextrecord"])( views.QAContextRecordForm.as_view() ), name="contextrecord-qa-bulk-update-confirm", diff --git a/archaeological_context_records/views.py b/archaeological_context_records/views.py index 15b2aee30..fdee2c459 100644 --- a/archaeological_context_records/views.py +++ b/archaeological_context_records/views.py @@ -51,11 +51,13 @@ revert_contextrecord = revert_item(models.ContextRecord) def autocomplete_contextrecord(request): - if not request.user.has_perm( - "archaeological_context_records.view_contextrecord", models.ContextRecord - ) and not request.user.has_perm( + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse(content_type="text/plain") + if not ishtaruser.has_permission( + "archaeological_context_records.view_contextrecord" + ) and not ishtaruser.has_permission( "archaeological_context_records.view_own_contextrecord", - models.ArchaeologicalSite, ): return HttpResponse(content_type="text/plain") if not request.GET.get("term"): @@ -258,7 +260,8 @@ class QAOperationContextRecordView(QAItemForm): icon_class="fa fa-plus", text=_("Add context record"), target="one", - rights=["add_contextrecord", "add_own_contextrecord"], + rights=["archaeological_context_records.add_contextrecord", + "archaeological_context_records.add_own_contextrecord"], ) def form_valid(self, form): diff --git a/archaeological_files/admin.py b/archaeological_files/admin.py index 206e97348..9ed26e68c 100644 --- a/archaeological_files/admin.py +++ b/archaeological_files/admin.py @@ -176,8 +176,10 @@ class CopyPriceAgreementAdmin(GeneralTypeAdmin): def copy_price_agreement(self, request): form = None - if not hasattr(request.user, "ishtaruser") or request.user.ishtaruser.has_right( - "change_priceagreement", session=request.session): + if not request.user.is_superuser and ( + not hasattr(request.user, "ishtaruser") or + not request.user.ishtaruser.has_permission( + "archaeological_files.change_priceagreement")): self.message_user( request, str(_("Cannot change price agreement.")) ) diff --git a/archaeological_files/ishtar_menu.py b/archaeological_files/ishtar_menu.py index bfdd72148..5541fd1d3 100644 --- a/archaeological_files/ishtar_menu.py +++ b/archaeological_files/ishtar_menu.py @@ -25,7 +25,7 @@ from archaeological_operations.models import AdministrativeAct from . import models -# be carreful: each access_controls must be relevant with check_rights in urls +# be carreful: each access_controls must be relevant with check_permissions in urls MENU_SECTIONS = [ ( @@ -40,31 +40,43 @@ MENU_SECTIONS = [ "file_search", _("Search"), model=models.File, - access_controls=["view_file", "view_own_file"], + access_controls=[ + "archaeological_files.view_file", + "archaeological_files.view_own_file" + ], ), MenuItem( "file_creation", _("Creation"), model=models.File, - access_controls=["add_file", "add_own_file"], + access_controls=[ + "archaeological_files.add_file", + "archaeological_files.add_own_file" + ], ), MenuItem( "file_modification", _("Modification"), model=models.File, - access_controls=["change_file", "change_own_file"], + access_controls=[ + "archaeological_files.change_file", + "archaeological_files.change_own_file" + ], ), MenuItem( "file_closing", _("Closing"), model=models.File, - access_controls=["close_file"], + access_controls=["archaeological_files.close_file"], ), MenuItem( "file_deletion", _("Deletion"), model=models.File, - access_controls=["delete_file", "delete_own_file"], + access_controls=[ + "archaeological_files.delete_file", + "archaeological_files.delete_own_file" + ], ), SectionItem( "admin_act_files", @@ -74,25 +86,33 @@ MENU_SECTIONS = [ "file_administrativeactfile_search", _("Search"), model=AdministrativeAct, - access_controls=["change_administrativeact"], + access_controls=[ + "archaeological_operations.change_administrativeact" + ], ), MenuItem( "file_administrativeactfile", _("Creation"), model=AdministrativeAct, - access_controls=["change_administrativeact"], + access_controls=[ + "archaeological_operations.change_administrativeact" + ], ), MenuItem( "file_administrativeactfile_modification", _("Modification"), model=AdministrativeAct, - access_controls=["change_administrativeact"], + access_controls=[ + "archaeological_operations.change_administrativeact" + ], ), MenuItem( "file_administrativeactfile_deletion", _("Deletion"), model=AdministrativeAct, - access_controls=["change_administrativeact"], + access_controls=[ + "archaeological_operations.change_administrativeact" + ], ), ], ), diff --git a/archaeological_files/models.py b/archaeological_files/models.py index 222c7b700..1f164c30d 100644 --- a/archaeological_files/models.py +++ b/archaeological_files/models.py @@ -27,12 +27,13 @@ from django.contrib.gis.db import models from django.contrib.postgres.indexes import GinIndex from django.core.cache import cache from django.core.validators import MinValueValidator, MaxValueValidator -from django.db.models import Q, Count, Sum, Max +from django.db.models import Max from django.db.models.signals import post_save, m2m_changed, post_delete from django.urls import reverse from ishtar_common.models_common import OrderedHierarchicalType -from ishtar_common.utils import ugettext_lazy as _, pgettext_lazy, get_current_profile, InlineClass +from ishtar_common.utils import ugettext_lazy as _, pgettext_lazy, get_current_profile, \ + InlineClass from ishtar_common.utils import ( cached_label_changed, @@ -1548,7 +1549,7 @@ class File( def get_extra_actions(self, request): # url, base_text, icon, extra_text, extra css class, is a quick action actions = super(File, self).get_extra_actions(request) - if self.can_do(request, "change_operation"): + if self.can_do(request, "archaeological_files.change_file"): actions += [ ( reverse("file-parcels-modify", args=[self.pk]), @@ -1571,7 +1572,7 @@ class File( False, ), ] - if self.can_do(request, "add_administrativeact"): + if self.can_do(request, "archaeological_operations.add_administrativeact"): actions += [ ( reverse("file-add-adminact", args=[self.pk]), @@ -1582,7 +1583,7 @@ class File( False, ), ] - if self.can_do(request, "add_operation"): + if self.can_do(request, "archaeological_operations.add_operation"): actions += [ ( reverse("file-add-operation", args=[self.pk]), diff --git a/archaeological_files/urls.py b/archaeological_files/urls.py index 0be30874b..4b50047a6 100644 --- a/archaeological_files/urls.py +++ b/archaeological_files/urls.py @@ -20,24 +20,24 @@ from django.conf.urls import url from django.urls import path -from ishtar_common.utils import check_rights +from ishtar_common.utils import check_permissions from archaeological_files import views, views_api from archaeological_operations.views import administrativeactfile_document -# be carreful: each check_rights must be relevant with ishtar_menu +# be carreful: each check_permissions must be relevant with ishtar_menu # forms: urlpatterns = [ url( r"file_administrativeactfile_search/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.file_administrativeactfile_search_wizard ), name="file_administrativeactfile_search", ), url( r"^file_administrativeactfile/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.file_administrativeactfile_wizard ), name="file_administrativeactfile", @@ -49,14 +49,14 @@ urlpatterns = [ ), url( r"file_administrativeactfile_deletion/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.file_administrativeactfile_deletion_wizard ), name="file_administrativeactfile_deletion", ), url( r"file_administrativeactfile_modification/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.file_administrativeactfile_modification_wizard ), name="file_administrativeactfile_modification", @@ -68,17 +68,20 @@ urlpatterns = [ ), url( r"file_search/(?P<step>.+)?$", - check_rights(["view_file", "view_own_file"])(views.file_search_wizard), + check_permissions([ + "archaeological_files.view_file", + "archaeological_files.view_own_file"])(views.file_search_wizard), name="file_search", ), url( r"^file_creation/(?P<step>.+)?$", - check_rights(["add_file"])(views.file_creation_wizard), + check_permissions(["archaeological_files.add_file"])(views.file_creation_wizard), name="file_creation", ), url( r"^file_modification/(?P<step>.+)?$", - check_rights(["change_file", "change_own_file"])( + check_permissions(["archaeological_files.change_file", + "archaeological_files.change_own_file"])( views.file_modification_wizard ), name="file_modification", @@ -86,12 +89,16 @@ urlpatterns = [ url(r"^file_modify/(?P<pk>.+)/$", views.file_modify, name="file_modify"), url( r"^file_closing/(?P<step>.+)?$", - check_rights(["change_file"])(views.file_closing_wizard), + check_permissions( + ["archaeological_files.change_file"] + )(views.file_closing_wizard), name="file_closing", ), url( r"file_deletion/(?P<step>.+)?$", - check_rights(["delete_file", "delete_own_file"])(views.file_deletion_wizard), + check_permissions( + ["archaeological_files.delete_file", "archaeological_files.delete_own_file"] + )(views.file_deletion_wizard), name="file_deletion", ), url(r"^file_delete/(?P<pk>.+)/$", views.file_delete, name="delete-file"), @@ -123,7 +130,9 @@ urlpatterns = [ url(r"revert-file/(?P<pk>.+)/(?P<date>.+)$", views.revert_file, name="revert-file"), url( r"^file-add-adminact/(?P<pk>[0-9-]+)/$", - check_rights(["add_administrativeact"])(views.file_adminact_add), + check_permissions(["archaeological_operations.add_administrativeact"])( + views.file_adminact_add + ), name="file-add-adminact", ), url( @@ -134,12 +143,15 @@ urlpatterns = [ ), url( r"^file-add-operation/(?P<pk>[0-9-]+)/$", - check_rights(["add_operation"])(views.file_add_operation), + check_permissions(["archaeological_operations.add_operation"])( + views.file_add_operation + ), name="file-add-operation", ), url( r'^file/edit-preventive-price/(?P<pk>\d+)/$', - check_rights(["change_file", "change_own_file"])( + check_permissions(["archaeological_files.change_file", + "archaeological_files.change_own_file"])( views.PreventiveSimpleEditView.as_view() ), name="file-edit-preventive-price", @@ -151,21 +163,24 @@ urlpatterns = [ ), url( r'^file/edit-preventive/(?P<pk>\d+)/$', - check_rights(["change_file", "change_own_file"])( + check_permissions(["archaeological_files.change_file", + "archaeological_files.change_own_file"])( views.PreventiveEditView.as_view() ), name="file-edit-preventive", ), url( r'^file/edit-preventive/add-default-cost/(?P<pk>\d+)/$', - check_rights(["change_file", "change_own_file"])( + check_permissions(["archaeological_files.change_file", + "archaeological_files.change_own_file"])( views.file_edit_preventive_add_default ), name="file-edit-preventive-default-cost", ), url( r'^file/edit-preventive/copy-planned/(?P<pk>\d+)/$', - check_rights(["change_file", "change_own_file"])( + check_permissions(["archaeological_files.change_file", + "archaeological_files.change_own_file"])( views.file_edit_preventive_copy_planned ), name="file-edit-preventive-copy-planned", diff --git a/archaeological_files/views.py b/archaeological_files/views.py index 44ba75947..0d3f978b5 100644 --- a/archaeological_files/views.py +++ b/archaeological_files/views.py @@ -24,7 +24,7 @@ from django.db.models import Q, F from django.http import HttpResponse, Http404, HttpResponseRedirect from django.forms.formsets import formset_factory from django.views.generic.edit import UpdateView -from django.shortcuts import redirect, render +from django.shortcuts import redirect from django.urls import reverse from ishtar_common.utils import ugettext_lazy as _ @@ -56,18 +56,18 @@ from archaeological_operations.forms import FinalAdministrativeActDeleteForm from ishtar_common.forms import ClosingDateFormSelection from . import forms, models -from archaeological_operations.models import Operation, AdministrativeAct +from archaeological_operations.models import AdministrativeAct RE_YEAR_INDEX = re.compile(r"([1-2][0-9]{3})-([0-9]+)") # eg.: 2014-123 def autocomplete_file(request): + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse(content_type="text/plain") if ( - not request.user.has_perm("ishtar_common.view_file", models.File) - and not request.user.has_perm("ishtar_common.view_own_file", models.File) - and not request.user.ishtaruser.has_right( - "file_search", session=request.session - ) + not ishtaruser.has_permission("archaeological_files.view_file") + and not ishtaruser.has_permission("archaeological_files.view_own_file") ): return HttpResponse(content_type="text/plain") if not request.GET.get("term"): @@ -103,9 +103,9 @@ revert_file = revert_item(models.File) def extra_file_dct(request, item): dct = {} - if request.user.has_perm( - "ishtar_common.add_operation", Operation - ) or request.user.ishtaruser.has_right("add_operation"): + if request.user.ishtaruser.has_permission( + "archaeological_operations.add_operation" + ): dct["can_add_operation"] = True return dct diff --git a/archaeological_finds/forms.py b/archaeological_finds/forms.py index 094e6be21..23531aeb0 100644 --- a/archaeological_finds/forms.py +++ b/archaeological_finds/forms.py @@ -2619,11 +2619,12 @@ class FindBasketAddItemForm(forms.Form): basket_id = forms.IntegerField(required=True) item_id = forms.IntegerField(required=True) - def save(self, user): + def save(self, ishtaruser): try: basket = ( models.FindBasket.objects.filter( - Q(user=user) | Q(shared_with=user) | Q(shared_write_with=user) + Q(user=ishtaruser) | Q(shared_with=ishtaruser) | + Q(shared_write_with=ishtaruser) ) .distinct() .get(pk=self.cleaned_data["basket_id"]) @@ -2634,9 +2635,11 @@ class FindBasketAddItemForm(forms.Form): raise PermissionDenied # check rights if ( - not user.user_ptr.is_superuser - and not user.has_right("view_find") - and not (user.has_right("view_own_find") and item.is_own(user)) + not ishtaruser.user_ptr.is_superuser + and not ishtaruser.has_permission("archaeological_finds.view_find") + and not ishtaruser.has_permission( + "archaeological_finds.view_own_find", + obj=item) ): raise PermissionDenied basket.items.add(item) diff --git a/archaeological_finds/ishtar_menu.py b/archaeological_finds/ishtar_menu.py index aa658023d..6ca50182e 100644 --- a/archaeological_finds/ishtar_menu.py +++ b/archaeological_finds/ishtar_menu.py @@ -24,7 +24,7 @@ from ishtar_common.menu_base import SectionItem, MenuItem from archaeological_operations.models import AdministrativeAct from . import models -# be careful: each access_controls must be relevant with check_rights in urls +# be careful: each access_controls must be relevant with check_permissions in urls MENU_SECTIONS = [ ( @@ -39,25 +39,37 @@ MENU_SECTIONS = [ "find_search", _("Search"), model=models.Find, - access_controls=["view_find", "view_own_find"], + access_controls=[ + "archeological_finds.view_find", + "archeological_finds.view_own_find" + ], ), MenuItem( "find_creation", _("Creation"), model=models.Find, - access_controls=["add_find", "add_own_find"], + access_controls=[ + "archeological_finds.add_find", + "archeological_finds.add_own_find" + ], ), MenuItem( "find_modification", _("Modification"), model=models.Find, - access_controls=["change_find", "change_own_find"], + access_controls=[ + "archeological_finds.change_find", + "archeological_finds.change_own_find" + ], ), MenuItem( "find_deletion", _("Deletion"), model=models.Find, - access_controls=["change_find", "change_own_find"], + access_controls=[ + "archeological_finds.change_find", + "archeological_finds.change_own_find" + ], ), SectionItem( "find_basket", @@ -67,31 +79,46 @@ MENU_SECTIONS = [ "find_basket_search", _("Search"), model=models.FindBasket, - access_controls=["view_find", "view_own_find"], + access_controls=[ + "archeological_finds.view_find", + "archeological_finds.view_own_find" + ], ), MenuItem( "find_basket_creation", _("Creation"), model=models.FindBasket, - access_controls=["view_find", "view_own_find"], + access_controls=[ + "archeological_finds.view_find", + "archeological_finds.view_own_find" + ], ), MenuItem( "find_basket_modification", _("Modification"), model=models.FindBasket, - access_controls=["view_find", "view_own_find"], + access_controls=[ + "archeological_finds.view_find", + "archeological_finds.view_own_find" + ], ), MenuItem( "find_basket_modification_add", _("Manage items"), model=models.FindBasket, - access_controls=["view_find", "view_own_find"], + access_controls=[ + "archeological_finds.view_find", + "archeological_finds.view_own_find" + ], ), MenuItem( "find_basket_deletion", _("Deletion"), model=models.FindBasket, - access_controls=["view_find", "view_own_find"], + access_controls=[ + "archeological_finds.view_find", + "archeological_finds.view_own_find" + ], ), ], ), @@ -115,15 +142,18 @@ MENU_SECTIONS = [ "treatmentfle_search", _("Search"), model=models.TreatmentFile, - access_controls=["view_treatmentfile", "view_own_treatmentfile"], + access_controls=[ + "archeological_finds.view_treatmentfile", + "archeological_finds.view_own_treatmentfile" + ], ), MenuItem( "treatmentfle_creation", _("Creation"), model=models.TreatmentFile, access_controls=[ - "change_treatmentfile", - "change_own_treatmentfile", + "archeological_finds.change_treatmentfile", + "archeological_finds.change_own_treatmentfile", ], ), MenuItem( @@ -131,8 +161,8 @@ MENU_SECTIONS = [ _("Modification"), model=models.TreatmentFile, access_controls=[ - "change_treatmentfile", - "change_own_treatmentfile", + "archeological_finds.change_treatmentfile", + "archeological_finds.change_own_treatmentfile", ], ), MenuItem( @@ -140,8 +170,8 @@ MENU_SECTIONS = [ _("Deletion"), model=models.TreatmentFile, access_controls=[ - "change_treatmentfile", - "change_own_treatmentfile", + "archeological_finds.change_treatmentfile", + "archeological_finds.change_own_treatmentfile", ], ), SectionItem( @@ -152,25 +182,33 @@ MENU_SECTIONS = [ "treatmentfle_admacttreatmentfle_search", _("Search"), model=AdministrativeAct, - access_controls=["change_administrativeact"], + access_controls=[ + "archaeological_operations.view_administrativeact" + ], ), MenuItem( "treatmentfle_admacttreatmentfle", _("Creation"), model=AdministrativeAct, - access_controls=["change_administrativeact"], + access_controls=[ + "archaeological_operations.change_administrativeact" + ], ), MenuItem( "treatmentfle_admacttreatmentfle_modification", _("Modification"), model=AdministrativeAct, - access_controls=["change_administrativeact"], + access_controls=[ + "archaeological_operations.change_administrativeact" + ], ), MenuItem( "treatmentfle_admacttreatmentfle_deletion", _("Deletion"), model=AdministrativeAct, - access_controls=["change_administrativeact"], + access_controls=[ + "archaeological_operations.change_administrativeact" + ], ), ], ), @@ -189,37 +227,54 @@ MENU_SECTIONS = [ "treatment_search", _("Search"), model=models.Treatment, - access_controls=["view_treatment", "view_own_treatment"], + access_controls=[ + "archaeological_finds.view_treatment", + "archaeological_finds.view_own_treatment" + ], ), MenuItem( "treatment_creation", _("Simple treatment - creation"), model=models.Treatment, - access_controls=["change_find", "change_own_find"], + access_controls=[ + "archaeological_finds.change_find", + "archaeological_finds.change_own_find"], ), MenuItem( "treatment_creation_n1", _("Treatment many to one - creation"), model=models.Treatment, - access_controls=["change_find", "change_own_find"], + access_controls=[ + "archaeological_finds.change_find", + "archaeological_finds.change_own_find" + ], ), MenuItem( "treatment_creation_1n", _("Treatment one to many - creation"), model=models.Treatment, - access_controls=["change_find", "change_own_find"], + access_controls=[ + "archaeological_finds.change_find", + "archaeological_finds.change_own_find" + ], ), MenuItem( "treatment_modification", _("Modification"), model=models.Treatment, - access_controls=["change_treatment", "change_own_treatment"], + access_controls=[ + "archaeological_finds.change_treatment", + "archaeological_finds.change_own_treatment" + ], ), MenuItem( "treatment_deletion", _("Deletion"), model=models.Treatment, - access_controls=["change_treatment", "change_own_treatment"], + access_controls=[ + "archaeological_finds.change_treatment", + "archaeological_finds.change_own_treatment" + ], ), SectionItem( "admin_act_treatments", @@ -229,25 +284,33 @@ MENU_SECTIONS = [ "treatment_admacttreatment_search", _("Search"), model=AdministrativeAct, - access_controls=["view_administrativeact"], + access_controls=[ + "archaeological_operations.view_administrativeact" + ], ), MenuItem( "treatment_admacttreatment", _("Creation"), model=AdministrativeAct, - access_controls=["add_administrativeact"], + access_controls=[ + "archaeological_operations.add_administrativeact" + ], ), MenuItem( "treatment_admacttreatment_modification", _("Modification"), model=AdministrativeAct, - access_controls=["change_administrativeact"], + access_controls=[ + "archaeological_operations.change_administrativeact" + ], ), MenuItem( "treatment_admacttreatment_deletion", _("Deletion"), model=AdministrativeAct, - access_controls=["change_administrativeact"], + access_controls=[ + "archaeological_operations.change_administrativeact" + ], ), ], ), diff --git a/archaeological_finds/models_finds.py b/archaeological_finds/models_finds.py index 464076caf..1863ba450 100644 --- a/archaeological_finds/models_finds.py +++ b/archaeological_finds/models_finds.py @@ -925,14 +925,18 @@ WEIGHT_UNIT = ( class FindBasket(Basket, MainItem, ValueGetter): SHOW_URL = "show-findbasket" SLUG = "findbasket" - items = models.ManyToManyField("Find", blank=True, related_name="basket", verbose_name=_("Associated finds")) + items = models.ManyToManyField("Find", blank=True, related_name="basket", + verbose_name=_("Associated finds")) QA_EDIT = QuickAction( url="findbasket-qa-bulk-update", icon_class="fa fa-pencil", text=_("Modify"), target="many", - rights=["view_find", "view_own_find"], + rights=[ + "archaeological_finds.view_find", + "archaeological_finds.view_own_find" + ], ) QUICK_ACTIONS = [ QA_EDIT, @@ -941,7 +945,10 @@ class FindBasket(Basket, MainItem, ValueGetter): icon_class="fa fa-clone", text=_("Duplicate"), target="one", - rights=["view_find", "view_own_find"], + rights=[ + "archaeological_finds.view_find", + "archaeological_finds.view_own_find" + ], ), ] @@ -976,7 +983,7 @@ class FindBasket(Basket, MainItem, ValueGetter): """ # url, base_text, icon, extra_text, extra css class, is a quick action - if not request.user or not request.user.ishtaruser: + if not request.user or not getattr(request.user, "ishtaruser", None): return [] ishtaruser = request.user.ishtaruser @@ -994,7 +1001,7 @@ class FindBasket(Basket, MainItem, ValueGetter): False, ), ] - can_edit_find = self.can_do(request, "change_find") + can_edit_find = self.can_do(request, "archaeological_finds.change_find") if can_edit_find: actions += [ ( @@ -1006,7 +1013,7 @@ class FindBasket(Basket, MainItem, ValueGetter): False, ), ] - if self.can_do(request, "add_treatmentfile"): + if self.can_do(request, "archaeological_finds.add_treatmentfile"): actions += [ ( reverse("findbasket-add-treatmentfile", args=[self.pk]), @@ -1857,14 +1864,16 @@ class Find( icon_class="fa fa-pencil", text=_("Bulk update"), target="many", - rights=["change_find", "change_own_find"], + rights=["archaeological_finds.change_find", + "archaeological_finds.change_own_find"], ) QA_LOCK = QuickAction( url="find-qa-lock", icon_class="fa fa-lock", text=_("Lock/Unlock"), target="many", - rights=["change_find", "change_own_find"], + rights=["archaeological_finds.change_find", + "archaeological_finds.change_own_find"], ) QUICK_ACTIONS = [ @@ -1874,21 +1883,30 @@ class Find( icon_class="fa fa-clone", text=_("Duplicate"), target="one", - rights=["change_find", "change_own_find"], + rights=[ + "archaeological_finds.change_find", + "archaeological_finds.change_own_find" + ], ), QuickAction( url="find-qa-basket", icon_class="fa fa-shopping-basket", text=_("Basket"), target="many", - rights=["change_find", "change_own_find"], + rights=[ + "archaeological_finds.change_find", + "archaeological_finds.change_own_find" + ], ), QuickAction( url="find-qa-packaging", icon_class="fa fa-gift", text=_("Packaging"), target="many", - rights=["change_find", "change_own_find"], + rights=[ + "archaeological_finds.change_find", + "archaeological_finds.change_own_find" + ], module="warehouse", ), QuickAction( @@ -1896,7 +1914,10 @@ class Find( icon_class="fa fa-object-group", text=_("Treatment many to one"), target="many", - rights=["change_find", "change_own_find"], + rights=[ + "archaeological_finds.change_find", + "archaeological_finds.change_own_find" + ], is_popup=False, ), QA_LOCK, @@ -2641,11 +2662,12 @@ class Find( is_locked = hasattr(self, "is_locked") and self.is_locked(request.user) profile = get_current_profile() - can_add_geo = profile.mapping and self.can_do(request, "add_geovectordata") + can_add_geo = profile.mapping and self.can_do(request, + "ishtar_common.add_geovectordata") if can_add_geo: if self.base_finds.count() == 1: actions.append(self.base_finds.all()[0].get_add_geo_action()) - can_edit_find = self.can_do(request, "change_find") + can_edit_find = self.can_do(request, "archaeological_finds.change_find") if can_edit_find and not is_locked: actions += [ ( diff --git a/archaeological_finds/models_treatments.py b/archaeological_finds/models_treatments.py index cbca04c9a..d23843226 100644 --- a/archaeological_finds/models_treatments.py +++ b/archaeological_finds/models_treatments.py @@ -22,14 +22,14 @@ import datetime from django.conf import settings from django.contrib.gis.db import models from django.contrib.postgres.indexes import GinIndex -from django.db import transaction from django.db.models import Max, Q from django.db.models.signals import post_save, post_delete, pre_delete, m2m_changed from django.template.defaultfilters import slugify from django.urls import reverse from ishtar_common.utils import ugettext_lazy as _, pgettext_lazy, SheetItem -from archaeological_finds.models_finds import Find, FindBasket, TreatmentType, FindTreatment +from archaeological_finds.models_finds import Find, FindBasket, TreatmentType, \ + FindTreatment from archaeological_operations.models import ClosedItem, Operation from archaeological_context_records.models import Dating from archaeological_warehouse.models import Warehouse, Container @@ -413,7 +413,7 @@ class Treatment( def get_extra_actions(self, request): # url, base_text, icon, extra_text, extra css class, is a quick action actions = super(Treatment, self).get_extra_actions(request) - if self.can_do(request, "add_administrativeact"): + if self.can_do(request, "archaeological_operations.add_administrativeact"): actions += [ ( reverse("treatment-add-adminact", args=[self.pk]), @@ -1309,7 +1309,7 @@ class TreatmentFile( def get_extra_actions(self, request): # url, base_text, icon, extra_text, extra css class, is a quick action actions = super(TreatmentFile, self).get_extra_actions(request) - if self.can_do(request, "add_administrativeact"): + if self.can_do(request, "archaeological_operations.add_administrativeact"): actions += [ ( reverse("treatmentfile-add-adminact", args=[self.pk]), @@ -1330,7 +1330,7 @@ class TreatmentFile( ): # a treatment of this type already exists return actions - can_edit_find = self.can_do(request, "change_find") + can_edit_find = self.can_do(request, "archaeological_finds.change_find") if can_edit_find: actions += [ ( diff --git a/archaeological_finds/tests.py b/archaeological_finds/tests.py index b521e0b97..16fb575c7 100644 --- a/archaeological_finds/tests.py +++ b/archaeological_finds/tests.py @@ -35,7 +35,6 @@ from django.test import LiveServerTestCase from django.test.client import Client from django.urls import reverse from ishtar_common.models import ( - ImporterGroup, ImporterType, IshtarUser, ImporterColumn, @@ -95,7 +94,8 @@ from ishtar_common.tests import ( GenericSerializationTest, SearchText, ) -from archaeological_operations.tests import ImportTest, create_operation, create_administrativact +from archaeological_operations.tests import ImportTest, create_operation, \ + create_administrativact from archaeological_context_records.tests import ContextRecordInit from archaeological_operations.serializers import operation_serialization @@ -1994,6 +1994,7 @@ class FindPermissionTest(FindInit, TestCase): response = c.get(reverse("get-find")) # only one "own" operation available content = response.content.decode() + self.assertTrue(content) self.assertTrue(json.loads(content)) self.assertEqual(json.loads(content)["recordsTotal"], 1) diff --git a/archaeological_finds/urls.py b/archaeological_finds/urls.py index a1b240363..ba10750d2 100644 --- a/archaeological_finds/urls.py +++ b/archaeological_finds/urls.py @@ -20,47 +20,56 @@ from django.conf.urls import url from django.urls import path -from ishtar_common.utils import check_rights, get_urls_for_model +from ishtar_common.utils import check_permissions, get_urls_for_model from archaeological_finds import views from archaeological_finds import views_api from archaeological_operations.views import administrativeactfile_document from archaeological_finds import models -# be careful: each check_rights must be relevant with ishtar_menu +# be careful: each check_permissions must be relevant with ishtar_menu # forms urlpatterns = [ url( r"find_search/(?P<step>.+)?$", - check_rights(["view_find", "view_own_find"])(views.find_search_wizard), + check_permissions( + ["archaeological_finds.view_find", "archaeological_finds.view_own_find"] + )(views.find_search_wizard), name="find_search", ), url( r"find_creation/(?P<step>.+)?$", - check_rights(["add_find", "add_own_find"])(views.find_creation_wizard), + check_permissions( + ["archaeological_finds.add_find", "archaeological_finds.add_own_find"] + )(views.find_creation_wizard), name="find_creation", ), url( r"find_modification/(?P<step>.+)?$", - check_rights(["change_find", "change_own_find"])( - views.find_modification_wizard - ), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.find_modification_wizard), name="find_modification", ), url(r"find_modify/(?P<pk>.+)/$", views.find_modify, name="find_modify"), url(r"find_create/(?P<pk>.+)/$", views.find_create, name="find_create"), url( r"find_deletion/(?P<step>.+)?$", - check_rights(["change_find", "change_own_find"])(views.find_deletion_wizard), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.find_deletion_wizard), name="find_deletion", ), url(r"find_delete/(?P<pk>.+)/$", views.find_delete, name="delete-find"), url( r"^find-qa-duplicate/(?P<pks>[0-9-]+)?/$", - check_rights(["change_find", "change_own_find"])( - views.QAFindDuplicateFormView.as_view() - ), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.QAFindDuplicateFormView.as_view()), name="find-qa-duplicate", ), url(r"get-findbasket/$", views.get_find_basket, name="get-findbasket"), @@ -71,17 +80,26 @@ urlpatterns = [ ), url( r"find_basket_search/(?P<step>.+)?$", - check_rights(["view_find", "view_own_find"])(views.basket_search_wizard), + check_permissions( + ["archaeological_finds.view_find", + "archaeological_finds.view_own_find"] + )(views.basket_search_wizard), name="find_basket_search", ), url( r"^find_basket_creation/$", - check_rights(["view_find", "view_own_find"])(views.NewFindBasketView.as_view()), + check_permissions( + ["archaeological_finds.view_find", + "archaeological_finds.view_own_find"] + )(views.NewFindBasketView.as_view()), name="new_findbasket", ), url( r"^find_basket_modification/(?P<step>.+)?$", - check_rights(["view_find", "view_own_find"])(views.basket_modify_wizard), + check_permissions( + ["archaeological_finds.view_find", + "archaeological_finds.view_own_find"] + )(views.basket_modify_wizard), name="find_basket_modification", ), url( @@ -91,139 +109,163 @@ urlpatterns = [ ), url( r"^find_basket_modification_add/$", - check_rights(["view_find", "view_own_find"])( - views.SelectBasketForManagement.as_view() - ), + check_permissions( + ["archaeological_finds.view_find", + "archaeological_finds.view_own_find"] + )(views.SelectBasketForManagement.as_view()), name="select_findbasketforadd", ), url( r"^find_basket_modification_add/(?P<pk>[0-9]+)?/$", - check_rights(["view_find", "view_own_find"])( - views.SelectItemsInBasket.as_view() - ), + check_permissions( + ["archaeological_finds.view_find", + "archaeological_finds.view_own_find"] + )(views.SelectItemsInBasket.as_view()), name="select_itemsinbasket", ), url( r"^find_basket_modification_add_item/$", - check_rights(["view_find", "view_own_find"])( - views.FindBasketAddItemView.as_view() - ), + check_permissions( + ["archaeological_finds.view_find", + "archaeological_finds.view_own_find"] + )(views.FindBasketAddItemView.as_view()), name="add_iteminbasket", ), url( r"^find_basket_modification_delete_item/(?P<basket>[0-9]+)?" r"/(?P<find_pk>[0-9]+)?/$", - check_rights(["view_find", "view_own_find"])( - views.FindBasketDeleteItemView.as_view() - ), + check_permissions( + ["archaeological_finds.view_find", + "archaeological_finds.view_own_find"] + )(views.FindBasketDeleteItemView.as_view()), name="delete_iteminbasket", ), url( r"^find_basket_list/(?P<pk>[0-9]+)?/$", - check_rights(["view_find", "view_own_find"])( - views.FindBasketListView.as_view() - ), + check_permissions( + ["archaeological_finds.view_find", + "archaeological_finds.view_own_find"] + )(views.FindBasketListView.as_view()), name="list_iteminbasket", ), url( r"^find_basket_deletion/(?P<step>.+)?$", - check_rights(["view_find", "view_own_find"])(views.basket_delete_wizard), + check_permissions( + ["archaeological_finds.view_find", + "archaeological_finds.view_own_find"] + )(views.basket_delete_wizard), name="find_basket_deletion", ), url( r"^findbasket-qa-duplicate/(?P<pks>[0-9-]+)?/$", - check_rights(["view_find", "view_own_find"])( - views.QAFindbasketDuplicateFormView.as_view() - ), + check_permissions( + ["archaeological_finds.view_find", + "archaeological_finds.view_own_find"] + )(views.QAFindbasketDuplicateFormView.as_view()), name="findbasket-qa-duplicate", ), url( r"^findbasket-add-treatment/(?P<pk>[0-9-]+)/$", - check_rights(["change_find", "change_own_find"])( - views.findbasket_treatment_add - ), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.findbasket_treatment_add), name="findbasket-add-treatment", ), url( r"^findbasket-add-treatmentfile/(?P<pk>[0-9-]+)/$", - check_rights(["add_treatmentfile", "add_own_treatmentfile"])( - views.findbasket_treatmentfile_add - ), + check_permissions( + ["archaeological_finds.add_treatmentfile", + "archaeological_finds.add_own_treatmentfile"] + )(views.findbasket_treatmentfile_add), name="findbasket-add-treatmentfile", ), url( r"^find-add-treatment/(?P<pk>[0-9-]+)/$", - check_rights(["change_find", "change_own_find"])(views.find_treatment_add), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.find_treatment_add), name="find-add-treatment", ), url( r"^find-add-divide-treatment/(?P<pk>[0-9-]+)/$", - check_rights(["change_find", "change_own_find"])( - views.find_divide_treatment_add - ), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.find_divide_treatment_add), name="find-add-divide-treatment", ), url( r"^treatmentfile-add-treatment/(?P<pk>[0-9-]+)/$", - check_rights(["change_find", "change_own_find"])( - views.treatmentfile_treatment_add - ), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.treatmentfile_treatment_add), name="treatmentfile-add-treatment", ), url( r"^treatment-add-adminact/(?P<pk>[0-9-]+)/$", - check_rights(["add_administrativeact"])(views.treatment_adminact_add), + check_permissions( + ["archaeological_operations.add_administrativeact"] + )(views.treatment_adminact_add), name="treatment-add-adminact", ), url( r"^treatmentfile-add-adminact/(?P<pk>[0-9-]+)/$", - check_rights(["add_administrativeact"])(views.treatmentfile_adminact_add), + check_permissions( + ["archaeological_operations.add_administrativeact"] + )(views.treatmentfile_adminact_add), name="treatmentfile-add-adminact", ), url( r"^find-qa-bulk-update/(?P<pks>[0-9-]+)?/$", - check_rights(["change_find", "change_own_find"])(views.QAFindForm.as_view()), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.QAFindForm.as_view()), name="find-qa-bulk-update", ), url( r"^find-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$", - check_rights(["change_find", "change_own_find"])(views.QAFindForm.as_view()), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.QAFindForm.as_view()), name="find-qa-bulk-update-confirm", kwargs={"confirm": True}, ), url( r"^find-qa-basket/(?P<pks>[0-9-]+)?/$", - check_rights(["change_find", "change_own_find"])( - views.QAFindBasketFormView.as_view() - ), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.QAFindBasketFormView.as_view()), name="find-qa-basket", ), url( r"findbasket-qa-bulk-update/(?P<pks>[0-9-]+)?/$", - check_rights([ - "change_find", - "change_own_find", - ])( - views.QAFindBasketModifyView.as_view() - ), + check_permissions([ + "archaeological_finds.change_find", + "archaeological_finds.change_own_find", + ])(views.QAFindBasketModifyView.as_view()), name="findbasket-qa-bulk-update", ), url( r"findbasket-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$", - check_rights([ - "change_find", - "change_own_find", - ])( - views.QAFindBasketModifyView.as_view() - ), + check_permissions([ + "archaeological_finds.change_find", + "archaeological_finds.change_own_find", + ])(views.QAFindBasketModifyView.as_view()), name="findbasket-qa-bulk-update-confirm", kwargs={"confirm": True}, ), url( r"^find-qa-packaging/(?P<pks>[0-9-]+)?/$", - check_rights(["change_find", "change_own_find"])( - views.QAFindTreatmentFormView.as_view() - ), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.QAFindTreatmentFormView.as_view()), name="find-qa-packaging", ), url( @@ -234,16 +276,18 @@ urlpatterns = [ ), url( r"^treatment_creation/(?P<step>.+)?$", - check_rights(["change_find", "change_own_find"])( - views.treatment_creation_wizard - ), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.treatment_creation_wizard), name="treatment_creation", ), url( r"^treatment_creation_n1/(?P<step>.+)?$", - check_rights(["change_find", "change_own_find"])( - views.treatment_creation_n1_wizard - ), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.treatment_creation_n1_wizard), name="treatment_creation_n1", ), url( @@ -253,16 +297,18 @@ urlpatterns = [ ), url( r"^treatment_creation_1n/(?P<step>.+)?$", - check_rights(["change_find", "change_own_find"])( - views.treatment_creation_1n_wizard - ), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.treatment_creation_1n_wizard), name="treatment_creation_1n", ), url( r"^treatment_modification/(?P<step>.+)?$", - check_rights(["change_find", "change_own_find"])( - views.treatment_modification_wizard - ), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.treatment_modification_wizard), name="treatment_modification", ), url( @@ -272,14 +318,18 @@ urlpatterns = [ ), url( r"^treatment_search/(?P<step>.+)?$", - check_rights(["view_find", "view_own_find"])(views.treatment_search_wizard), + check_permissions( + ["archaeological_finds.view_find", + "archaeological_finds.view_own_find"] + )(views.treatment_search_wizard), name="treatment_search", ), url( r"^treatment_deletion/(?P<step>.+)?$", - check_rights(["change_treatmentfile", "change_own_treatmentfile"])( - views.treatment_deletion_wizard - ), + check_permissions( + ["archaeological_finds.change_treatmentfile", + "archaeological_finds.change_own_treatmentfile"] + )(views.treatment_deletion_wizard), name="treatment_deletion", ), url( @@ -289,21 +339,21 @@ urlpatterns = [ ), url( r"^treatment_admacttreatment_search/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.treatment_administrativeact_search_wizard ), name="treatment_admacttreatment_search", ), url( r"^treatment_admacttreatment/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.treatment_administrativeact_wizard ), name="treatment_admacttreatment", ), url( r"^treatment_admacttreatment_modification/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.treatment_administrativeact_modification_wizard ), name="treatment_admacttreatment_modification", @@ -315,7 +365,7 @@ urlpatterns = [ ), url( r"^treatment_admacttreatment_deletion/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.treatment_admacttreatment_deletion_wizard ), name="treatment_admacttreatment_deletion", @@ -332,21 +382,21 @@ urlpatterns = [ ), url( r"^treatmentfle_admacttreatmentfle_search/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.treatmentfile_admacttreatmentfile_search_wizard ), name="treatmentfle_admacttreatmentfle_search", ), url( r"^treatmentfle_admacttreatmentfle_modification/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.treatmentfile_admacttreatmentfile_modification_wizard ), name="treatmentfle_admacttreatmentfle_modification", ), url( r"^treatmentfle_admacttreatmentfle/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.treatmentfile_admacttreatmentfile_wizard ), name="treatmentfle_admacttreatmentfle", @@ -358,7 +408,7 @@ urlpatterns = [ ), url( r"^treatmentfle_admacttreatmentfle_deletion/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.treatmentfile_admacttreatmentfile_deletion_wizard ), name="treatmentfle_admacttreatmentfle_deletion", @@ -370,23 +420,26 @@ urlpatterns = [ ), url( r"^treatmentfle_search/(?P<step>.+)?$", - check_rights(["view_treatmentfile", "view_own_treatmentfile"])( - views.treatmentfile_search_wizard - ), + check_permissions( + ["archaeological_finds.view_treatmentfile", + "archaeological_finds.view_own_treatmentfile"] + )(views.treatmentfile_search_wizard), name="treatmentfile_search", ), url( r"treatmentfle_creation/(?P<step>.+)?$", - check_rights(["change_treatmentfile", "change_own_treatmentfile"])( - views.treatmentfile_creation_wizard - ), + check_permissions( + ["archaeological_finds.change_treatmentfile", + "archaeological_finds.change_own_treatmentfile"] + )(views.treatmentfile_creation_wizard), name="treatmentfile_creation", ), url( r"treatmentfle_modification/(?P<step>.+)?$", - check_rights(["change_treatmentfile", "change_own_treatmentfile"])( - views.treatmentfile_modification_wizard - ), + check_permissions( + ["archaeological_finds.change_treatmentfile", + "archaeological_finds.change_own_treatmentfile"] + )(views.treatmentfile_modification_wizard), name="treatmentfile_modification", ), url( @@ -396,9 +449,10 @@ urlpatterns = [ ), url( r"^treatmentfle_deletion/(?P<step>.+)?$", - check_rights(["change_find", "change_own_find"])( - views.treatmentfile_deletion_wizard - ), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.treatmentfile_deletion_wizard), name="treatmentfile_deletion", ), url( @@ -600,14 +654,18 @@ urlpatterns = [ ), url( r"autocomplete-findbasket/$", - check_rights(["change_find", "change_own_find"])(views.autocomplete_findbasket), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.autocomplete_findbasket), name="autocomplete-findbasket", ), url( r"autocomplete-findbasket-write/$", - check_rights(["change_find", "change_own_find"])( - views.autocomplete_findbasket_write - ), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.autocomplete_findbasket_write), name="autocomplete-findbasket-write", ), url( @@ -615,9 +673,10 @@ urlpatterns = [ ), url( r"api/ishtar/base-finds/get-geo$", - check_rights(["view_find", "view_own_find"])( - views.get_geo_items, - ), + check_permissions( + ["archaeological_finds.view_find", + "archaeological_finds.view_own_find"] + )(views.get_geo_items), name="api-get-geo", ), url( @@ -639,9 +698,10 @@ urlpatterns = [ ), url( r"autocomplete-basefind/$", - check_rights(["view_basefind", "view_own_basefind"])( - views.autocomplete_basefind - ), + check_permissions( + ["archaeological_finds.view_basefind", + "archaeological_finds.view_own_basefind"] + )(views.autocomplete_basefind), name="autocomplete-basefind", ), ] diff --git a/archaeological_finds/views.py b/archaeological_finds/views.py index 866349ce2..0b286531c 100644 --- a/archaeological_finds/views.py +++ b/archaeological_finds/views.py @@ -151,14 +151,12 @@ get_administrativeacttreatmentfile = get_item( def autocomplete_treatmentfile(request): + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse(content_type="text/plain") if ( - not request.user.has_perm("ishtar_common.view_treatment", models.Treatment) - and not request.user.has_perm( - "ishtar_common.view_own_treatment", models.Treatment - ) - and not request.user.ishtaruser.has_right( - "treatmentfile_search", session=request.session - ) + not ishtaruser.has_permission("archaeological_finds.view_treatment") + and not ishtaruser.has_permission("archaeological_finds.view_own_treatment") ): return HttpResponse(content_type="text/plain") if not request.GET.get("term"): @@ -193,7 +191,7 @@ def show_basefind(request, pk, **dct): def show_find_extra(request, find): - if not request.user or not request.user.ishtaruser: + if not request.user or not getattr(request.user, "ishtaruser", None): return {} user = request.user.ishtaruser if isinstance(find, dict): @@ -607,8 +605,8 @@ class FindBasketDeleteItemView( basket = self.get_basket(user=ishtaruser, pk=self.kwargs["basket"]) if ( not user.is_superuser - and not ishtaruser.has_right("view_find") - and not (ishtaruser.has_right("view_own_find") and find.is_own(user)) + and not ishtaruser.has_permission("archaeological_finds.view_find") + and not ishtaruser.has_permission("archaeological_finds.view_own_find", find) ): raise PermissionDenied basket.items.remove(find) diff --git a/archaeological_operations/ishtar_menu.py b/archaeological_operations/ishtar_menu.py index b58fb5078..31d7ade34 100644 --- a/archaeological_operations/ishtar_menu.py +++ b/archaeological_operations/ishtar_menu.py @@ -24,7 +24,7 @@ from ishtar_common.menu_base import SectionItem, MenuItem from ishtar_common.models import IshtarSiteProfile from archaeological_operations import models -# be careful: each access_controls must be relevant with check_rights in urls +# be careful: each access_controls must be relevant with check_permissions in urls MENU_SECTIONS = [ @@ -39,31 +39,43 @@ MENU_SECTIONS = [ "operation_search", _("Search"), model=models.Operation, - access_controls=["view_operation", "view_own_operation"], + access_controls=[ + "archaeological_operations.view_operation", + "archaeological_operations.view_own_operation" + ], ), MenuItem( "operation_creation", _("Creation"), model=models.Operation, - access_controls=["add_operation", "add_own_operation"], + access_controls=[ + "archaeological_operations.add_operation", + "archaeological_operations.add_own_operation" + ], ), MenuItem( "operation_modification", _("Modification"), model=models.Operation, - access_controls=["change_operation", "change_own_operation"], + access_controls=[ + "archaeological_operations.change_operation", + "archaeological_operations.change_own_operation" + ], ), MenuItem( "operation_closing", _("Closing"), model=models.Operation, - access_controls=["close_operation"], + access_controls=["archaeological_operations.close_operation"], ), MenuItem( "operation_deletion", _("Deletion"), model=models.Operation, - access_controls=["change_operation", "change_own_operation"], + access_controls=[ + "archaeological_operations.change_operation", + "archaeological_operations.change_own_operation" + ], ), SectionItem( "admin_act_operations", @@ -74,25 +86,33 @@ MENU_SECTIONS = [ "operation_administrativeactop_search", _("Search"), model=models.AdministrativeAct, - access_controls=["change_administrativeact"], + access_controls=[ + "archaeological_operations.change_administrativeact" + ], ), MenuItem( "operation_administrativeactop", _("Creation"), model=models.AdministrativeAct, - access_controls=["change_administrativeact"], + access_controls=[ + "archaeological_operations.change_administrativeact" + ], ), MenuItem( "operation_administrativeactop_modification", _("Modification"), model=models.AdministrativeAct, - access_controls=["change_administrativeact"], + access_controls=[ + "archaeological_operations.change_administrativeact" + ], ), MenuItem( "operation_administrativeactop_deletion", _("Deletion"), model=models.AdministrativeAct, - access_controls=["change_administrativeact"], + access_controls=[ + "archaeological_operations.change_administrativeact" + ], ), ], ), @@ -112,8 +132,8 @@ MENU_SECTIONS = [ pgettext_lazy("admin act register", "Register"), model=models.AdministrativeAct, access_controls=[ - "view_administrativeact", - "view_own_administrativeact", + "archaeological_operations.view_administrativeact", + "archaeological_operations.view_own_administrativeact", ], ), ], @@ -132,8 +152,8 @@ MENU_SECTIONS = [ _("Search"), model=models.ArchaeologicalSite, access_controls=[ - "view_archaeologicalsite", - "view_own_archaeologicalsite", + "archaeological_operations.view_archaeologicalsite", + "archaeological_operations.view_own_archaeologicalsite", ], ), MenuItem( @@ -141,8 +161,8 @@ MENU_SECTIONS = [ _("Creation"), model=models.ArchaeologicalSite, access_controls=[ - "add_archaeologicalsite", - "add_own_archaeologicalsite", + "archaeological_operations.add_archaeologicalsite", + "archaeological_operations.add_own_archaeologicalsite", ], ), MenuItem( @@ -150,15 +170,17 @@ MENU_SECTIONS = [ _("Modification"), model=models.ArchaeologicalSite, access_controls=[ - "change_archaeologicalsite", - "change_own_archaeologicalsite", + "archaeological_operations.change_archaeologicalsite", + "archaeological_operations.change_own_archaeologicalsite", ], ), MenuItem( "site_deletion", _("Deletion"), model=models.ArchaeologicalSite, - access_controls=["change_archaeologicalsite"], + access_controls=[ + "archaeological_operations.change_archaeologicalsite" + ], ), ], ), diff --git a/archaeological_operations/models.py b/archaeological_operations/models.py index 9119a5c72..a074adc9a 100644 --- a/archaeological_operations/models.py +++ b/archaeological_operations/models.py @@ -31,7 +31,7 @@ from django.contrib.gis.db.models.functions import Centroid from django.contrib.postgres.indexes import GinIndex from django.contrib.sites.models import Site from django.db import transaction, OperationalError, IntegrityError -from django.db.models import Q, Count, Sum, Max, Avg +from django.db.models import Q, Max from django.db.models.signals import post_save, m2m_changed, post_delete from django.forms import ValidationError from django.urls import reverse @@ -579,14 +579,20 @@ class ArchaeologicalSite( icon_class="fa fa-lock", text=_("Lock/Unlock"), target="many", - rights=["change_archaeologicalsite", "change_own_archaeologicalsite"], + rights=[ + "archaeological_operations.change_archaeologicalsite", + "archaeological_operations.change_own_archaeologicalsite" + ], ) QA_EDIT = QuickAction( url="site-qa-bulk-update", icon_class="fa fa-pencil", text=_("Bulk update"), target="many", - rights=["change_archaeologicalsite", "change_own_archaeologicalsite"], + rights=[ + "archaeological_operations.change_archaeologicalsite", + "archaeological_operations.change_own_archaeologicalsite" + ], ) QUICK_ACTIONS = [ QA_EDIT, @@ -596,7 +602,7 @@ class ArchaeologicalSite( icon_class="fa fa-plus", text=_("Create associated operation"), target="many", - rights=["change_operation"], + rights=["archaeological_operations.add_operation"], is_popup=False ), QuickAction( @@ -604,7 +610,10 @@ class ArchaeologicalSite( icon_class="fa fa-clone", text=_("Duplicate"), target="one", - rights=["change_archaeologicalsite", "change_own_archaeologicalsite"], + rights=[ + "archaeological_operations.change_archaeologicalsite", + "archaeological_operations.change_own_archaeologicalsite" + ], ), ] @@ -780,8 +789,12 @@ class ArchaeologicalSite( actions = super(ArchaeologicalSite, self).get_extra_actions(request) is_locked = self.is_locked(request.user) profile = get_current_profile() - can_edit_site = self.can_do(request, "change_archaeologicalsite") - can_add_geo = profile.mapping and self.can_do(request, "add_geovectordata") + can_edit_site = self.can_do( + request, "archaeological_operations.change_archaeologicalsite" + ) + can_add_geo = profile.mapping and self.can_do( + request, "ishtar_common.add_geovectordata" + ) if can_add_geo: actions.append(self.get_add_geo_action()) @@ -797,7 +810,9 @@ class ArchaeologicalSite( ), ] - can_create_operation = self.can_do(request, "change_operation") + can_create_operation = self.can_do( + request, "archaeological_operations.change_operation" + ) if can_create_operation and not self.operations.count(): actions.append( ( @@ -1439,14 +1454,20 @@ class Operation( icon_class="fa fa-pencil", text=_("Bulk update"), target="many", - rights=["change_operation", "change_own_operation"], + rights=[ + "archaeological_operations.change_operation", + "archaeological_operations.change_own_operation" + ], ) QA_LOCK = QuickAction( url="operation-qa-lock", icon_class="fa fa-lock", text=_("Lock/Unlock"), target="many", - rights=["change_operation", "change_own_operation"], + rights=[ + "archaeological_operations.change_operation", + "archaeological_operations.change_own_operation" + ], ) QUICK_ACTIONS = [ QA_EDIT, @@ -1456,7 +1477,10 @@ class Operation( icon_class="fa fa-clone", text=_("Duplicate"), target="one", - rights=["change_operation", "change_own_operation"], + rights=[ + "archaeological_operations.change_operation", + "archaeological_operations.change_own_operation" + ], ), ] @@ -2124,7 +2148,9 @@ class Operation( actions = super(Operation, self).get_extra_actions(request) is_locked = self.is_locked(request.user) - can_edit_operation = self.can_do(request, "change_operation") + can_edit_operation = self.can_do( + request, "archaeological_operations.change_operation" + ) if can_edit_operation and not is_locked: actions = [ ( @@ -2138,10 +2164,14 @@ class Operation( ] + actions profile = get_current_profile() - can_add_geo = profile.mapping and self.can_do(request, "add_geovectordata") + can_add_geo = profile.mapping and self.can_do( + request, "ishtar_common.add_geovectordata" + ) if can_add_geo: actions.append(self.get_add_geo_action()) - can_add_cr = self.can_do(request, "add_contextrecord") + can_add_cr = self.can_do( + request, "archaeological_context_records.add_contextrecord" + ) if can_add_cr and not is_locked: start = actions end = [] @@ -2158,7 +2188,8 @@ class Operation( True, ), ] + end - if profile.files and self.can_do(request, "add_administrativeact"): + if profile.files and self.can_do( + request, "archaeological_operations.add_administrativeact"): actions += [ ( reverse("operation-add-adminact", args=[self.pk]), diff --git a/archaeological_operations/urls.py b/archaeological_operations/urls.py index 7f5080c39..ba96c64b2 100644 --- a/archaeological_operations/urls.py +++ b/archaeological_operations/urls.py @@ -21,7 +21,7 @@ from django.conf.urls import url from django.urls import path, register_converter from ishtar_common import urls_converters -from ishtar_common.utils import check_rights +from ishtar_common.utils import check_permissions from archaeological_operations import views from archaeological_operations import views_api from archaeological_operations import models @@ -29,27 +29,27 @@ from archaeological_operations import models register_converter(urls_converters.UnderscoreSlug, "uslug") -# be carreful: each check_rights must be relevant with ishtar_menu +# be carreful: each check_permissions must be relevant with ishtar_menu # forms urlpatterns = [ url( r"operation_administrativeactop_search/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.operation_administrativeactop_search_wizard ), name="operation_administrativeactop_search", ), url( r"operation_administrativeactop/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.operation_administrativeactop_wizard ), name="operation_administrativeactop", ), url( r"operation_administrativeactop_modification/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.operation_administrativeactop_modification_wizard ), name="operation_administrativeactop_modification", @@ -61,7 +61,7 @@ urlpatterns = [ ), url( r"operation_administrativeactop_deletion/(?P<step>.+)?$", - check_rights(["change_administrativeact"])( + check_permissions(["archaeological_operations.change_administrativeact"])( views.operation_administrativeactop_deletion_wizard ), name="operation_administrativeactop_deletion", @@ -73,29 +73,34 @@ urlpatterns = [ ), url( r"operation_search/(?P<step>.+)?$", - check_rights(["view_operation", "view_own_operation"])( - views.operation_search_wizard - ), + check_permissions( + ["archaeological_operations.view_operation", + "archaeological_operations.view_own_operation"] + )(views.operation_search_wizard), name="operation_search", ), url( r"^operation-add-adminact/(?P<pk>[0-9-]+)/$", - check_rights(["add_administrativeact"])(views.operation_adminact_add), + check_permissions( + ["archaeological_operations.add_administrativeact"] + )(views.operation_adminact_add), name="operation-add-adminact", ), url( r"operation_creation/(?P<step>.+)?$", - check_rights(["add_operation", "add_own_operation"])( - views.operation_creation_wizard - ), + check_permissions( + ["archaeological_operations.add_operation", + "archaeological_operations.add_own_operation"] + )(views.operation_creation_wizard), name="operation_creation", ), url(r"operation_add/(?P<file_id>\d+)$", views.operation_add, name="operation_add"), url( r"operation_modification/(?P<step>.+)?$", - check_rights(["change_operation", "change_own_operation"])( - views.operation_modification_wizard - ), + check_permissions( + ["archaeological_operations.change_operation", + "archaeological_operations.change_own_operation"] + )(views.operation_modification_wizard), name="operation_modification", ), url( @@ -105,14 +110,17 @@ urlpatterns = [ ), url( r"operation_closing/(?P<step>.+)?$", - check_rights(["change_operation"])(views.operation_closing_wizard), + check_permissions( + ["archaeological_operations.change_operation"] + )(views.operation_closing_wizard), name="operation_closing", ), url( r"operation_deletion/(?P<step>.+)?$", - check_rights(["change_operation", "change_own_operation"])( - views.operation_deletion_wizard - ), + check_permissions( + ["archaeological_operations.change_operation", + "archaeological_operations.change_own_operation"] + )(views.operation_deletion_wizard), name="operation_deletion", ), url( @@ -122,9 +130,10 @@ urlpatterns = [ ), url( r"administrativact_register/(?P<step>.+)?$", - check_rights(["view_administrativeact", "view_own_administrativeact"])( - views.administrativact_register_wizard - ), + check_permissions( + ["archaeological_operations.view_administrativeact", + "archaeological_operations.view_own_administrativeact"] + )(views.administrativact_register_wizard), name="administrativact_register", ), url( @@ -267,29 +276,34 @@ urlpatterns = [ ), url( r"site_search/(?P<step>.+)?$", - check_rights(["view_archaeologicalsite", "view_own_archaeologicalsite"])( - views.site_search_wizard - ), + check_permissions( + ["archaeological_operations.view_archaeologicalsite", + "archaeological_operations.view_own_archaeologicalsite"] + )(views.site_search_wizard), name="site_search", ), url( r"site_creation/(?P<step>.+)?$", - check_rights(["add_archaeologicalsite", "add_own_archaeologicalsite"])( - views.site_creation_wizard - ), + check_permissions( + ["archaeological_operations.add_archaeologicalsite", + "archaeological_operations.add_own_archaeologicalsite"] + )(views.site_creation_wizard), name="site_creation", ), url( r"site_modification/(?P<step>.+)?$", - check_rights(["change_archaeologicalsite", "change_own_archaeologicalsite"])( - views.site_modification_wizard - ), + check_permissions( + ["archaeological_operations.change_archaeologicalsite", + "archaeological_operations.change_own_archaeologicalsite"] + )(views.site_modification_wizard), name="site_modification", ), url(r"site_modify/(?P<pk>.+)/$", views.site_modify, name="site_modify"), url( r"site_deletion/(?P<step>.+)?$", - check_rights(["change_archaeologicalsite"])(views.site_deletion_wizard), + check_permissions( + ["archaeological_operations.change_archaeologicalsite"] + )(views.site_deletion_wizard), name="site_deletion", ), url(r"site_delete/(?P<pk>.+)/$", views.site_delete, name="delete-site"), @@ -310,59 +324,67 @@ urlpatterns = [ ), url( r"^operation-relations-modify/(?P<pk>.+)/$", - check_rights(["change_operation", "change_own_operation"])( - views.operation_modify_relations - ), + check_permissions( + ["archaeological_operations.change_operation", + "archaeological_operations.change_own_operation"] + )(views.operation_modify_relations), name="operation-relation-modify", ), path( "operation-site-relations-modify/<int:pk>/", - check_rights(["change_operation", "change_own_operation"])( - views.operation_site_modify_relations - ), + check_permissions( + ["archaeological_operations.change_operation", + "archaeological_operations.change_own_operation"] + )(views.operation_site_modify_relations), name="operation-site-relations-modify", ), path( "operation-site-relations-modify/<int:pk>/<uslug:window_id>/", - check_rights(["change_operation", "change_own_operation"])( - views.operation_site_modify_relations - ), + check_permissions( + ["archaeological_operations.change_operation", + "archaeological_operations.change_own_operation"] + )(views.operation_site_modify_relations), name="operation-site-relations-modify", ), path( "site-operation-relations-modify/<int:pk>/", - check_rights(["change_operation", "change_own_operation"])( - views.site_operation_modify_relations - ), + check_permissions( + ["archaeological_operations.change_operation", + "archaeological_operations.change_own_operation"] + )(views.site_operation_modify_relations), name="site-operation-relations-modify", ), path( "site-operation-relations-modify/<int:pk>/<uslug:window_id>/", - check_rights(["change_operation", "change_own_operation"])( - views.site_operation_modify_relations - ), + check_permissions( + ["archaeological_operations.change_operation", + "archaeological_operations.change_own_operation"] + )(views.site_operation_modify_relations), name="site-operation-relations-modify", ), url( r"^operation-qa-bulk-update/(?P<pks>[0-9-]+)?/$", - check_rights(["change_operation", "change_own_operation"])( - views.QAOperationForm.as_view() - ), + check_permissions( + ["archaeological_operations.change_operation", + "archaeological_operations.change_own_operation"] + )(views.QAOperationForm.as_view()), name="operation-qa-bulk-update", ), url( r"^operation-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$", - check_rights(["change_operation", "change_own_operation"])( - views.QAOperationForm.as_view() - ), + check_permissions( + ["archaeological_operations.change_operation", + "archaeological_operations.change_own_operation"] + )(views.QAOperationForm.as_view()), name="operation-qa-bulk-update-confirm", kwargs={"confirm": True}, ), url( r"^operation-qa-duplicate/(?P<pks>[0-9-]+)?/$", - check_rights(["change_operation", "change_own_operation"])( - views.QAOperationdDuplicateFormView.as_view() - ), + check_permissions( + ["archaeological_operations.change_operation", + "archaeological_operations.change_own_operation"] + )(views.QAOperationdDuplicateFormView.as_view()), name="operation-qa-duplicate", ), url( @@ -373,9 +395,10 @@ urlpatterns = [ ), url( r"^site-qa-duplicate/(?P<pks>[0-9-]+)?/$", - check_rights(["change_archaeologicalsite", "change_own_archaeologicalsite"])( - views.QAArchaeologicalSiteDuplicateFormView.as_view() - ), + check_permissions( + ["archaeological_operations.change_archaeologicalsite", + "archaeological_operations.change_own_archaeologicalsite"] + )(views.QAArchaeologicalSiteDuplicateFormView.as_view()), name="site-qa-duplicate", ), url( @@ -386,29 +409,31 @@ urlpatterns = [ ), url( r"^site-qa-bulk-update/(?P<pks>[0-9-]+)?/$", - check_rights(["change_archaeologicalsite", "change_own_archaeologicalsite"])( - views.QAArchaeologicalSiteForm.as_view() - ), + check_permissions( + ["archaeological_operations.change_archaeologicalsite", + "archaeological_operations.change_own_archaeologicalsite"] + )(views.QAArchaeologicalSiteForm.as_view()), name="site-qa-bulk-update", ), url( r"^site-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$", - check_rights(["change_archaeologicalsite", "change_own_archaeologicalsite"])( - views.QAArchaeologicalSiteForm.as_view() - ), + check_permissions( + ["archaeological_operations.change_archaeologicalsite", + "archaeological_operations.change_own_archaeologicalsite"] + )(views.QAArchaeologicalSiteForm.as_view()), name="site-qa-bulk-update-confirm", kwargs={"confirm": True}, ), url( r"^site-add-operation/(?P<pks>[0-9-]+)?/$", - check_rights(["change_operation"])( + check_permissions(["archaeological_operations.change_operation"])( views.site_add_operation ), name="site-add-operation", ), url( r"^site-add-top-operation/(?P<pks>\d+)?/$", - check_rights(["change_operation"])( + check_permissions(["archaeological_operations.change_operation"])( views.site_add_top_operation ), name="site-add-top-operation", diff --git a/archaeological_operations/views.py b/archaeological_operations/views.py index 20193e197..7b6a56597 100644 --- a/archaeological_operations/views.py +++ b/archaeological_operations/views.py @@ -23,14 +23,14 @@ from jinja2 import TemplateSyntaxError from django.conf import settings from django.core.exceptions import PermissionDenied from django.db.models import Q -from django.forms.utils import ErrorDict, ErrorList +from django.forms.utils import ErrorList from django.http import HttpResponse, HttpResponseRedirect, Http404 from django.shortcuts import render, redirect from django.urls import reverse from django.views.generic import RedirectView from ishtar_common.utils import ugettext_lazy as _, pgettext_lazy from archaeological_operations.utils import parse_parcels -from django.forms import formset_factory, ValidationError +from django.forms import ValidationError from archaeological_operations import models from archaeological_operations import forms @@ -43,7 +43,7 @@ from ishtar_common.models import ( DocumentTemplate, ) from archaeological_context_records.models import ContextRecord -from ishtar_common.utils import put_session_message, check_rights_condition +from ishtar_common.utils import check_permissions_condition from ishtar_common.views import ( gen_generate_doc, QAItemEditForm, @@ -58,14 +58,12 @@ from ishtar_common.wizards import SearchWizard def autocomplete_patriarche(request): + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse(content_type="text/plain") if ( - not request.user.has_perm("ishtar_common.view_operation", models.Operation) - and not request.user.has_perm( - "ishtar_common.view_own_operation", models.Operation - ) - and not request.user.ishtaruser.has_right( - "operation_search", session=request.session - ) + not ishtaruser.has_permission("archaeological_operations.view_operation") + and not ishtaruser.has_permission("archaeological_operations.view_own_operation") ): return HttpResponse(content_type="text/plain") if not request.GET.get("term"): @@ -88,11 +86,13 @@ def autocomplete_patriarche(request): def autocomplete_archaeologicalsite(request): - if not request.user.has_perm( - "archaeological_operations.view_archaeologicalsite", models.ArchaeologicalSite - ) and not request.user.has_perm( + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse(content_type="text/plain") + if not ishtaruser.has_permission( + "archaeological_operations.view_archaeologicalsite" + ) and not ishtaruser.has_permission( "archaeological_operations.view_own_archaeologicalsite", - models.ArchaeologicalSite, ): return HttpResponse(content_type="text/plain") if not request.GET.get("term"): @@ -121,14 +121,14 @@ new_archaeologicalsite = new_qa_item( def autocomplete_operation(request): + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse(content_type="text/plain") # person_types = request.user.ishtaruser.person.person_type if ( - not request.user.has_perm("ishtar_common.view_operation", models.Operation) - and not request.user.has_perm( - "ishtar_common.view_own_operation", models.Operation - ) - and not request.user.ishtaruser.has_right( - "operation_search", session=request.session + not ishtaruser.has_permission("archaeological_operations.view_operation") + and not ishtaruser.has_permission( + "archaeological_operations.view_own_operation" ) ): return HttpResponse(content_type="text/plain") @@ -161,10 +161,13 @@ def autocomplete_operation(request): def get_available_operation_code(request, year=None): - if not request.user.has_perm( - "ishtar_common.view_operation", models.Operation - ) and not request.user.has_perm( - "ishtar_common.view_own_operation", models.Operation + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse(content_type="text/plain") + if not ishtaruser.has_permission( + "archaeological_operations.view_operation" + ) and not ishtaruser.has_permission( + "archaeological_operations.view_own_operation" ): return HttpResponse(content_type="text/plain") data = json.dumps({"id": models.Operation.get_available_operation_code(year)}) @@ -211,9 +214,8 @@ wizard_steps = [ def get_check_files_for_operation(other_check=None): def func(self): - if not get_current_profile().files or not check_rights_condition(["view_file"])( - self - ): + if not get_current_profile().files or \ + not check_permissions_condition(["archaeological_files.view_file"])(self): return False if not other_check: return True @@ -975,7 +977,10 @@ def administrativeactfile_document( search_form = AdministrativeActTreatmentFileFormSelection document_type = "TF" - if not request.user.has_perm("view_administrativeact", models.AdministrativeAct): + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse(content_type="text/plain") + if not ishtaruser.has_permission("archaeological_operations.view_administrativeact"): return HttpResponse(content_type="text/plain") dct = {} DocumentGenerationAdminActForm = forms.DocumentGenerationAdminActForm @@ -1032,10 +1037,13 @@ def administrativeactfile_document( def autocomplete_administrativeact(request): - if not request.user.has_perm( - "archaeological_operations.view_administrativeact", models.AdministrativeAct - ) and not request.user.has_perm( - "archaeological_operations.view_own_administrativeact", models.AdministrativeAct + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse(content_type="text/plain") + if not ishtaruser.has_permission( + "archaeological_operations.view_administrativeact" + ) and not ishtaruser.has_permission( + "archaeological_operations.view_own_administrativeact" ): return HttpResponse(content_type="text/plain") if not request.GET.get("term"): diff --git a/archaeological_warehouse/ishtar_menu.py b/archaeological_warehouse/ishtar_menu.py index 851ec3643..c0b8d658b 100644 --- a/archaeological_warehouse/ishtar_menu.py +++ b/archaeological_warehouse/ishtar_menu.py @@ -23,7 +23,7 @@ from ishtar_common.menu_base import SectionItem, MenuItem from . import models -# be careful: each access_controls must be relevant with check_rights in urls +# be careful: each access_controls must be relevant with check_permissions in urls MENU_SECTIONS = [ @@ -39,14 +39,17 @@ MENU_SECTIONS = [ "warehouse_search", _("Search"), model=models.Warehouse, - access_controls=["view_warehouse", "view_own_warehouse"], + access_controls=[ + "archaeological_warehouse.view_warehouse", + "archaeological_warehouse.view_own_warehouse" + ], ), MenuItem( "warehouse_creation", _("Creation"), model=models.Warehouse, access_controls=[ - "add_warehouse", + "archaeological_warehouse.add_warehouse", ], ), MenuItem( @@ -54,7 +57,7 @@ MENU_SECTIONS = [ _("Modification"), model=models.Warehouse, access_controls=[ - "change_warehouse", + "archaeological_warehouse.change_warehouse", ], ), MenuItem( @@ -62,7 +65,7 @@ MENU_SECTIONS = [ _("Deletion"), model=models.Warehouse, access_controls=[ - "change_warehouse", + "archaeological_warehouse.change_warehouse", ], ), ], @@ -80,42 +83,48 @@ MENU_SECTIONS = [ "container_search", _("Search"), model=models.Warehouse, - access_controls=["view_container", "view_own_container"], + access_controls=[ + "archaeological_warehouse.view_container", + "archaeological_warehouse.view_own_container" + ], ), MenuItem( "container_creation", _("Creation"), model=models.Warehouse, - access_controls=["add_container", "add_own_container"], + access_controls=[ + "archaeological_warehouse.add_container", + "archaeological_warehouse.add_own_container" + ], ), MenuItem( "container_modification", _("Modification"), model=models.Warehouse, access_controls=[ - "change_container", - "change_own_container", + "archaeological_warehouse.change_container", + "archaeological_warehouse.change_own_container", ], ), MenuItem( "container-merge", _("Automatic merge"), model=models.Container, - access_controls=["administrator"], + access_controls=["ishtaradmin"], ), MenuItem( "container-manual-merge", _("Manual merge"), model=models.Container, - access_controls=["administrator"], + access_controls=["ishtaradmin"], ), MenuItem( "container_deletion", _("Deletion"), model=models.Warehouse, access_controls=[ - "change_container", - "change_own_container", + "archaeological_warehouse.change_container", + "archaeological_warehouse.change_own_container", ], ), ], diff --git a/archaeological_warehouse/models.py b/archaeological_warehouse/models.py index 3cb04816d..9aa5549db 100644 --- a/archaeological_warehouse/models.py +++ b/archaeological_warehouse/models.py @@ -32,7 +32,8 @@ from django.urls import reverse from ishtar_common.utils import ugettext_lazy as _, pgettext_lazy from django.apps import apps -from ishtar_common.data_importer import post_importer_action, pre_importer_action, ImporterError +from ishtar_common.data_importer import post_importer_action, pre_importer_action, \ + ImporterError from ishtar_common.model_managers import UUIDModelManager from ishtar_common.models import ValueGetter, get_current_profile, HistoryModel, Imported from ishtar_common.models_common import ( @@ -377,7 +378,10 @@ class Warehouse( icon_class="fa fa-pencil", text=_("Bulk update"), target="many", - rights=["change_warehouse", "change_own_warhouse"], + rights=[ + "archaeological_warehouse.change_warehouse", + "archaeological_warehouse.change_own_warhouse" + ], ) QA_LOCK = QuickAction( @@ -385,7 +389,10 @@ class Warehouse( icon_class="fa fa-lock", text=_("Lock/Unlock"), target="many", - rights=["change_warehouse", "change_own_warehouse"], + rights=[ + "archaeological_warehouse.change_warehouse", + "archaeological_warehouse.change_own_warehouse" + ], ) QUICK_ACTIONS = [ QA_LOCK, @@ -1105,21 +1112,30 @@ class Container( icon_class="fa fa-pencil", text=_("Bulk update"), target="many", - rights=["change_container", "change_own_container"], + rights=[ + "archaeological_warehouse.change_container", + "archaeological_warehouse.change_own_container" + ], ) QA_MOVE = QuickAction( url="container-qa-move", icon_class="fa fa-arrow-right", text=pgettext_lazy("action", "Move"), target="many", - rights=["change_container", "change_own_container"], + rights=[ + "archaeological_warehouse.change_container", + "archaeological_warehouse.change_own_container" + ], ) QA_LOCK = QuickAction( url="container-qa-lock", icon_class="fa fa-lock", text=_("Lock/Unlock"), target="many", - rights=["change_container", "change_own_container"], + rights=[ + "archaeological_warehouse.change_container", + "archaeological_warehouse.change_own_container" + ], ) QUICK_ACTIONS = [QA_EDIT, QA_MOVE, QA_LOCK] @@ -1939,7 +1955,7 @@ class Container( """ # url, base_text, icon, extra_text, extra css class, is a quick action actions = super(Container, self).get_extra_actions(request) - can_edit_find = self.can_do(request, "change_find") + can_edit_find = self.can_do(request, "archaeological_finds.change_find") if can_edit_find: actions += [ ( diff --git a/archaeological_warehouse/tests.py b/archaeological_warehouse/tests.py index c218b7d0e..96df83024 100644 --- a/archaeological_warehouse/tests.py +++ b/archaeological_warehouse/tests.py @@ -20,7 +20,7 @@ import datetime import json -from django.contrib.auth.models import Permission +from django.contrib.auth.models import Permission, User from django.db.utils import IntegrityError from django.test.client import Client from django.urls import reverse @@ -560,6 +560,7 @@ class ContainerQATest(FindInit, TestCase): def setUp(self): self.get_default_user() + self.alt_username, self.alt_password, self.alt_user = create_user() self.main_warehouse = models.Warehouse.objects.create( name="Main", warehouse_type=models.WarehouseType.objects.all()[0] ) @@ -638,16 +639,16 @@ class ContainerQATest(FindInit, TestCase): response = c.get(url) self.assertRedirects(response, "/") c = Client() - c.login(username=self.username, password=self.password) + c.login(username=self.alt_username, password=self.alt_password) response = c.get(url) # change_container permission is needed - self.assertEqual(response.status_code, 404) + self.assertEqual(response.status_code, 302) c.logout() - self.user.user_permissions.add( + self.alt_user.user_permissions.add( Permission.objects.get(codename="change_container") ) - c.login(username=self.username, password=self.password) + c.login(username=self.alt_username, password=self.alt_password) response = c.get(url) self.assertEqual(response.status_code, 200) diff --git a/archaeological_warehouse/urls.py b/archaeological_warehouse/urls.py index a41852b8b..669732a57 100644 --- a/archaeological_warehouse/urls.py +++ b/archaeological_warehouse/urls.py @@ -20,19 +20,20 @@ from django.conf.urls import url from django.urls import path -from ishtar_common.utils import check_rights +from ishtar_common.utils import check_permissions from archaeological_warehouse import models, views, views_api -# be careful: each check_rights must be relevant with ishtar_menu +# be careful: each check_permissions must be relevant with ishtar_menu # forms urlpatterns = [ url( r"warehouse_packaging/(?P<step>.+)?$", # AFAC - check_rights(["change_find", "change_own_find"])( - views.warehouse_packaging_wizard - ), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.warehouse_packaging_wizard), name="warehouse_packaging", ), url( @@ -105,19 +106,24 @@ urlpatterns = [ ), url( r"^warehouse_search/(?P<step>.+)?$", - check_rights(["view_warehouse", "view_own_warehouse"])( - views.warehouse_search_wizard - ), + check_permissions( + ["archaeological_warehouse.view_warehouse", + "archaeological_warehouse.view_own_warehouse"] + )(views.warehouse_search_wizard), name="warehouse_search", ), url( r"^warehouse_creation/(?P<step>.+)?$", - check_rights(["add_warehouse"])(views.warehouse_creation_wizard), + check_permissions( + ["archaeological_warehouse.add_warehouse"] + )(views.warehouse_creation_wizard), name="warehouse_creation", ), url( r"^warehouse_modification/(?P<step>.+)?$", - check_rights(["change_warehouse"])(views.warehouse_modification_wizard), + check_permissions( + ["archaeological_warehouse.change_warehouse"] + )(views.warehouse_modification_wizard), name="warehouse_modification", ), url( @@ -127,7 +133,9 @@ urlpatterns = [ ), url( r"^warehouse_deletion/(?P<step>.+)?$", - check_rights(["change_warehouse"])(views.warehouse_deletion_wizard), + check_permissions( + ["archaeological_warehouse.change_warehouse"] + )(views.warehouse_deletion_wizard), name="warehouse_deletion", ), url( @@ -143,49 +151,51 @@ urlpatterns = [ ), url( r"^warehouse-qa-bulk-update/(?P<pks>[0-9-]+)?/$", - check_rights([ - "change_warehouse", - "change_own_warehouse" - ])( - views.QAWarehouseForm.as_view() - ), + check_permissions([ + "archaeological_warehouse.change_warehouse", + "archaeological_warehouse.change_own_warehouse" + ])(views.QAWarehouseForm.as_view()), name="warehouse-qa-bulk-update", ), url( r"^warehouse-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$", - check_rights([ - "change_warehouse", - "change_own_warehouse", - ])( - views.QAWarehouseForm.as_view() - ), + check_permissions([ + "archaeological_warehouse.change_warehouse", + "archaeological_warehouse.change_own_warehouse", + ])(views.QAWarehouseForm.as_view()), name="warehouse-qa-bulk-update-confirm", kwargs={"confirm": True}, ), url( r"^container-add-treatment/(?P<pk>[0-9-]+)/$", - check_rights(["change_find", "change_own_find"])(views.container_treatment_add), + check_permissions( + ["archaeological_finds.change_find", + "archaeological_finds.change_own_find"] + )(views.container_treatment_add), name="container-add-treatment", ), url( r"^container_search/(?P<step>.+)?$", - check_rights(["view_container", "view_own_container"])( - views.container_search_wizard - ), + check_permissions( + ["archaeological_warehouse.view_container", + "archaeological_warehouse.view_own_container"] + )(views.container_search_wizard), name="container_search", ), url( r"^container_creation/(?P<step>.+)?$", - check_rights(["add_container", "add_own_container"])( - views.container_creation_wizard - ), + check_permissions( + ["archaeological_warehouse.add_container", + "archaeological_warehouse.add_own_container"] + )(views.container_creation_wizard), name="container_creation", ), url( r"^container_modification/(?P<step>.+)?$", - check_rights(["change_container", "change_own_container"])( - views.container_modification_wizard - ), + check_permissions( + ["archaeological_warehouse.change_container", + "archaeological_warehouse.change_own_container"] + )(views.container_modification_wizard), name="container_modification", ), url( @@ -195,9 +205,10 @@ urlpatterns = [ ), url( r"^container_deletion/(?P<step>.+)?$", - check_rights(["change_container", "change_own_container"])( - views.container_deletion_wizard - ), + check_permissions( + ["archaeological_warehouse.change_container", + "archaeological_warehouse.change_own_container"] + )(views.container_deletion_wizard), name="container_deletion", ), url( @@ -207,24 +218,27 @@ urlpatterns = [ ), url( r"^container-qa-bulk-update/(?P<pks>[0-9-]+)?/$", - check_rights(["change_container", "change_own_container"])( - views.QAContainerForm.as_view() - ), + check_permissions( + ["archaeological_warehouse.change_container", + "archaeological_warehouse.change_own_container"] + )(views.QAContainerForm.as_view()), name="container-qa-bulk-update", ), url( r"^container-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$", - check_rights(["change_container", "change_own_container"])( - views.QAContainerForm.as_view() - ), + check_permissions( + ["archaeological_warehouse.change_container", + "archaeological_warehouse.change_own_container"] + )(views.QAContainerForm.as_view()), name="container-qa-bulk-update-confirm", kwargs={"confirm": True}, ), url( r"^container-qa-move/(?P<pks>[0-9-]+)?/$", - check_rights(["change_container", "change_own_container"])( - views.QAContainerMoveForm.as_view() - ), + check_permissions( + ["archaeological_warehouse.change_container", + "archaeological_warehouse.change_own_container"] + )(views.QAContainerMoveForm.as_view()), name="container-qa-move", ), url( diff --git a/archaeological_warehouse/views.py b/archaeological_warehouse/views.py index 4b3f494d8..416849c9a 100644 --- a/archaeological_warehouse/views.py +++ b/archaeological_warehouse/views.py @@ -95,10 +95,13 @@ new_container = new_qa_item( def autocomplete_warehouse(request): - if not request.user.has_perm( - "ishtar_common.view_warehouse", models.Warehouse - ) and not request.user.has_perm( - "ishtar_common.view_own_warehouse", models.Warehouse + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse(content_type="text/plain") + if not ishtaruser.has_permission( + "archaeological_warehouse.view_warehouse" + ) and not ishtaruser.has_permission( + "archaeological_warehouse.view_own_warehouse", models.Warehouse ): return HttpResponse(content_type="text/plain") if not request.GET.get("term"): @@ -106,7 +109,8 @@ def autocomplete_warehouse(request): q = request.GET.get("term") query = Q() for q in q.split(" "): - extra = Q(name__icontains=q) | Q(slug__icontains=q) | Q(warehouse_type__label__icontains=q) + extra = Q(name__icontains=q) | Q(slug__icontains=q) | \ + Q(warehouse_type__label__icontains=q) query = query & extra limit = 15 warehouses = models.Warehouse.objects.filter(query)[:limit] @@ -117,10 +121,13 @@ def autocomplete_warehouse(request): def autocomplete_container(request, warehouse_id=None): - if not request.user.has_perm( - "ishtar_common.view_warehouse", models.Warehouse - ) and not request.user.has_perm( - "ishtar_common.view_own_warehouse", models.Warehouse + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse(content_type="text/plain") + if not ishtaruser.has_permission( + "archaeological_warehouse.view_container" + ) and not ishtaruser.has_permission( + "archaeological_warehouse.view_own_container" ): return HttpResponse(content_type="text/plain") if not request.GET.get("term"): diff --git a/ishtar_common/backend.py b/ishtar_common/backend.py index 00f90f444..c69a92d10 100644 --- a/ishtar_common/backend.py +++ b/ishtar_common/backend.py @@ -32,6 +32,7 @@ class ObjectPermBackend(ModelBackend): supports_object_permissions = True supports_anonymous_user = True + """ def has_perm(self, user_obj, perm, model=None, obj=None, session=None): if not user_obj.is_authenticated: return False @@ -48,7 +49,7 @@ class ObjectPermBackend(ModelBackend): is_ownperm = perm.split(".")[-1].split("_")[1] == "own" except IndexError: is_ownperm = False - if ishtar_user.has_right("administrator", session=session): + if ishtar_user.has_permission("ishtaradmin"): return True main_right = ishtar_user.person.has_right( perm, session=session @@ -65,3 +66,4 @@ class ObjectPermBackend(ModelBackend): return False return not is_ownperm or model.has_item_of(ishtar_user) return not is_ownperm or obj.is_own(user_obj) + """ diff --git a/ishtar_common/context_processors.py b/ishtar_common/context_processors.py index 74e38efc4..59d517192 100644 --- a/ishtar_common/context_processors.py +++ b/ishtar_common/context_processors.py @@ -181,7 +181,7 @@ def get_base_context(request): "search_model__app_label", "search_model__model" ).distinct() ] - if request.user.ishtaruser.has_right("administrator", session=request.session): + if request.user.ishtaruser.has_permission("ishtaradmin"): dct["ADMIN"] = True if ( request.user.ishtaruser.current_profile diff --git a/ishtar_common/forms.py b/ishtar_common/forms.py index ad76d63cd..e5ffeefb5 100644 --- a/ishtar_common/forms.py +++ b/ishtar_common/forms.py @@ -722,7 +722,7 @@ class IshtarForm(forms.Form, BSForm): if not any( True for permission in permissions - if ishtar_user.has_perm(permission) + if ishtar_user.has_permission(permission) ): continue for option, value in options.items(): @@ -1010,7 +1010,10 @@ class ImportSelect(HistorySelect): def __init__(self, *args, **kwargs): user = kwargs.get("user", None) super().__init__(*args, **kwargs) - if not user or (not user.has_perm("view_import") and not user.has_perm("view_own_import")): + ishtaruser = getattr(user, "ishtaruser", None) + if not ishtaruser or ( + not ishtaruser.has_permission("ishtar_common.view_import") + and not ishtaruser.has_permission("ishtar_common.view_own_import")): self.fields.pop("imports") diff --git a/ishtar_common/forms_common.py b/ishtar_common/forms_common.py index b1e4e7ef4..22e23f3ca 100644 --- a/ishtar_common/forms_common.py +++ b/ishtar_common/forms_common.py @@ -257,9 +257,13 @@ class BaseImportForm(IshtarForm, forms.ModelForm): self._post_init() def _filter_importer_type_query(self, q, user): - if user.is_superuser or user.ishtaruser.has_right("add_import"): + ishtaruser = getattr(user, "ishtaruser", None) + if not ishtaruser: + self.fields["importer_type"].choices = [("", "--")] + return + if user.is_superuser or ishtaruser.has_permission("ishtar_common.add_import"): return q - if not user.ishtaruser.has_right("add_own_import"): + if not user.ishtaruser.has_permission("ishtar_common.add_own_import"): self.fields["importer_type"].choices = [("", "--")] return q = q.filter(users__pk=user.ishtaruser.pk) @@ -555,10 +559,12 @@ class TargetKeyForm(forms.ModelForm): self.associated_import = None if instance and instance.pk: model = instance.target.associated_model + ishtaruser = getattr(self.user, "ishtaruser", None) + meta = model._meta if ( model - and self.user.has_perm( - "{}.change_{}".format(model._meta.app_label, model._meta.model_name) + and ishtaruser.has_permission( + f"{meta.app_label}.change_{meta.model_name}" ) and hasattr(model, "admin_url") ): diff --git a/ishtar_common/ishtar_menu.py b/ishtar_common/ishtar_menu.py index 5c2d1bdb1..aa8ed3b8f 100644 --- a/ishtar_common/ishtar_menu.py +++ b/ishtar_common/ishtar_menu.py @@ -23,7 +23,7 @@ from ishtar_common.menu_base import SectionItem, MenuItem from . import models -# be careful: each access_controls must be relevant with check_rights in urls +# be careful: each access_controls must be relevant with check_permissions in urls MENU_SECTIONS = [ (1, SectionItem("home", _("Home"), childs=[])), @@ -41,37 +41,39 @@ MENU_SECTIONS = [ "person_search", _("Search"), model=models.Person, - access_controls=["add_person"], + access_controls=["ishtar_common.add_person"], ), MenuItem( "person_creation", _("Creation"), model=models.Person, - access_controls=["add_person"], + access_controls=["ishtar_common.add_person"], ), MenuItem( "person_modification", _("Modification"), model=models.Person, - access_controls=["change_person", "change_own_person"], + access_controls=["ishtar_common.change_person", + "ishtar_common.change_own_person"], ), MenuItem( "person-merge", _("Automatic merge"), model=models.Person, - access_controls=["administrator"], + access_controls=["ishtaradmin"], ), MenuItem( "person-manual-merge", _("Manual merge"), model=models.Person, - access_controls=["administrator"], + access_controls=["ishtaradmin"], ), MenuItem( "person_deletion", _("Deletion"), model=models.Person, - access_controls=["change_person", "change_own_person"], + access_controls=["ishtar_common.change_person", + "ishtar_common.change_own_person"], ), ], ), @@ -84,7 +86,7 @@ MENU_SECTIONS = [ _("Addition/modification"), model=models.IshtarUser, access_controls=[ - "administrator", + "ishtaradmin", ], ), MenuItem( @@ -92,7 +94,7 @@ MENU_SECTIONS = [ _("Deletion"), model=models.IshtarUser, access_controls=[ - "administrator", + "ishtaradmin", ], ), ], @@ -106,8 +108,8 @@ MENU_SECTIONS = [ _("Search"), model=models.Organization, access_controls=[ - "add_organization", - "add_own_organization", + "ishtar_common.add_organization", + "ishtar_common.add_own_organization", ], ), MenuItem( @@ -115,8 +117,8 @@ MENU_SECTIONS = [ _("Creation"), model=models.Organization, access_controls=[ - "add_organization", - "add_own_organization", + "ishtar_common.add_organization", + "ishtar_common.add_own_organization", ], ), MenuItem( @@ -124,29 +126,29 @@ MENU_SECTIONS = [ _("Modification"), model=models.Organization, access_controls=[ - "change_organization", - "change_own_organization", + "ishtar_common.change_organization", + "ishtar_common.change_own_organization", ], ), MenuItem( "organization-merge", _("Automatic merge"), model=models.Organization, - access_controls=["administrator"], + access_controls=["ishtaradmin"], ), MenuItem( "orga-manual-merge", _("Manual merge"), model=models.Organization, - access_controls=["administrator"], + access_controls=["ishtaradmin"], ), MenuItem( "organization_deletion", _("Deletion"), model=models.Organization, access_controls=[ - "change_organization", - "change_own_organization", + "ishtar_common.change_organization", + "ishtar_common.change_own_organization", ], ), ], @@ -164,13 +166,15 @@ MENU_SECTIONS = [ "import-list", _("Current imports"), model=models.Import, - access_controls=["view_import", "change_import"], + access_controls=["ishtar_common.view_import", + "ishtar_common.change_import"], ), MenuItem( "import-list-old", _("Old imports"), model=models.Import, - access_controls=["view_import", "change_import"], + access_controls=["ishtar_common.view_import", + "ishtar_common.change_import"], ), ], ), @@ -185,25 +189,29 @@ MENU_SECTIONS = [ "document/search", _("Search"), model=models.Document, - access_controls=["view_document", "view_own_document"], + access_controls=["ishtar_common.view_document", + "ishtar_common.view_own_document"], ), MenuItem( "document/create", _("Creation"), model=models.Document, - access_controls=["add_document", "add_own_document"], + access_controls=["ishtar_common.add_document", + "ishtar_common.add_own_document"], ), MenuItem( "document/edit", _("Modification"), model=models.Document, - access_controls=["change_document", "change_own_document"], + access_controls=["ishtar_common.change_document", + "ishtar_common.change_own_document"], ), MenuItem( "document/delete", _("Deletion"), model=models.Document, - access_controls=["change_document", "change_own_document"], + access_controls=["ishtar_common.change_document", + "ishtar_common.change_own_document"], ), ], ), diff --git a/ishtar_common/menu_base.py b/ishtar_common/menu_base.py index e8470787a..e0f206a57 100644 --- a/ishtar_common/menu_base.py +++ b/ishtar_common/menu_base.py @@ -43,28 +43,28 @@ class SectionItem: return False return True - def can_be_available(self, user, session=None): + def can_be_available(self, user): if not self.check_profile_restriction(): return False if not self.childs: return True for child in self.childs: - if child.can_be_available(user, session=session): + if child.can_be_available(user): return True return False - def is_available(self, user, obj=None, session=None): + def is_available(self, user, obj=None): if not self.childs: return True for child in self.childs: - if child.is_available(user, obj, session=session): + if child.is_available(user, obj): return True return False def set_items(self, user, items, current_action=None, session=None): selected = None if user: - self.available = self.can_be_available(user, session=session) + self.available = self.can_be_available(user) for child in self.childs: selected = ( child.set_items(user, items, current_action, session=session) @@ -101,35 +101,37 @@ class MenuItem: return False return True - def can_be_available(self, user, session=None): + def can_be_available(self, user): if not self.check_profile_restriction(): return False if not self.access_controls: return True if not hasattr(user, "ishtaruser"): return False + ishtaruser = user.ishtaruser for access_control in self.access_controls: # check by profile - if user.ishtaruser.person.has_right(access_control, session=session): + if ishtaruser.has_permission(access_control): return True return False - def is_available(self, user, obj=None, session=None): + def is_available(self, user, obj=None): if not self.check_profile_restriction(): return False if not self.access_controls: return True if not hasattr(user, "ishtaruser"): return False + ishtaruser = user.ishtaruser for access_control in self.access_controls: - if user.ishtaruser.person.has_right( - access_control, obj=obj, session=session + if ishtaruser.has_permission( + access_control, obj=obj ): return True return False def set_items(self, user, items, current_action=None, session=None): if user: - self.available = self.can_be_available(user, session=session) + self.available = self.can_be_available(user) if self.idx == current_action: return True diff --git a/ishtar_common/menus.py b/ishtar_common/menus.py index b167c1765..aae127a09 100644 --- a/ishtar_common/menus.py +++ b/ishtar_common/menus.py @@ -135,20 +135,20 @@ class Menu: self.items_by_idx = {} childs = deepcopy(self.ref_childs) for idx, main_menu in enumerate(reversed(childs)): - if not main_menu.can_be_available(self.user, self.session): + if not main_menu.can_be_available(self.user): childs.pop(len(self.ref_childs) - idx - 1) continue self.items_by_idx[main_menu.idx] = main_menu sub_childs = main_menu.childs[:] for s_idx, child in enumerate(reversed(main_menu.childs)): - if not child.can_be_available(self.user, self.session): + if not child.can_be_available(self.user): sub_childs.pop(len(main_menu.childs) - s_idx - 1) continue self.items_by_idx[child.idx] = child if hasattr(child, "childs"): sub_sub_childs = child.childs[:] for ss_idx, subchild in enumerate(reversed(child.childs)): - if not subchild.can_be_available(self.user, self.session): + if not subchild.can_be_available(self.user): sub_sub_childs.pop(len(child.childs) - ss_idx - 1) continue self.items_by_idx[subchild.idx] = subchild diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 5f57e8398..b1f226088 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -2665,7 +2665,7 @@ class Organization(Address, Merge, OwnPerms, BaseGenderedType, ValueGetter, Main icon_class="fa fa-pencil", text=_("Bulk update"), target="many", - rights=["change_organization"], + rights=["ishtar_common.change_organization"], ) QUICK_ACTIONS = [QA_EDIT] @@ -2946,7 +2946,7 @@ class Person(Address, Merge, OwnPerms, ValueGetter, MainItem): icon_class="fa fa-pencil", text=_("Bulk update"), target="many", - rights=["change_person"], + rights=["ishtar_common.change_person"], ) QUICK_ACTIONS = [QA_EDIT] @@ -3130,72 +3130,6 @@ class Person(Address, Merge, OwnPerms, ValueGetter, MainItem): def is_natural(self): return not self.attached_to - def has_right(self, right_name, session=None, obj=None): - if "." in right_name: - right_name = right_name.split(".")[-1] - res, cache_key = "", "" - if session: - cache_key = "session-{}-{}".format(session.session_key, right_name) - res = cache.get(cache_key) - if res in (True, False): - return res - # list all cache key in order to clean them on profile change - cache_key_list = "sessionlist-{}".format(session.session_key) - key_list = cache.get(cache_key_list, []) - key_list.append(cache_key) - cache.set(cache_key_list, key_list, settings.CACHE_TIMEOUT) - if isinstance(right_name, (list, tuple)): - res = ( - bool( - self.profiles.filter( - current=True, profile_type__txt_idx__in=right_name - ).count() - ) - or bool( - self.profiles.filter( - current=True, - profile_type__groups__permissions__codename__in=right_name, - ).count() - ) - or bool( - self.ishtaruser.user_ptr.groups.filter( - permissions__codename__in=right_name - ).count() - ) - or bool( - self.ishtaruser.user_ptr.user_permissions.filter( - codename__in=right_name - ).count() - ) - ) - else: - res = ( - bool( - self.profiles.filter( - current=True, profile_type__txt_idx=right_name - ).count() - ) - or bool( - self.profiles.filter( - current=True, - profile_type__groups__permissions__codename=right_name, - ).count() - ) - or bool( - self.ishtaruser.user_ptr.groups.filter( - permissions__codename__in=[right_name] - ).count() - ) - or bool( - self.ishtaruser.user_ptr.user_permissions.filter( - codename__in=[right_name] - ).count() - ) - ) - if session: - cache.set(cache_key, res, settings.CACHE_TIMEOUT) - return res - def full_label(self): values = [] if self.title: @@ -3330,7 +3264,8 @@ class BiographicalNote(BaseHistorizedItem, ValueGetter, MainItem): url="biographicalnote-qa-edit", icon_class="fa fa-pencil", text=_("Edit biographical note"), - rights=["change_biographicalnote", "change_own_biographicalnote"], + rights=["ishtar_common.change_biographicalnote", + "ishtar_common.change_own_biographicalnote"], ) class Meta: @@ -3367,7 +3302,8 @@ class BiographicalNote(BaseHistorizedItem, ValueGetter, MainItem): return res def set_slug(self): - self.slug = create_slug(self.__class__, self.denomination, max_length=250, pk=self.pk) + self.slug = create_slug(self.__class__, self.denomination, max_length=250, + pk=self.pk) def get_extra_actions(self, request): """ @@ -3375,7 +3311,7 @@ class BiographicalNote(BaseHistorizedItem, ValueGetter, MainItem): """ # url, base_text, icon, extra_text, extra css class, is a quick action, actions = super().get_extra_actions(request) - can_edit = self.can_do(request, "change_biographicalnote") + can_edit = self.can_do(request, "ishtar_common.change_biographicalnote") if not can_edit: return actions actions += [ @@ -3823,11 +3759,54 @@ class IshtarUser(FullSearch): ) return cls.objects.create(user_ptr=user, person=person) - def has_right(self, right_name, session=None): - return self.person.has_right(right_name, session=session) - - def has_perm(self, perm, model=None, session=None, obj=None): - return self.person.has_right(perm, session=session, obj=None) + @property + def is_ishtaradmin(self): + is_ishtaradmin = getattr(self, "_is_ishtaradmin", None) + if is_ishtaradmin is not None: + return is_ishtaradmin + self._is_ishtaradmin = bool( + self.person.profiles.filter( + current=True, profile_type__txt_idx="administrator" + ).exists() + ) + return self._is_ishtaradmin + + def has_permission(self, permission, obj=None): + if permission == "ishtaradmin": + return self.is_ishtaradmin + if "." not in permission: + # TODO: perm delete + print(permission) + raise + if obj: + return self.user_ptr.has_perm(permission, obj) + return self.user_ptr.has_perm(permission) + """ + res = ( + bool( + self.profiles.filter( + current=True, profile_type__txt_idx=permission + ).count() + ) + or bool( + self.profiles.filter( + current=True, + profile_type__groups__permissions__codename=permission, + ).count() + ) + or bool( + self.ishtaruser.user_ptr.groups.filter( + permissions__codename__in=[permission] + ).count() + ) + or bool( + self.ishtaruser.user_ptr.user_permissions.filter( + codename__in=[permission] + ).count() + ) + ) + return res + """ def full_label(self): return self.person.full_label() @@ -4557,7 +4536,7 @@ class Document( icon_class="fa fa-pencil", text=_("Bulk update"), target="many", - rights=["change_document", "change_own_document"], + rights=["ishtar_common.change_document", "ishtar_common.change_own_document"], ) QUICK_ACTIONS = [ QA_EDIT, @@ -4566,14 +4545,14 @@ class Document( icon_class="fa fa-clone", text=_("Duplicate"), target="one", - rights=["change_document", "change_own_document"], + rights=["ishtar_common.change_document", "ishtar_common.change_own_document"], ), QuickAction( url="document-qa-packaging", icon_class="fa fa-gift", text=_("Packaging"), target="many", - rights=["change_document", "change_own_document"], + rights=["ishtar_common.change_document", "ishtar_common.change_own_document"], module="warehouse", ), ] @@ -4937,7 +4916,7 @@ class Document( actions = super(Document, self).get_extra_actions(request) # is_locked = self.is_locked(request.user) - can_edit_document = self.can_do(request, "change_document") + can_edit_document = self.can_do(request, "ishtar_common.change_document") if not can_edit_document: return actions actions += [ @@ -4961,7 +4940,7 @@ class Document( True, ) ) - can_create_document = self.can_do(request, "add_document") + can_create_document = self.can_do(request, "ishtar_common.add_document") if can_create_document: actions += [ ( diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py index 6f995569c..4a266af9c 100644 --- a/ishtar_common/models_common.py +++ b/ishtar_common/models_common.py @@ -1182,13 +1182,17 @@ class Imported(models.Model): abstract = True def _get_imports(self, user, key, limit): - if not user.ishtaruser: + ishtaruser = getattr(user, "ishtaruser", None) + if not ishtaruser: return [] q = getattr(self, key) - if user.is_superuser or user.ishtaruser.has_right("view_import"): + if ishtaruser.has_permission("ishtaradmin") or \ + ishtaruser.has_permission("ishtar_common.view_import"): q = q.all() - elif user.ishtaruser.has_right("view_own_import"): - q = q.filter(Q(user=user.ishtaruser) | Q(importer_type__users__pk=user.ishtaruser.pk)) + elif ishtaruser.has_permission("ishtar_common.view_own_import"): + q = q.filter(Q(user=user.ishtaruser) | Q( + importer_type__users__pk=user.ishtaruser.pk) + ) else: return [] q = q.order_by("-id") @@ -1946,7 +1950,8 @@ class DocumentItem: @property def pdf_attached(self): for document in self.documents.filter( - Q(associated_file__isnull=False) | Q(source__associated_file__isnull=False) + Q(associated_file__isnull=False) | + Q(source__associated_file__isnull=False) ).all(): return document.pdf_attached @@ -1967,7 +1972,7 @@ class DocumentItem: print(f"**WARNING** can_do not implemented for {self.__class__}") return actions - can_add_doc = self.can_do(request, "add_document") + can_add_doc = self.can_do(request, "ishtar_common.add_document") if can_add_doc and ( not hasattr(self, "is_locked") or not self.is_locked(request.user) ): @@ -3318,13 +3323,13 @@ class MainItem(ShortMenuItem, SerializeItem, SheetItem): pass @classmethod - def get_quick_actions(cls, user, session=None, obj=None): + def get_quick_actions(cls, user): """ Get a list of (url, title, icon, target) actions for an user """ qas = [] for action in cls.QUICK_ACTIONS: - if not action.is_available(user, session=session, obj=obj): + if not action.is_available(user): continue qas.append( [ @@ -3376,14 +3381,14 @@ class MainItem(ShortMenuItem, SerializeItem, SheetItem): """ Check permission availability for the current object. :param request: request object - :param action_name: action name eg: "change_find" + :param action_name: action name eg: "archaeological_finds.change_find" :return: boolean """ # overload with OwnPerm when _own_ is relevant if not getattr(request.user, "ishtaruser", None): return False user = request.user - return user.ishtaruser.has_right(action_name, request.session) + return user.ishtaruser.has_permission(action_name) def get_extra_actions(self, request): if not hasattr(self, "SLUG"): @@ -3636,7 +3641,9 @@ class Town(GeographicItem, Imported, DocumentItem, MainItem, models.Model): # url, base_text, icon, extra_text, extra css class, is a quick action actions = super().get_extra_actions(request) profile = get_current_profile() - can_add_geo = profile.mapping and self.can_do(request, "add_geovectordata") + can_add_geo = profile.mapping and self.can_do( + request, "ishtar_common.add_geovectordata" + ) if can_add_geo: actions.append(self.get_add_geo_action()) return actions @@ -4168,7 +4175,7 @@ class QuickAction: if self.target not in ("one", "many", None): raise AttributeError("target must be one, many or None") - def is_available(self, user, session=None, obj=None): + def is_available(self, user, obj=None): if self.module and not getattr(get_current_profile(), self.module): return False if not self.rights: # no restriction @@ -4178,7 +4185,7 @@ class QuickAction: user = user.ishtaruser for right in self.rights: - if user.has_perm(right, session=session, obj=obj): + if user.has_permission(right, obj=obj): return True return False diff --git a/ishtar_common/models_imports.py b/ishtar_common/models_imports.py index 5e29b98ed..ddb23e490 100644 --- a/ishtar_common/models_imports.py +++ b/ishtar_common/models_imports.py @@ -1447,25 +1447,28 @@ class BaseImport(models.Model, OwnPerms, SheetItem): abstract = True @classmethod - def get_permissions_for_actions(cls, user, session): + def get_permissions_for_actions(cls, user): if not hasattr(user, "ishtaruser") or not user.ishtaruser: return False, False, False, False - can_edit_all, can_delete_all, can_edit_own, can_delete_own = False, False, False, False - if user.is_superuser: + can_edit_all, can_delete_all = False, False + can_edit_own, can_delete_own = False, False + ishtaruser = user.ishtaruser + if ishtaruser.has_permission("ishtaradmin"): can_edit_all = True can_delete_all = True - if user.ishtaruser.has_right("change_import", session=session): - can_edit_all = True - elif user.ishtaruser.has_right("change_own_import", session=session): - can_edit_own = True - if user.ishtaruser.has_right("delete_import", session=session): - can_delete_all = True - elif user.ishtaruser.has_right("delete_own_import", session=session): - can_delete_own = True + else: + if ishtaruser.has_permission("ishtar_common.change_import"): + can_edit_all = True + elif ishtaruser.has_permission("ishtar_common.change_own_import"): + can_edit_own = True + if ishtaruser.has_permission("ishtar_common.delete_import"): + can_delete_all = True + elif ishtaruser.has_permission("ishtar_common.delete_own_import"): + can_delete_own = True return can_edit_all, can_delete_all, can_edit_own, can_delete_own @classmethod - def query_can_access(cls, user, perm="view_import"): + def query_can_access(cls, user, perm="ishtar_common.view_import"): """ Filter the query to check access permissions :param user: User instance @@ -1474,8 +1477,11 @@ class BaseImport(models.Model, OwnPerms, SheetItem): q = cls.objects if not isinstance(perm, (list, tuple)): perm = [perm] - if user.is_superuser or (hasattr(user, "ishtaruser") and user.ishtaruser and - any(user.ishtaruser.has_right(p) for p in perm)): + ishtaruser = getattr(user, "ishtaruser", None) + if not ishtaruser: + return q.filter(pk__isnull=True) + if ishtaruser.has_permission("ishtaradmin") or ( + any(ishtaruser.has_permission(p) for p in perm)): return q q = q.filter(Q(importer_type__users__pk=user.ishtaruser.pk)) return q diff --git a/ishtar_common/templatetags/window_header.py b/ishtar_common/templatetags/window_header.py index bfcd95883..23d779944 100644 --- a/ishtar_common/templatetags/window_header.py +++ b/ishtar_common/templatetags/window_header.py @@ -19,7 +19,9 @@ def window_nav(context, item, window_id, show_url, modify_url='', histo_url='', extra_actions = [] if hasattr(item, 'get_extra_actions'): try: - extra_actions = item.get_extra_actions(context['request'], context["window_id_underscore"]) + extra_actions = item.get_extra_actions( + context['request'], context["window_id_underscore"] + ) except (KeyError, TypeError): extra_actions = item.get_extra_actions(context['request']) extra_actions = sorted_actions(extra_actions) @@ -27,14 +29,8 @@ def window_nav(context, item, window_id, show_url, modify_url='', histo_url='', if hasattr(item, 'get_extra_templates'): extra_templates = item.get_extra_templates(context['request']) - slug = None - if hasattr(item, "LONG_SLUG"): - slug = item.LONG_SLUG - elif hasattr(item, "SLUG"): - slug = item.SLUG modify_url_value, delete_url = None, None - can_edit = hasattr(item, 'can_do') and slug and \ - item.can_do(context['request'], 'change_' + slug) + can_edit = hasattr(item, 'can_edit') and item.can_edit(context['request']) if can_edit: modify_url_value = modify_url delete_url = getattr(item, "DELETE_URL", False) @@ -81,8 +77,7 @@ def window_file_nav(context, item, window_id, previous=None, nxt=None): revert_url = 'revert-file' add_operation = "" modify_url_value, delete_url = None, None - can_edit = hasattr(item, 'can_do') and \ - item.can_do(context['request'], 'change_file') + can_edit = hasattr(item, 'can_edit') and item.can_edit(context['request']) if can_edit: modify_url_value = modify_url delete_url = getattr(item, "DELETE_URL", False) diff --git a/ishtar_common/urls.py b/ishtar_common/urls.py index a205e3b01..8bb8dd356 100644 --- a/ishtar_common/urls.py +++ b/ishtar_common/urls.py @@ -26,9 +26,9 @@ from django.views.generic import TemplateView from .menus import Menu from ishtar_common import views, models, views_item -from ishtar_common.utils import check_rights, get_urls_for_model +from ishtar_common.utils import check_permissions, get_urls_for_model -# be careful: each check_rights must be relevant with ishtar_menu +# be careful: each check_permissions must be relevant with ishtar_menu # forms urlpatterns = [ @@ -69,72 +69,76 @@ urlpatterns = [ ), url( r"person_search/(?P<step>.+)?$", - check_rights(["add_person"])(views.person_search_wizard), + check_permissions(["ishtar_common.add_person"])(views.person_search_wizard), name="person_search", ), url( r"person_creation/(?P<step>.+)?$", - check_rights(["add_person"])(views.person_creation_wizard), + check_permissions(["ishtar_common.add_person"])(views.person_creation_wizard), name="person_creation", ), url( r"person_modification/(?P<step>.+)?$", - check_rights(["change_person", "change_own_person"])( - views.person_modification_wizard - ), + check_permissions( + ["ishtar_common.change_person", "ishtar_common.change_own_person"] + )(views.person_modification_wizard), name="person_modification", ), url(r"person_modify/(?P<pk>.+)/$", views.person_modify, name="person_modify"), url( r"person_deletion/(?P<step>.+)?$", - check_rights(["change_person", "change_own_person"])( - views.person_deletion_wizard - ), + check_permissions( + ["ishtar_common.change_person", "ishtar_common.change_own_person"] + )(views.person_deletion_wizard), name="person_deletion", ), url(r"person_delete/(?P<pk>.+)/$", views.person_delete, name="person_delete"), url( r"^person-edit/$", - check_rights(["add_person"])(views.PersonCreate.as_view()), + check_permissions(["ishtar_common.add_person"])(views.PersonCreate.as_view()), name="person_create", ), url( r"^person-edit/(?P<pk>\d+)$", - check_rights(["change_person", "change_own_person"])( - views.PersonEdit.as_view() - ), + check_permissions( + ["ishtar_common.change_person", "ishtar_common.change_own_person"] + )(views.PersonEdit.as_view()), name="person_edit", ), url( r"^person-qa-bulk-update/(?P<pks>[0-9-]+)?/$", - check_rights(["change_person", "change_own_person"])( - views.QAPersonForm.as_view() - ), + check_permissions( + ["ishtar_common.change_person", "ishtar_common.change_own_person"] + )(views.QAPersonForm.as_view()), name="person-qa-bulk-update", ), url( r"^person-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$", - check_rights(["change_person", "change_own_person"])( - views.QAPersonForm.as_view() - ), + check_permissions( + ["ishtar_common.change_person", "ishtar_common.change_own_person"] + )(views.QAPersonForm.as_view()), name="person-qa-bulk-update-confirm", kwargs={"confirm": True}, ), url( r"organization_search/(?P<step>.+)?$", - check_rights(["add_organization"])(views.organization_search_wizard), + check_permissions( + ["ishtar_common.add_organization"] + )(views.organization_search_wizard), name="organization_search", ), url( r"organization_creation/(?P<step>.+)?$", - check_rights(["add_organization"])(views.organization_creation_wizard), + check_permissions( + ["ishtar_common.add_organization"] + )(views.organization_creation_wizard), name="organization_creation", ), url( r"organization_modification/(?P<step>.+)?$", - check_rights(["change_organization", "change_own_organization"])( - views.organization_modification_wizard - ), + check_permissions( + ["ishtar_common.change_organization", "ishtar_common.change_own_organization"] + )(views.organization_modification_wizard), name="organization_modification", ), url( @@ -144,9 +148,9 @@ urlpatterns = [ ), url( r"organization_deletion/(?P<step>.+)?$", - check_rights(["change_organization", "change_own_organization"])( - views.organization_deletion_wizard - ), + check_permissions( + ["ishtar_common.change_organization", "ishtar_common.change_own_organization"] + )(views.organization_deletion_wizard), name="organization_deletion", ), url( @@ -156,47 +160,54 @@ urlpatterns = [ ), url( r"organization-edit/$", - check_rights(["add_organization"])(views.OrganizationCreate.as_view()), + check_permissions( + ["ishtar_common.add_organization"] + )(views.OrganizationCreate.as_view()), name="organization_create", ), url( r"organization-edit/(?P<pk>\d+)$", - check_rights(["change_organization", "change_own_organization"])( - views.OrganizationEdit.as_view() - ), + check_permissions( + ["ishtar_common.change_organization", + "ishtar_common.change_own_organization"] + )(views.OrganizationEdit.as_view()), name="organization_edit", ), url( r"organization-person-edit/$", - check_rights(["add_organization"])(views.OrganizationPersonCreate.as_view()), + check_permissions( + ["ishtar_common.add_organization"] + )(views.OrganizationPersonCreate.as_view()), name="organization_person_create", ), url( r"organization-person-edit/(?P<pk>\d+)$", - check_rights(["change_organization", "change_own_organization"])( - views.OrganizationPersonEdit.as_view() - ), + check_permissions( + ["ishtar_common.change_organization", "ishtar_common.change_own_organization"] + )(views.OrganizationPersonEdit.as_view()), name="organization_person_edit", ), url( r"^organization-qa-bulk-update/(?P<pks>[0-9-]+)?/$", - check_rights(["change_organization", "change_own_organization"])( - views.QAOrganizationForm.as_view() - ), + check_permissions( + ["ishtar_common.change_organization", "ishtar_common.change_own_organization"] + )(views.QAOrganizationForm.as_view()), name="organization-qa-bulk-update", ), url( r"^organization-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$", - check_rights(["change_organization", "change_own_organization"])( - views.QAOrganizationForm.as_view() - ), + check_permissions( + ["ishtar_common.change_organization", "ishtar_common.change_own_organization"] + )(views.QAOrganizationForm.as_view()), name="organization-qa-bulk-update-confirm", kwargs={"confirm": True}, ), url(r"get-ishtaruser/(?P<type>.+)?$", views.get_ishtaruser, name="get-ishtaruser"), url( r"account_management/(?P<step>.+)?$", - check_rights(["add_ishtaruser"])(views.account_management_wizard), + check_permissions( + ["ishtar_common.add_ishtaruser"] + )(views.account_management_wizard), name="account_management", ), url( @@ -206,67 +217,97 @@ urlpatterns = [ ), url( r"account_deletion/(?P<step>.+)?$", - check_rights(["add_ishtaruser"])(views.account_deletion_wizard), + check_permissions( + ["ishtar_common.add_ishtaruser"] + )(views.account_deletion_wizard), name="account_deletion", ), url( r"^import-new/$", - check_rights(["add_import", "add_own_import"])(views.NewImportView.as_view()), + check_permissions( + ["ishtar_common.add_import", "ishtar_common.add_own_import"] + )(views.NewImportView.as_view()), name="new_import", ), url( r"^import-edit/(?P<pk>[0-9]+)/$", - check_rights(["change_import", "change_own_import"])(views.EditImportView.as_view()), + check_permissions( + ["ishtar_common.change_import", "ishtar_common.change_own_import"] + )(views.EditImportView.as_view()), name="edit_import", ), url( r"^import-new-gis/$", - check_rights(["add_import", "add_own_import"])(views.NewImportGISView.as_view()), + check_permissions( + ["ishtar_common.add_import", "ishtar_common.add_own_import"] + )(views.NewImportGISView.as_view()), name="new_import_gis", ), url( r"^import-new-group/$", - check_rights(["add_import", "add_own_import"])(views.NewImportGroupView.as_view()), + check_permissions( + ["ishtar_common.add_import", "ishtar_common.add_own_import"] + )(views.NewImportGroupView.as_view()), name="new_import_group", ), url( r"^import-list/$", - check_rights(["view_import", "change_import", "change_own_import"])(views.ImportListView.as_view()), + check_permissions( + ["ishtar_common.view_import", "ishtar_common.change_import", + "ishtar_common.change_own_import"] + )(views.ImportListView.as_view()), name="current_imports", ), url( r"^import-list-table/$", - check_rights(["view_import", "change_import", "change_own_import"])(views.ImportListTableView.as_view()), + check_permissions( + ["ishtar_common.view_import", "ishtar_common.change_import", + "ishtar_common.change_own_import"] + )(views.ImportListTableView.as_view()), name="current_imports_table", ), url( r"^import-get-status/$", - check_rights(["view_import", "change_import", "change_own_import"])(views.import_get_status), - name="import_get_status", + check_permissions( + ["ishtar_common.view_import", "ishtar_common.change_import", + "ishtar_common.change_own_import"] + )(views.import_get_status), + name="import_get_status", ), url( r"^import-list-old/$", - check_rights(["view_import", "change_import", "change_own_import"])(views.ImportOldListView.as_view()), + check_permissions( + ["ishtar_common.view_import", "ishtar_common.change_import", + "ishtar_common.change_own_import"] + )(views.ImportOldListView.as_view()), name="old_imports", ), url( r"^import-delete/(?P<pk>[0-9]+)/$", - check_rights(["delete_import", "delete_own_import"])(views.ImportDeleteView.as_view()), + check_permissions( + ["ishtar_common.delete_import", "ishtar_common.delete_own_import"] + )(views.ImportDeleteView.as_view()), name="import_delete", ), url( r"^import-group-delete/(?P<pk>[0-9]+)/$", - check_rights(["delete_import", "delete_own_import"])(views.ImportGroupDeleteView.as_view()), + check_permissions( + ["ishtar_common.delete_import", "ishtar_common.delete_own_import"] + )(views.ImportGroupDeleteView.as_view()), name="import_group_delete", ), url( r"^import-link-unmatched/(?P<pk>[0-9]+)/$", - check_rights(["change_import", "change_own_import"])(views.ImportMatchView.as_view()), + check_permissions( + ["ishtar_common.change_import", "ishtar_common.change_own_import"] + )(views.ImportMatchView.as_view()), name="import_link_unmatched", ), url( r"^import-csv-view/(?P<target>source|result|match|error)/(?P<group>group\-)?(?P<pk>[0-9]+)/$", - check_rights(["view_import", "view_own_import"])(views.ImportCSVView.as_view()), + check_permissions( + ["ishtar_common.view_import", "ishtar_common.view_own_import"] + )(views.ImportCSVView.as_view()), name="import_display_csv", ), url( @@ -282,12 +323,16 @@ urlpatterns = [ ), url( r"^import-pre-form/(?P<import_id>[0-9]+)/$", - check_rights(["change_import", "change_own_import"])(views.ImportPreFormView.as_view()), + check_permissions( + ["ishtar_common.change_import", "ishtar_common.change_own_import"] + )(views.ImportPreFormView.as_view()), name="import_pre_import_form", ), url( r"^import-ignore-line/(?P<line_id>[0-9]+)/$", - check_rights(["change_import", "change_own_import"])(views.line_error), + check_permissions( + ["ishtar_common.change_import", "ishtar_common.change_own_import"] + )(views.line_error), name="import_ignore_line", ), url(r"^profile(?:/(?P<pk>[0-9]+))?/$", views.ProfileEdit.as_view(), name="profile"), @@ -417,9 +462,10 @@ urlpatterns += [ ), url( r"^biographicalnote-qa-edit/(?P<pks>[0-9-]+)?/$", - check_rights(["change_biographicalnote", "change_own_biographicalnote"])( - views.QABiographicalNoteForm.as_view() - ), + check_permissions( + ["ishtar_common.change_biographicalnote", + "ishtar_common.change_own_biographicalnote"] + )(views.QABiographicalNoteForm.as_view()), name="biographicalnote-qa-edit", ), url( @@ -551,44 +597,44 @@ urlpatterns += [ ), url( r"document/search/(?P<step>.+)?$", - check_rights(["view_document", "view_own_document"])( - views.document_search_wizard - ), + check_permissions( + ["ishtar_common.view_document", "ishtar_common.view_own_document"] + )(views.document_search_wizard), name="search-document", ), url( r"document/search/(?P<step>.+)?$", - check_rights(["view_document", "view_own_document"])( - views.document_search_wizard - ), + check_permissions( + ["ishtar_common.view_document", "ishtar_common.view_own_document"] + )(views.document_search_wizard), name="document_search", ), url( r"document/create/$", - check_rights(["add_document", "add_own_document"])( - views.DocumentCreateView.as_view() - ), + check_permissions( + ["ishtar_common.add_document", "ishtar_common.add_own_document"] + )(views.DocumentCreateView.as_view()), name="create-document", ), url( r"document/edit/$", - check_rights(["change_document", "change_own_document"])( - views.DocumentSelectView.as_view() - ), + check_permissions( + ["ishtar_common.change_document", "ishtar_common.change_own_document"] + )(views.DocumentSelectView.as_view()), name="edit-document", ), url( r"document/edit/(?P<pk>.+)/$", - check_rights(["change_document", "change_own_document"])( - views.DocumentEditView.as_view() - ), + check_permissions( + ["ishtar_common.change_document", "ishtar_common.change_own_document"] + )(views.DocumentEditView.as_view()), name="edit-document", ), url( r"document/delete/(?P<step>.+)?$", - check_rights(["change_document", "change_own_document"])( - views.document_deletion_wizard - ), + check_permissions( + ["ishtar_common.change_document", "ishtar_common.change_own_document"] + )(views.document_deletion_wizard), name="document_deletion", ), url( @@ -603,31 +649,31 @@ urlpatterns += [ ), url( r"^document-qa-bulk-update/(?P<pks>[0-9-]+)?/$", - check_rights(["change_document", "change_own_document"])( - views.QADocumentForm.as_view() - ), + check_permissions( + ["ishtar_common.change_document", "ishtar_common.change_own_document"] + )(views.QADocumentForm.as_view()), name="document-qa-bulk-update", ), url( r"^document-qa-bulk-update/(?P<pks>[0-9-]+)?/confirm/$", - check_rights(["change_document", "change_own_document"])( - views.QADocumentForm.as_view() - ), + check_permissions( + ["ishtar_common.change_document", "ishtar_common.change_own_document"] + )(views.QADocumentForm.as_view()), name="document-qa-bulk-update-confirm", kwargs={"confirm": True}, ), url( r"^document-qa-duplicate/(?P<pks>[0-9-]+)?/$", - check_rights(["change_document", "change_own_document"])( - views.QADocumentDuplicateFormView.as_view() - ), + check_permissions( + ["ishtar_common.change_document", "ishtar_common.change_own_document"] + )(views.QADocumentDuplicateFormView.as_view()), name="document-qa-duplicate", ), url( r"^document-qa-packaging/(?P<pks>[0-9-]+)?/$", - check_rights(["change_document", "change_own_document"])( - views.QADocumentPackagingFormView.as_view() - ), + check_permissions( + ["ishtar_common.change_document", "ishtar_common.change_own_document"] + )(views.QADocumentPackagingFormView.as_view()), name="document-qa-packaging", ), url( @@ -642,30 +688,32 @@ urlpatterns += [ ), url( r"geo/create/(?P<app_source>[-\w]+)/(?P<model_source>[-\w]+)/(?P<source_pk>\d+)/$", - check_rights(["add_geovectordata", "add_own_geovectordata"])( - views.GeoPreCreateView.as_view() - ), + check_permissions( + ["ishtar_common.add_geovectordata", "ishtar_common.add_own_geovectordata"] + )(views.GeoPreCreateView.as_view()), name="create-pre-geo", ), url( r"geo/create/(?P<app_source>[-\w]+)/(?P<model_source>[-\w]+)/(?P<source_pk>\d+)/(?P<geom_type>[-\w]+)/$", - check_rights(["add_geovectordata", "add_own_geovectordata"])( - views.GeoCreateView.as_view() - ), + check_permissions( + ["ishtar_common.add_geovectordata", "ishtar_common.add_own_geovectordata"] + )(views.GeoCreateView.as_view()), name="create-geo", ), url( r"geo/edit/(?P<pk>\d+)/$", - check_rights(["change_geovectordata", "change_own_geovectordata"])( - views.GeoEditView.as_view() - ), + check_permissions( + ["ishtar_common.change_geovectordata", + "ishtar_common.change_own_geovectordata"] + )(views.GeoEditView.as_view()), name="edit-geo", ), url( r"geo/delete/(?P<pk>\d+)/$", - check_rights(["change_geovectordata", "change_own_geovectordata"])( - views.GeoDeleteView.as_view() - ), + check_permissions( + ["ishtar_common.change_geovectordata", + "ishtar_common.change_own_geovectordata"] + )(views.GeoDeleteView.as_view()), name="delete-geo", ), url( diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index 09e83714b..8de745874 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -21,8 +21,9 @@ from csv import QUOTE_ALL import datetime import feedparser from functools import wraps +from guardian.exceptions import WrongAppError from itertools import chain -from inspect import currentframe, getframeinfo +from inspect import currentframe import json import logging import hashlib @@ -225,24 +226,25 @@ def import_class(full_path_classname): return model -def check_rights(rights=None, redirect_url="/"): +def check_permissions(permissions=None, redirect_url="/"): """ Decorator that checks the rights to access the view. """ def decorator(view_func): def _wrapped_view(request, *args, **kwargs): - if not rights: + if not permissions: return view_func(request, *args, **kwargs) if hasattr(request.user, "ishtaruser"): - if request.user.ishtaruser.has_right("administrator", request.session): + ishtaruser = request.user.ishtaruser + if ishtaruser.has_permission("ishtaradmin"): kwargs["current_right"] = "administrator" return view_func(request, *args, **kwargs) - for right in rights: + for permission in permissions: # be careful to put the more permissive rights first # if granted it can allow more - if request.user.ishtaruser.has_right(right, request.session): - kwargs["current_right"] = right + if ishtaruser.has_permission(permission): + kwargs["current_right"] = permission return view_func(request, *args, **kwargs) put_session_message( request.session.session_key, @@ -256,17 +258,18 @@ def check_rights(rights=None, redirect_url="/"): return decorator -def check_rights_condition(rights): +def check_permissions_condition(permissions): """ To be used to check in wizard condition_dict """ def func(self): request = self.request - if request.user.ishtaruser.has_right("administrator", request.session): + ishtaruser = request.user.ishtaruser + if ishtaruser.has_permission("ishtaradmin"): return True - for right in rights: - if request.user.ishtaruser.has_right(right, request.session): + for permission in permissions: + if ishtaruser.has_permission(permission): return True return False @@ -297,7 +300,7 @@ def check_model_access_control(request, model, available_perms=None): ishtaruser = request.user.ishtaruser except request.user._meta.model.ishtaruser.RelatedObjectDoesNotExist: return False, True - if ishtaruser.has_right("administrator", session=request.session): + if ishtaruser.has_permission("ishtaradmin"): allowed = True own = False return allowed, own @@ -305,10 +308,10 @@ def check_model_access_control(request, model, available_perms=None): content_type__app_label=model._meta.app_label, content_type__model=model._meta.model_name ) - for perm in q.values_list("codename", flat=True): + for app_name, perm in q.values_list("content_type__app_label", "codename"): if perm not in available_perms: continue - if ishtaruser.person.has_right(perm, session=request.session): + if ishtaruser.has_permission(f"{app_name}.{perm}"): allowed = True if "_own_" not in perm: own = False @@ -343,48 +346,56 @@ class OwnPerms: return None # implement for each object def can_view(self, request): - if hasattr(self, "LONG_SLUG"): - perm = "view_" + self.LONG_SLUG - else: - perm = "view_" + self.SLUG + meta = self.__class__._meta + perm = f"{meta.app_label}.view_{meta.model_name}" return self.can_do(request, perm) def can_edit(self, request): if not getattr(request.user, "ishtaruser", None): return False ishtaruser = request.user.ishtaruser - slug = self.LONG_SLUG if hasattr(self, "LONG_SLUG") else self.SLUG - if ishtaruser.has_perm("change_" + slug, session=request.session): + meta = self.__class__._meta + perm = f"{meta.app_label}.change_{meta.model_name}" + if ishtaruser.has_permission(perm): return True - if not ishtaruser.has_perm("change_own_" + slug, session=request.session): + own_perm = f"{meta.app_label}.change_own_{meta.model_name}" + if not ishtaruser.has_permission(own_perm): return False return self.is_own(ishtaruser) - def can_do(self, request, action_name): + def can_do(self, request, permission): """ Check permission availability for the current object. :param request: request object - :param action_name: action name eg: "change_find" - "own" variation is - checked + :param permission: action name eg: "archaelogical_finds.change_find" - "own" + variation is checked :return: boolean """ if not getattr(request.user, "ishtaruser", None): return False - splited = action_name.split("_") - action_own_name = splited[0] + "_own_" + "_".join(splited[1:]) - user = request.user - if action_name == "view_findbasket": - action_own_name = "view_own_find" - action_name = "view_find" - return user.ishtaruser.has_right(action_name, request.session) or ( - user.ishtaruser.has_right(action_own_name, request.session) - and self.is_own(user.ishtaruser) - ) + + if "_findbasket" in permission: + permission = permission.replace("basket", "") + ishtaruser = request.user.ishtaruser + + if ishtaruser.has_permission(permission): + return True + app, perm = permission.split(".") + p = perm.split("_") + own = f"{app}.{p[0]}_own_{('_').join(p[1:])}" + try: + return ishtaruser.has_permission(own, self) + except WrongAppError: + # normaly occurs when, for instance, add doc permission is required + # for an item with document attached but the item is not a document. + # own permission is irrelevant: return False + return False def is_own(self, user, alt_query_own=None): """ Check if the current object is owned by the user """ + print("ishtar_common/utils.py - 370 - DELETE") IshtarUser = apps.get_model("ishtar_common", "IshtarUser") if isinstance(user, IshtarUser): ishtaruser = user @@ -406,6 +417,7 @@ class OwnPerms: """ Check if the user own some items """ + print("ishtar_common/utils.py - 392 - DELETE") IshtarUser = apps.get_model("ishtar_common", "IshtarUser") if isinstance(user, IshtarUser): ishtaruser = user @@ -1139,9 +1151,7 @@ def get_random_item_image_link(request): return "" ishtar_user = request.user.ishtaruser - if not ishtar_user.has_right( - "ishtar_common.view_document", session=request.session - ): + if not ishtar_user.has_permission("ishtar_common.view_document"): return "" q = ( @@ -1945,17 +1955,23 @@ def get_urls_for_model( """ Generate get and show url for a model """ + app_label = model._meta.app_label + model_name = model._meta.model_name urls = [ url( r"show-{}(?:/(?P<pk>.+))?/(?P<type>.+)?$".format(model.SLUG), - check_rights(["view_" + model.SLUG, "view_own_" + model.SLUG])( + check_permissions( + [f"{app_label}.view_{model_name}", + f"{app_label}.view_own_{model_name}"])( getattr(views, "show_" + model.SLUG) ), name="show-" + model.SLUG, ), url( r"^display-{}/(?P<pk>.+)/$".format(model.SLUG), - check_rights(["view_" + model.SLUG, "view_own_" + model.SLUG])( + check_permissions( + [f"{app_label}.view_{model_name}", + f"{app_label}.view_own_{model_name}"])( getattr(views, "display_" + model.SLUG) ), name="display-" + model.SLUG, @@ -1965,7 +1981,9 @@ def get_urls_for_model( urls += [ url( r"get-{}/own/(?P<type>.+)?$".format(model.SLUG), - check_rights(["view_" + model.SLUG, "view_own_" + model.SLUG])( + check_permissions( + [f"{app_label}.view_{model_name}", + f"{app_label}.view_own_{model_name}"])( getattr(views, "get_" + model.SLUG) ), name="get-own-" + model.SLUG, @@ -1976,7 +1994,9 @@ def get_urls_for_model( urls += [ url( r"get-{}/(?P<type>.+)?$".format(model.SLUG), - check_rights(["view_" + model.SLUG, "view_own_" + model.SLUG])( + check_permissions( + [f"{app_label}.view_{model_name}", + f"{app_label}.view_own_{model_name}"])( getattr(views, "get_" + model.SLUG) ), name="get-" + model.SLUG, @@ -1987,7 +2007,9 @@ def get_urls_for_model( urls += [ url( r"autocomplete-{}/$".format(model.SLUG), - check_rights(["view_" + model.SLUG, "view_own_" + model.SLUG])( + check_permissions( + [f"{app_label}.view_{model_name}", + f"{app_label}.view_own_{model_name}"])( getattr(views, "autocomplete_" + model.SLUG) ), name="autocomplete-" + model.SLUG, diff --git a/ishtar_common/views.py b/ishtar_common/views.py index 780a2253b..6c209a848 100644 --- a/ishtar_common/views.py +++ b/ishtar_common/views.py @@ -863,7 +863,10 @@ def autocomplete_person_permissive( def autocomplete_user(request): - if not request.user.has_perm("ishtar_common.view_person", models.Person): + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse("[]", content_type="text/plain") + if not ishtaruser.has_permission("ishtar_common.view_person"): return HttpResponse("[]", content_type="text/plain") q = request.GET.get("term") limit = request.GET.get("limit", 20) @@ -893,7 +896,10 @@ def autocomplete_user(request): def autocomplete_ishtaruser(request): - if not request.user.has_perm("ishtar_common.view_person", models.Person): + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse("[]", content_type="text/plain") + if not ishtaruser.has_permission("ishtar_common.view_person"): return HttpResponse("[]", content_type="text/plain") q = request.GET.get("term", "") limit = request.GET.get("limit", 20) @@ -917,12 +923,13 @@ def autocomplete_ishtaruser(request): def autocomplete_person( request, person_types=None, attached_to=None, is_ishtar_user=None, permissive=False ): - all_items = request.user.has_perm("ishtar_common.view_person", models.Person) + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse("[]", content_type="text/plain") + all_items = ishtaruser.has_permission("ishtar_common.view_person") own_items = False if not all_items: - own_items = request.user.has_perm( - "ishtar_common.view_own_person", models.Person - ) + own_items = ishtaruser.has_permission("ishtar_common.view_own_person") if not all_items and not own_items or not request.GET.get("term"): return HttpResponse("[]", content_type="text/plain") q = request.GET.get("term") @@ -966,12 +973,13 @@ def autocomplete_person( def autocomplete_import(request): - all_items = request.user.has_perm("ishtar_common.view_import", models.Import) + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse("[]", content_type="text/plain") + all_items = ishtaruser.has_permission("ishtar_common.view_import") own_items = False if not all_items: - own_items = request.user.has_perm( - "ishtar_common.view_own_import", models.Import - ) + own_items = ishtaruser.has_permission("ishtar_common.view_own_import") if not all_items and not own_items or not request.GET.get("term"): return HttpResponse("[]", content_type="text/plain") q = request.GET.get("term") @@ -982,7 +990,8 @@ def autocomplete_import(request): return HttpResponseBadRequest() query = Q() for q in q.split(" "): - query = query & (Q(name__unaccent__icontains=q) | Q(group__name__unaccent__icontains=q)) + query = query & (Q(name__unaccent__icontains=q) | + Q(group__name__unaccent__icontains=q)) if own_items: if not hasattr(request.user, "ishtaruser"): return HttpResponse(json.dumps([]), content_type="text/plain") @@ -1116,16 +1125,12 @@ def department_by_state(request, state_id=""): def autocomplete_organization(request, orga_type=None): + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse("[]", content_type="text/plain") if ( - not request.user.has_perm( - "ishtar_common.view_organization", models.Organization - ) - and not request.user.has_perm( - "ishtar_common.view_own_organization", models.Organization - ) - and not request.user.ishtaruser.has_right( - "person_search", session=request.session - ) + not ishtaruser.has_permission("ishtar_common.view_organization") + and not ishtaruser.has_permission("ishtar_common.view_own_organization") ): return HttpResponse("[]", content_type="text/plain") if not request.GET.get("term"): @@ -1149,9 +1154,13 @@ def autocomplete_organization(request, orga_type=None): def autocomplete_author(request): - if not request.user.has_perm( - "ishtar_common.view_author", models.Author - ) and not request.user.has_perm("ishtar_common.view_own_author", models.Author): + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse("[]", content_type="text/plain") + if not ishtaruser.has_permission( + "ishtar_common.view_author" + ) and not ishtaruser.has_permission( + "ishtar_common.view_own_author"): return HttpResponse("[]", content_type="text/plain") if not request.GET.get("term"): return HttpResponse("[]", content_type="text/plain") @@ -1172,7 +1181,10 @@ def autocomplete_author(request): def autocomplete_biographical_note(request): - if not request.user.has_perm("ishtar_common.view_person", models.Person): + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse("[]", content_type="text/plain") + if not ishtaruser.has_permission("ishtar_common.view_person"): return HttpResponse("[]", content_type="text/plain") q = request.GET.get("term", "") limit = request.GET.get("limit", 20) @@ -1637,18 +1649,20 @@ class NewImportView(BaseImportView, CreateView): class ImportPermissionMixin: - permission_full = "change_import" - permission_own = "change_own_import" + permission_full = "ishtar_common.change_import" + permission_own = "ishtar_common.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("/") + ishtaruser = user.ishtaruser 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): + if not ishtaruser.has_permission("ishtaradmin") and \ + not ishtaruser.has_permission(self.permission_full): + if not ishtaruser.has_permission(self.permission_own): return redirect("/") q = q.filter(Q(importer_type__users__pk=user.ishtaruser.pk)) if not q.count(): @@ -1711,7 +1725,8 @@ 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): +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 @@ -1741,21 +1756,38 @@ class ImportListView(IshtarMixin, LoginRequiredMixin, ListView): user = self.request.user if not user.pk or not user.ishtaruser: raise Http404() - q1 = self._queryset_filter(self.model.query_can_access(user, ["view_import", "change_import"])) + q1 = self._queryset_filter( + self.model.query_can_access( + user, + ["ishtar_common.view_import", "ishtar_common.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, ["view_import", "change_import"])) - q2 = q2.order_by("-end_date", "-creation_date", "-pk") - 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 + q2 = self._queryset_filter( + models.ImportGroup.query_can_access( + user, + ["ishtar_common.view_import", "ishtar_common.change_import"] + ) ) + q2 = q2.order_by("-end_date", "-creation_date", "-pk") + 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) 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 + 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 ) - imprt.action_list = imprt.get_actions(can_edit=can_edit, can_delete=can_delete) imports.append(imprt) self.imports_len = len(imports) self.current_page = 0 @@ -1768,9 +1800,8 @@ class ImportListView(IshtarMixin, LoginRequiredMixin, ListView): 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 - ) + can_edit_all, can_delete_all, can_edit_own, can_delete_own = \ + models.Import.get_permissions_for_actions(request.user) owns = {} for field in request.POST: if not field.startswith("import-action-") or not request.POST[field]: @@ -1785,7 +1816,8 @@ class ImportListView(IshtarMixin, LoginRequiredMixin, ListView): except (models.Import.DoesNotExist, ValueError): 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 + request.user, imprt, owns, can_edit_all, + can_delete_all, can_edit_own, can_delete_own ) action = request.POST[field] if can_delete and action == "D": @@ -1843,15 +1875,28 @@ class ImportListView(IshtarMixin, LoginRequiredMixin, ListView): if self.imports_len > self.page_step and self.pagination: dct["current_page"] = self.current_page dct["page_range"] = (n + 1 for n in range(self.page_number)) - 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') + add_import_perm = self.request.user.ishtaruser.has_permission( + "ishtar_common.add_import" + ) + 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) + ishtaruser = self.request.user.ishtaruser + if not add_import_perm and ishtaruser.has_permission( + "ishtar_common.add_own_import"): + 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: @@ -2313,11 +2358,11 @@ def import_get_status(request, current_right=None): "number_of_line": item.number_of_line, "progress_percent": item.progress_percent, }) - can_edit_all, can_delete_all, can_edit_own, can_delete_own = models.Import.get_permissions_for_actions( - request.user, request.session - ) + 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 + request.user, item, {}, can_edit_all, + can_delete_all, can_edit_own, can_delete_own ) item_dct["actions"] = [ (key, str(lbl)) @@ -2404,11 +2449,11 @@ class ImportCSVView(ImportPermissionMixin, IshtarMixin, LoginRequiredMixin, Temp TITLES = { "source": ("fa fa-file-text-o", _("Source")), "error": ("text-danger fa fa-exclamation-triangle", _("Error")), - "result": ("fa fa-th", _("Result")) , + "result": ("fa fa-th", _("Result")), "match": ("fa fa-arrows-h", _("Match")), } - permission_full = "view_import" - permission_own = "view_own_import" + permission_full = "ishtar_common.view_import" + permission_own = "ishtar_common.view_own_import" def get(self, request, *args, **kwargs): user = self.request.user @@ -2416,7 +2461,9 @@ class ImportCSVView(ImportPermissionMixin, IshtarMixin, LoginRequiredMixin, Temp raise Http404() self.is_group = kwargs.get("group", None) model = models.ImportGroup if self.is_group else models.Import - q = model.query_can_access(self.request.user, perm=self.permission_full).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] @@ -2491,7 +2538,9 @@ def line_error(request, line_id, current_right=None): if not q.count(): return line = q.all()[0] - q = models.Import.query_can_access(request.user, perm="change_import").filter(pk=line.import_item_id) + q = models.Import.query_can_access( + request.user, perm="ishtar_common.change_import" + ).filter(pk=line.import_item_id) if not q.count(): raise Http404() line.ignored = not line.ignored @@ -2853,7 +2902,12 @@ def get_bookmark(request, pk): def gen_generate_doc(model): def func(request, pk, template_pk=None): - if not request.user.has_perm("view_" + model.SLUG, model): + ishtaruser = getattr(request.user, "ishtaruser", None) + if not ishtaruser: + return HttpResponse(content_type="text/plain") + meta = model._meta + perm = f"{meta.app_label}.view_{meta.model_name}" + if not ishtaruser.has_permission(perm): return HttpResponse(content_type="text/plain") try: item = model.objects.get(pk=pk) @@ -3075,10 +3129,10 @@ class QAItemForm(IshtarMixin, LoginRequiredMixin, FormView): quick_action = self.get_quick_action() if not quick_action: raise Http404() - if not quick_action.is_available(user=request.user, session=request.session): + if not quick_action.is_available(user=request.user): for item in self.items: if not quick_action.is_available( - user=request.user, session=request.session, obj=item + user=request.user, obj=item ): raise Http404() @@ -3431,13 +3485,15 @@ class GeoCreateView(GeoFormMixin, CreateView): obj = model.objects.get(pk=self.kwargs.get("source_pk")) except model.DoesNotExist: raise Http404() - if not ishtaruser.has_perm("add_geovectordata"): # -> add_own_geovectordata + if not ishtaruser.has_permission( + "ishtar_common.add_geovectordata"): + # -> add_own_geovectordata # check permission to view attached item - if not getattr(model, "SLUG", None): - raise Http404() - if not ishtaruser.has_right(f"view_{model.SLUG}") \ - or not ishtaruser.has_right(f"view_own_{model.SLUG}") \ - or not obj.is_own(ishtaruser): + meta = model._meta + perm = f"{meta.app_label}.view_{meta.model_name}" + perm_own = f"{meta.app_label}.view_own_{meta.model_name}" + if not ishtaruser.has_permission(perm) \ + and not ishtaruser.has_permission(perm_own, obj=obj): # check permission to view own attached item raise Http404() kwargs["main_items_fields"] = {} diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py index 48d8e229b..a88cb48b3 100644 --- a/ishtar_common/views_item.py +++ b/ishtar_common/views_item.py @@ -222,11 +222,9 @@ def check_permission(request, action_slug, obj_id=None): return True if obj_id: return main_menu.items[action_slug].is_available( - request.user, obj_id, session=request.session + request.user, obj_id ) - return main_menu.items[action_slug].can_be_available( - request.user, session=request.session - ) + return main_menu.items[action_slug].can_be_available(request.user) def new_qa_item( diff --git a/ishtar_common/wizards.py b/ishtar_common/wizards.py index 43e84fbcb..e41c4c811 100644 --- a/ishtar_common/wizards.py +++ b/ishtar_common/wizards.py @@ -55,25 +55,6 @@ from ishtar_common.utils import get_all_field_names, get_person_gdpr_log, MultiV logger = logging.getLogger(__name__) -# buggy and unecessary at least for the moment... -""" -def _check_right(step, condition=True): - '''Return a method to check the right for a specific step''' - def check_right(self): - cond = condition - if callable(condition): - cond = condition(self) - if not cond: - return False - return True - # TODO: to be check - if not hasattr(self.request.user, 'ishtaruser'): - return False - return self.request.user.ishtaruser.has_right( - ('administrator', step), session=self.request.session) - return check_right -""" - def filter_no_fields_form(form, other_check=None): def func(self): |