diff options
Diffstat (limited to 'ishtar_common/views_item.py')
-rw-r--r-- | ishtar_common/views_item.py | 135 |
1 files changed, 69 insertions, 66 deletions
diff --git a/ishtar_common/views_item.py b/ishtar_common/views_item.py index 23752c8a9..b5c63cc65 100644 --- a/ishtar_common/views_item.py +++ b/ishtar_common/views_item.py @@ -13,6 +13,7 @@ import requests import subprocess # nosec from tempfile import NamedTemporaryFile +from django.apps import apps from django.conf import settings from django.contrib.auth.models import Permission from django.contrib.contenttypes.models import ContentType @@ -46,6 +47,7 @@ from django.utils.translation import ( deactivate, pgettext_lazy, ) +from guardian.models import UserObjectPermission from tidylib import tidy_document as tidy from unidecode import unidecode from weasyprint import HTML, CSS @@ -54,50 +56,24 @@ from weasyprint.fonts import FontConfiguration from bootstrap_datepicker.widgets import DateField from ishtar_common.utils import ( + API_MAIN_MODELS, check_model_access_control, CSV_OPTIONS, + GENERAL_TYPE_PREFIX, get_all_field_names, - Round, + get_current_item_keys_dict, + get_current_profile, + HistoryError, PRIVATE_FIELDS, + SearchAltName, + Round, ) -from ishtar_common.models import get_current_profile, GeneralType, SearchAltName -from ishtar_common.models_common import HistoryError from .menus import Menu -from . import models, models_rest -from archaeological_files.models import File -from archaeological_operations.models import ( - Operation, - ArchaeologicalSite, - AdministrativeAct, -) -from archaeological_context_records.models import ContextRecord -from archaeological_finds.models import Find, FindBasket, Treatment, TreatmentFile -from archaeological_warehouse.models import Warehouse, Container - logger = logging.getLogger(__name__) ENCODING = settings.ENCODING or "utf-8" -CURRENT_ITEM_KEYS = ( - ("file", File), - ("operation", Operation), - ("site", ArchaeologicalSite), - ("contextrecord", ContextRecord), - ("warehouse", Warehouse), - ("container", Container), - ("find", Find), - ("findbasket", FindBasket), - ("treatmentfile", TreatmentFile), - ("treatment", Treatment), - ("administrativeact", AdministrativeAct), - ("administrativeactop", AdministrativeAct), - ("administrativeactfile", AdministrativeAct), - ("administrativeacttreatment", AdministrativeAct), - ("administrativeacttreatmentfile", AdministrativeAct), -) -CURRENT_ITEM_KEYS_DICT = dict(CURRENT_ITEM_KEYS) - HIERARCHIC_LEVELS = 5 LIST_FIELDS = { # key: hierarchic depth @@ -354,11 +330,11 @@ def show_source_item(request, source_id, model, name, base_dct, extra_dct): source_id, external_id = int(source_id), int(external_id) except ValueError: raise Http404() - models_rest.ApiExternalSource.objects.get() + ApiExternalSource = apps.get_model("ishtar_common", "ApiExternalSource") # TODO: check permissions try: - src = models_rest.ApiExternalSource.objects.get(pk=source_id) - except models_rest.ApiExternalSource.DoesNotExist: + src = ApiExternalSource.objects.get(pk=source_id) + except ApiExternalSource.DoesNotExist: return HttpResponse("{}", content_type="text/plain") url = src.url if not url.endswith("/"): @@ -618,6 +594,8 @@ def _get_values(request, val): else: vals = [val] new_vals = [] + Organization = apps.get_model("ishtar_common", "Organization") + Person = apps.get_model("ishtar_common", "Person") for v in vals: if callable(v): try: @@ -626,7 +604,7 @@ def _get_values(request, val): continue try: if ( - not isinstance(v, (models.Person, models.Organization)) + not isinstance(v, (Person, Organization)) and hasattr(v, "url") and v.url ): @@ -1144,7 +1122,7 @@ def _manage_dated_fields(dated_fields, dct): def _clean_type_val(val): - for prefix in GeneralType.PREFIX_CODES: + for prefix in GENERAL_TYPE_PREFIX["prefix_codes"]: val = val.replace(prefix, "") val = val.strip() if val.startswith('"') and val.endswith('"'): @@ -1210,6 +1188,7 @@ def _manage_hierarchic_fields(model, dct, and_reqs): hierarchic_fields = HIERARCHIC_FIELDS[:] if hasattr(model, "hierarchic_fields"): hierarchic_fields += model.hierarchic_fields() + Town = apps.get_model("ishtar_common", "Town") for reqs in dct.copy(): if type(reqs) not in (list, tuple): reqs = [reqs] @@ -1257,6 +1236,7 @@ def _manage_hierarchic_fields(model, dct, and_reqs): and_reqs.append(main_req) continue + Container = apps.get_model("archaeological_warehouse", "Container") for val in vals: attr = "cached_label__iexact" if val.endswith("*"): @@ -1277,7 +1257,7 @@ def _manage_hierarchic_fields(model, dct, and_reqs): vals = [v.replace('"', "") for v in val.split(";")] town_ids = [] for val in vals: - q = models.Town.objects.filter(cached_label__iexact=val).values_list( + q = Town.objects.filter(cached_label__iexact=val).values_list( "id", flat=True) if not q.count(): continue @@ -1287,7 +1267,7 @@ def _manage_hierarchic_fields(model, dct, and_reqs): for rel_query in ("parents__", "children__"): for idx in range(HIERARCHIC_LEVELS): k = rel_query * (idx + 1) + "pk" - q = models.Town.objects.filter( + q = Town.objects.filter( **{k: town_id}).values_list("id", flat=True) if not q.count(): break @@ -1595,6 +1575,7 @@ def _manage_default_search( dct, request, model, default_name, my_base_request, my_relative_session_names ): pinned_search = "" + current_item_keys_dict = get_current_item_keys_dict() pin_key = "pin-search-" + default_name base_request = my_base_request if isinstance(my_base_request, dict) else {} dct = {k: v for k, v in dct.items() if v} @@ -1606,6 +1587,7 @@ def _manage_default_search( ): # an item is pinned value = request.session[default_name] if "basket-" in value: + FindBasket = apps.get_model("archaeological_finds", "FindBasket") try: dct = {"basket__pk": request.session[default_name].split("-")[-1]} pinned_search = str(FindBasket.objects.get(pk=dct["basket__pk"])) @@ -1630,9 +1612,9 @@ def _manage_default_search( name in request.session and request.session[name] and "basket-" not in request.session[name] - and name in CURRENT_ITEM_KEYS_DICT + and name in current_item_keys_dict ): - up_model = CURRENT_ITEM_KEYS_DICT[name] + up_model = current_item_keys_dict[name] try: dct.update({key: request.session[name]}) up_item = up_model.objects.get(pk=dct[key]) @@ -2031,6 +2013,7 @@ def get_item( no_link=False, no_limit=False, return_query=False, + ishtaruser=None, # could be provided when request is None **dct, ): available_perms = [] @@ -2044,7 +2027,8 @@ def get_item( if "json" in data_type: EMPTY = "[]" - if data_type not in ("json", "csv", "json-image", "json-map", "json-stats"): + if not return_query and data_type not in ( + "json", "csv", "json-image", "json-map", "json-stats"): return HttpResponse(EMPTY, content_type="text/plain") if data_type == "json-stats" and len(model.STATISTIC_MODALITIES) < 2: @@ -2070,6 +2054,7 @@ def get_item( own = True if ( full == "shortcut" + and request and "SHORTCUT_SEARCH" in request.session and request.session["SHORTCUT_SEARCH"] == "own" ): @@ -2077,13 +2062,23 @@ def get_item( query_own = None if own: - q = models.IshtarUser.objects.filter(user_ptr=request.user) - if not q.count(): - return HttpResponse(EMPTY, content_type="text/plain") + # TODO: verify alt_query_own + """ if alt_query_own: query_own = getattr(model, alt_query_own)(q.all()[0]) else: query_own = model.get_query_owns(q.all()[0]) + print(query_own) # TODO - get old request to transform them + """ + user_pk = request.user.pk if request else ishtaruser.pk + q = UserObjectPermission.objects.filter( + user_id=user_pk, + permission__codename=f"view_own_{model._meta.model_name}", + content_type=ContentType.objects.get_for_model(model) + ) + query_own = Q( + pk__in=[int(pk) for pk in q.values_list("object_pk", flat=True)] + ) query_parameters = {} @@ -2191,14 +2186,10 @@ def get_item( request_keys.update(my_extra_request_keys) # manage search on json fields and excluded fields - if ( - search_form - and request - and request.user - and getattr(request.user, "ishtaruser", None) - ): + if search_form: + ishtaruser = request.user.ishtaruser if request else ishtaruser available, __, excluded_fields, json_fields = search_form.check_custom_form( - request.user.ishtaruser + ishtaruser ) # for now no manage on excluded_fields: should we prevent search on # some fields regarding the user concerned? @@ -2218,10 +2209,12 @@ def get_item( if "query" in dct: request_items = dct["query"] request_items["submited"] = True - elif request.method == "POST": + elif request and request.method == "POST": request_items = request.POST - else: + elif request: request_items = request.GET + else: + return HttpResponse(EMPTY, content_type="text/plain") count = dct.get("count", False) @@ -2271,7 +2264,7 @@ def get_item( key = "name__icontains" else: key = "cached_label__icontains" - dct[key] = request.GET.get("term", None) + dct[key] = (request and request.GET.get("term", None)) or None try: old = "old" in request_items and int(request_items["old"]) @@ -2332,11 +2325,12 @@ def get_item( # manage default and pinned search and not bookmark if ( not has_a_search + and request and not request_items.get("search_vector", "") and not request_items.get("submited", "") and full != "shortcut" ): - if data_type == "csv" and func_name in request.session: + if data_type == "csv" and func_name and func_name in request.session: dct = request.session[func_name] else: # default search @@ -2451,6 +2445,10 @@ def get_item( # manage hierarchic in shortcut menu if full == "shortcut": + File = apps.get_model("archaeological_files", "File") + Operation = apps.get_model("archaeological_operations", "Operation") + ContextRecord = apps.get_model("archaeological_context_records", "ContextRecord") + Find = apps.get_model("archaeological_finds", "Find") ASSOCIATED_ITEMS = { Operation: (File, "associated_file__pk"), ContextRecord: (Operation, "operation__pk"), @@ -2463,6 +2461,7 @@ def get_item( if current: dct = {upper_key: current} query &= Q(**dct) + # print("ishtar_common/views_item.py - 2455") # print(query, distinct_queries, base_query, exc_query, extras) items = model.objects.filter(query) for d_q in distinct_queries: @@ -2540,6 +2539,7 @@ def get_item( for col in cols: query_table_cols += col.split("|") + Document = apps.get_model("ishtar_common", "Document") # contextual (full, simple, etc.) col contxt = full and "full" or "simple" if ( @@ -2559,7 +2559,7 @@ def get_item( table_cols.append("cached_label") if data_type == "json-image": prefix = "" - if model != models.Document: + if model != Document: prefix = "main_image__" query_table_cols.append(prefix + "thumbnail") table_cols.append(prefix + "thumbnail") @@ -2584,7 +2584,7 @@ def get_item( for k in request_items: if not k.startswith("order["): continue - num = int(k.split("]")[0][len("order[") :]) + num = int(k.split("]")[0][len("order["):]) if num not in sorts: sorts[num] = ["", ""] # sign, col_num if k.endswith("[dir]"): @@ -2907,9 +2907,10 @@ def adapt_distant_search(params, src, model): search_vector = params["search_vector"][0] match = RE_FACET.search(search_vector) final_search_vector = "" + ApiKeyMatch = apps.get_model("ishtar_common", "ApiKeyMatch") while match: key, value, __ = match.groups() - q = models_rest.ApiKeyMatch.objects.filter( + q = ApiKeyMatch.objects.filter( source=src, search_model__model__iexact=model, search_keys__contains=[key], @@ -2929,10 +2930,11 @@ def adapt_distant_search(params, src, model): def get_distant_item(request, model, external_source_id, data_type=None): - # TODO: check permissions + # TODO: verify/test check permissions + ApiExternalSource = apps.get_model("ishtar_common", "ApiExternalSource") try: - src = models_rest.ApiExternalSource.objects.get(pk=external_source_id) - except (models_rest.ApiExternalSource.DoesNotExist, ValueError): + src = ApiExternalSource.objects.get(pk=external_source_id) + except (ApiExternalSource.DoesNotExist, ValueError): return HttpResponse("{}", content_type="text/plain") url = src.url url += reverse(f"api-search-{model}") @@ -2954,7 +2956,7 @@ def get_distant_item(request, model, external_source_id, data_type=None): "submited", "data_type", ] - app = models_rest.MAIN_MODELS[model] + app = API_MAIN_MODELS[model] model_class = ContentType.objects.get(app_label=app, model=model).model_class() bool_fields = model_class.REVERSED_BOOL_FIELDS + model_class.BOOL_FIELDS + model_class.CALLABLE_BOOL_FIELDS is_empty_params = not any( @@ -3010,9 +3012,10 @@ def external_export(request, source_id, model_name, slug): if not url: return HttpResponse('Unauthorized', status=401) + ApiExternalSource = apps.get_model("ishtar_common", "ApiExternalSource") try: - src = models_rest.ApiExternalSource.objects.get(pk=source_id) - except (models_rest.ApiExternalSource.DoesNotExist, ValueError): + src = ApiExternalSource.objects.get(pk=source_id) + except (ApiExternalSource.DoesNotExist, ValueError): return HttpResponse('Unauthorized', status=401) url = src.url + url |