diff options
Diffstat (limited to 'ishtar_common')
-rw-r--r-- | ishtar_common/admin.py | 21 | ||||
-rw-r--r-- | ishtar_common/models.py | 36 | ||||
-rw-r--r-- | ishtar_common/models_common.py | 70 | ||||
-rw-r--r-- | ishtar_common/utils.py | 83 |
4 files changed, 148 insertions, 62 deletions
diff --git a/ishtar_common/admin.py b/ishtar_common/admin.py index 465a9f152..91a036ad9 100644 --- a/ishtar_common/admin.py +++ b/ishtar_common/admin.py @@ -795,20 +795,33 @@ class PermissionRequestAdminForm(forms.ModelForm): klass = ct.model_class() if not klass: continue - if getattr(klass, "SHOW_URL", None) and hasattr(klass, "history_creator_id"): + if (getattr(klass, "SHOW_URL", None) and + hasattr(klass, "history_creator_id")) or \ + ct.model in ("geovectordata", "document"): choices.append((ct.pk, ct.name)) self.fields["model"].choices = [("", "-" * 9)] + list( - sorted(choices, key=lambda x: x[1]) + sorted(choices, key=lambda x: x[1]) ) def clean(self): + super().clean() + model = self.cleaned_data["model"] + include_upstream_items = self.cleaned_data.get("include_upstream_items", None) + if include_upstream_items and model.model in ("organization", "person", "file", + "warehouse"): + raise forms.ValidationError( + _("This model do have attached upstream items. Uncheck " + "\"Include upstream items\" field.") + ) limit_to_attached_areas = self.cleaned_data.get("limit_to_attached_areas", "") if not limit_to_attached_areas: return self.cleaned_data - model = self.cleaned_data["model"] if model.model not in ("operation", "contextrecord", "find", "archaeologicalsite", "file"): - raise forms.ValidationError(_("This model do not accept area limitation.")) + raise forms.ValidationError( + _("This model do not accept area limitation. Uncheck " + "\"Limit request to attached areas\" field.") + ) return self.cleaned_data diff --git a/ishtar_common/models.py b/ishtar_common/models.py index 045bab1cc..eb9e73150 100644 --- a/ishtar_common/models.py +++ b/ishtar_common/models.py @@ -3607,12 +3607,14 @@ class UserProfile(models.Model): item_ids = [] model_class = content_type.model_class() if permission_request.include_associated_items: - item_ids += model_class.objects.filter( - ishtar_users__pk=ishtar_user.pk - ).values_list("pk", flat=True) - item_ids += model_class.objects.filter( - history_creator_id=ishtar_user.pk - ).values_list("pk", flat=True) + if hasattr(model_class, "ishtar_users"): + item_ids += model_class.objects.filter( + ishtar_users__pk=ishtar_user.pk + ).values_list("pk", flat=True) + if hasattr(model_class, "history_creator_id"): + item_ids += model_class.objects.filter( + history_creator_id=ishtar_user.pk + ).values_list("pk", flat=True) if content_type.model == "find" and \ permission_type in ("view", "change"): Find = apps.get_model("archaeological_finds", "Find") @@ -4510,6 +4512,28 @@ class Document( "towns", "areas", ] + UPPER_PERMISSIONS = [ + (("archaeological_files", "file"), + "files__pk"), + (("archaeological_operations", "operation"), + "operations__pk"), + (("archaeological_operations", "archaeologicalsite"), + "sites__pk"), + (("archaeological_operations", "administrativeact"), + "administrativeacts__pk"), + (("archaeological_context_records", "contextrecord"), + "context_records__pk"), + (("archaeological_finds", "find"), + "finds__pk"), + (("archaeological_finds", "treatmentfile"), + "treatment_files__pk"), + (("archaeological_finds", "treatment"), + "treatments__pk"), + (("archaeological_warehouse", "warehouse"), + "warehouses__pk"), + (("archaeological_warehouse", "container"), + "containers__pk"), + ] SLUG = "document" LINK_SPLIT = "<||>" diff --git a/ishtar_common/models_common.py b/ishtar_common/models_common.py index dc48fa9e5..aa52d82c7 100644 --- a/ishtar_common/models_common.py +++ b/ishtar_common/models_common.py @@ -22,7 +22,7 @@ from unidecode import unidecode from django import forms from django.apps import apps from django.conf import settings -from django.contrib.auth.models import Permission, User +from django.contrib.auth.models import User from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.fields import GenericForeignKey from django.contrib.gis.db import models @@ -60,8 +60,6 @@ from simple_history.signals import ( pre_create_historical_record, ) -from guardian.models import UserObjectPermission - from ishtar_common.data_importer import post_importer_action, ImporterError from ishtar_common.model_managers import TypeManager from ishtar_common.model_merging import merge_model_objects @@ -1528,7 +1526,7 @@ class BaseHistorizedItem( FullSearch, Imported, JsonData, - FixAssociated, + FixAssociated ): """ Historized item with external ID management. @@ -1541,7 +1539,6 @@ class BaseHistorizedItem( EXTERNAL_ID_KEY = "" EXTERNAL_ID_DEPENDENCIES = [] HISTORICAL_M2M = [] - UPPER_PERMISSIONS = [] history_modifier = models.ForeignKey( User, @@ -1614,52 +1611,6 @@ class BaseHistorizedItem( def get_verbose_name(cls): return cls._meta.verbose_name - @classmethod - def get_ids_from_upper_permissions(cls, user_id, base_permissions): - if not cls.UPPER_PERMISSIONS: - return [] - ProfileType = apps.get_model("ishtar_common", "ProfileType") - item_ids = [] - for model, attr in cls.UPPER_PERMISSIONS: - if isinstance(model, tuple): - app_label, model_name = model - model = apps.get_model(app_label, model_name) - permissions = list(set([ - "_".join(permission.codename.split("_")[:-1]) - + f"_{model._meta.model_name}" - for permission in base_permissions - ])) - q = ProfileType.objects.filter( - user_profiles__person__ishtaruser=user_id, - groups__permissions__codename__in=permissions - ) - lst = [] - if not q.count(): - # no permissions associated for upstream model get direct attachement - lst = model.objects.filter( - ishtar_users__pk=user_id - ).values_list("pk", flat=True) - else: - perms = [] - for codename in permissions: - perms += [ - perm - for perm in Permission.objects.filter( - codename=codename).all() - ] - lst = [] - for permission in perms: - lst += list( - UserObjectPermission.objects.filter( - permission=permission, - user_id=user_id - ).values_list("object_pk", flat=True) - ) - item_ids += cls.objects.filter( - **{f"{attr}__in": lst} - ).values_list("pk", flat=True) - return list(set(item_ids)) - def is_locked(self, user=None): if not user: return self.locked @@ -2317,6 +2268,21 @@ class GeoVectorData(Imported, OwnPerms): "related_items_archaeological_warehouse_container", ] + UPPER_PERMISSIONS = [ + (("archaeological_operations", "operation"), + "related_items_archaeological_operations_operation__pk"), + (("archaeological_operations", "archaeologicalsite"), + "related_items_archaeological_operations_archaeologicalsite__pk"), + (("archaeological_context_records", "contextrecord"), + "related_items_archaeological_context_records_contextrecord__pk"), + (("archaeological_finds", "find"), + "related_items_archaeological_finds_basefind__find__pk"), + (("archaeological_warehouse", "warehouse"), + "related_items_archaeological_warehouse_warehouse__pk"), + (("archaeological_warehouse", "container"), + "related_items_archaeological_warehouse_container__pk"), + ] + buffer = models.FloatField( _("Buffer"), blank=True, null=True ) @@ -3110,7 +3076,7 @@ class PermissionRequest(models.Model): help_text=_("All items associated items match the request") ) include_upstream_items = models.BooleanField( - _("Include upstream items"), default=True, + _("Include upstream items"), default=False, help_text=_( "All items associated by upstream link math the request. " "For instance, match is done for all finds associated with own " diff --git a/ishtar_common/utils.py b/ishtar_common/utils.py index bbed4e8a4..5536bc84b 100644 --- a/ishtar_common/utils.py +++ b/ishtar_common/utils.py @@ -414,6 +414,89 @@ class OwnPerms: """ Manage special permissions for object's owner """ + UPPER_PERMISSIONS = [] + + @classmethod + def _has_permission_query_for_upper_permissions( + cls, base_permissions, model, user_id): + ProfileType = apps.get_model("ishtar_common", "ProfileType") + permissions = list(set([ + "_".join(permission.codename.split("_")[:-1]) + + f"_{model._meta.model_name}" + for permission in base_permissions + ])) + q = ProfileType.objects.filter( + user_profiles__person__ishtaruser=user_id, + groups__permissions__codename__in=permissions + ) + return q, permissions + + @classmethod + def get_ids_from_upper_permissions(cls, user_id, base_permissions): + if not cls.UPPER_PERMISSIONS: + return [] + UserObjectPermission = apps.get_model("guardian", "UserObjectPermission") + item_ids = [] + full_permissions = [] + for base_permission in base_permissions: + if "_own_" not in base_permission.codename: + full_permissions.append(base_permission) + continue + codename = base_permission.codename.replace("_own", "") + try: + full_permissions.append( + Permission.objects.get( + codename=codename, + content_type=base_permission.content_type + ) + ) + except Permission.DoesNotExist: + continue + for model, attr in cls.UPPER_PERMISSIONS: + if isinstance(model, tuple): + app_label, model_name = model + model = apps.get_model(app_label, model_name) + + # check if has full permission + q_full, __ = cls._has_permission_query_for_upper_permissions( + full_permissions, model, user_id + ) + has_full_permission = bool(q_full.count()) + if has_full_permission: + item_ids += cls.objects.filter( + **{f"{attr}__isnull": False} + ).values_list("pk", flat=True) + continue + + q, permissions = cls._has_permission_query_for_upper_permissions( + base_permissions, model, user_id + ) + lst = [] + if not q.count(): + # no permissions associated for upstream model get direct attachement + lst = model.objects.filter( + ishtar_users__pk=user_id + ).values_list("pk", flat=True) + else: + perms = [] + for codename in permissions: + perms += [ + perm + for perm in Permission.objects.filter( + codename=codename).all() + ] + lst = [] + for permission in perms: + lst += list( + UserObjectPermission.objects.filter( + permission=permission, + user_id=user_id + ).values_list("object_pk", flat=True) + ) + item_ids += cls.objects.filter( + **{f"{attr}__in": lst} + ).values_list("pk", flat=True) + return list(set(item_ids)) @classmethod def get_query_owns(cls, ishtaruser): |