diff --git a/swh/deposit/api/private/deposit_list.py b/swh/deposit/api/private/deposit_list.py index 4bb40e31..e8c07e31 100644 --- a/swh/deposit/api/private/deposit_list.py +++ b/swh/deposit/api/private/deposit_list.py @@ -3,10 +3,20 @@ # License: GNU General Public License version 3, or any later version # See top-level LICENSE file for more information - +from django.core.paginator import Paginator +from django.db.models import CharField, Q, TextField +from django.http import JsonResponse +from rest_framework.decorators import ( + api_view, + authentication_classes, + permission_classes, +) from rest_framework.generics import ListAPIView +from rest_framework.permissions import AllowAny +import sentry_sdk from swh.deposit.api.utils import DefaultPagination, DepositSerializer +from swh.deposit.utils import parse_swh_deposit_origin, parse_swh_metadata_provenance from . import APIPrivateView from ...models import Deposit @@ -66,3 +76,96 @@ class APIList(ListAPIView, APIPrivateView): deposits_qs = deposits_qs.exclude(external_id__startswith=exclude_like) return deposits_qs.order_by("id") + + +def _deposit_search_query(search_value: str) -> Q: + fields = [f for f in Deposit._meta.fields if isinstance(f, (CharField, TextField))] + queries = [Q(**{f.name + "__icontains": search_value}) for f in fields] + search_query = Q() + for query in queries: + search_query = search_query | query + return search_query + + +@api_view() +@authentication_classes([]) +@permission_classes([AllowAny]) +def deposit_list_datatables(request): + table_data = {} + table_data["draw"] = int(request.GET["draw"]) + try: + deposits = Deposit.objects.all() + deposits_count = deposits.count() + search_value = request.GET["search[value]"] + if search_value: + deposits = deposits.filter(_deposit_search_query(search_value)) + + exclude_pattern = request.GET.get("excludePattern") + if exclude_pattern: + deposits = deposits.exclude(_deposit_search_query(exclude_pattern)) + + column_order = request.GET["order[0][column]"] + field_order = request.GET["columns[%s][name]" % column_order] + order_dir = request.GET["order[0][dir]"] + + if order_dir == "desc": + field_order = "-" + field_order + + deposits = deposits.order_by(field_order) + + length = int(request.GET["length"]) + page = int(request.GET["start"]) / length + 1 + paginator = Paginator(deposits, length) + + data = [DepositSerializer(d).data for d in paginator.page(page).object_list] + + table_data["recordsTotal"] = deposits_count + table_data["recordsFiltered"] = deposits.count() + data_list = [] + for d in data: + data_dict = { + "id": d["id"], + "type": d["type"], + "external_id": d["external_id"], + "reception_date": d["reception_date"], + "status": d["status"], + "status_detail": d["status_detail"], + "swhid": d["swhid"], + "swhid_context": d["swhid_context"], + } + provenance = None + raw_metadata = d["raw_metadata"] + # Try to determine provenance out of the raw metadata + if raw_metadata and d["type"] == "meta": # metadata provenance + provenance = parse_swh_metadata_provenance(d["raw_metadata"]) + elif raw_metadata and d["type"] == "code": + provenance = parse_swh_deposit_origin(raw_metadata) + + if not provenance and d["origin_url"]: + provenance = d["origin_url"] + + # Finally, if still not found, we determine uri using the swhid + if not provenance and d["swhid_context"]: + # Trying to compute the origin as we did before in the js + from swh.model.swhids import QualifiedSWHID + + swhid = QualifiedSWHID.from_string(d["swhid_context"]) + provenance = swhid.origin + + data_dict["uri"] = provenance # could be None + + # This could be large. As this is not displayed yet, drop it to avoid + # cluttering the data dict + data_dict.pop("raw_metadata", None) + + data_list.append(data_dict) + + table_data["data"] = data_list + + except Exception as exc: + sentry_sdk.capture_exception(exc) + table_data[ + "error" + ] = "An error occurred while retrieving the list of deposits !" + + return JsonResponse(table_data) diff --git a/swh/deposit/api/private/urls.py b/swh/deposit/api/private/urls.py index e48290d6..2243aca1 100644 --- a/swh/deposit/api/private/urls.py +++ b/swh/deposit/api/private/urls.py @@ -10,10 +10,11 @@ from ...config import ( PRIVATE_GET_DEPOSIT_METADATA, PRIVATE_GET_RAW_CONTENT, PRIVATE_LIST_DEPOSITS, + PRIVATE_LIST_DEPOSITS_DATATABLES, PRIVATE_PUT_DEPOSIT, ) from .deposit_check import APIChecks -from .deposit_list import APIList +from .deposit_list import APIList, deposit_list_datatables from .deposit_read import APIReadArchives, APIReadMetadata from .deposit_update_status import APIUpdateStatus @@ -75,4 +76,9 @@ urlpatterns = [ name=PRIVATE_CHECK_DEPOSIT + "-nc", ), url(r"^deposits/$", APIList.as_view(), name=PRIVATE_LIST_DEPOSITS), + url( + r"^deposits/datatables/$", + deposit_list_datatables, + name=PRIVATE_LIST_DEPOSITS_DATATABLES, + ), ] diff --git a/swh/deposit/config.py b/swh/deposit/config.py index 758ecf09..e91a781b 100644 --- a/swh/deposit/config.py +++ b/swh/deposit/config.py @@ -27,6 +27,7 @@ PRIVATE_CHECK_DEPOSIT = "check-deposit" PRIVATE_PUT_DEPOSIT = "private-update" PRIVATE_GET_DEPOSIT_METADATA = "private-read" PRIVATE_LIST_DEPOSITS = "private-deposit-list" +PRIVATE_LIST_DEPOSITS_DATATABLES = "private-deposit-list-datatables" ARCHIVE_KEY = "archive" RAW_METADATA_KEY = "raw-metadata"