diff --git a/swh/deposit/api/collection.py b/swh/deposit/api/collection.py --- a/swh/deposit/api/collection.py +++ b/swh/deposit/api/collection.py @@ -5,7 +5,9 @@ from typing import Optional, Tuple +from django.shortcuts import render from rest_framework import status +from rest_framework.generics import ListAPIView from ..config import DEPOSIT_STATUS_LOAD_SUCCESS, EDIT_IRI from ..models import Deposit @@ -22,14 +24,15 @@ Receipt, get_collection_by_name, ) +from .utils import DefaultPagination, DepositSerializer -class CollectionAPI(APIPost): +class CollectionAPI(ListAPIView, APIPost): """Deposit request class defining api endpoints for sword deposit. What's known as 'Col-IRI' in the sword specification. - HTTP verbs supported: POST + HTTP verbs supported: GET and POST """ @@ -40,6 +43,43 @@ SWHAtomEntryParser, ) + serializer_class = DepositSerializer + pagination_class = DefaultPagination + + def get(self, request, *args, **kwargs): + """List the user's collection if the user has access to said collection. + + """ + self.checks(request, kwargs["collection_name"]) + paginated_result = super().get(request, *args, **kwargs) + data = paginated_result.data + # Build pagination link headers + links = [] + for link_name in ["next", "previous"]: + link = data.get(link_name) + if link is None: + continue + links.append(f'<{link}>; rel="{link_name}"') + response = render( + request, + "deposit/collection_list.xml", + context={ + "count": data["count"], + "results": [dict(d) for d in data["results"]], + }, + content_type="application/xml", + status=status.HTTP_200_OK, + ) + response._headers["Link"] = ",".join(links) + return response + + def get_queryset(self): + """List the deposits for the authenticated user (pagination is handled by the + `pagination_class` class attribute). + + """ + return Deposit.objects.filter(client=self.request.user.id).order_by("id") + def process_post( self, req, diff --git a/swh/deposit/api/collection_list.py b/swh/deposit/api/collection_list.py deleted file mode 100644 --- a/swh/deposit/api/collection_list.py +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright (C) 2021 The Software Heritage developers -# See the AUTHORS file at the top-level directory of this distribution -# License: GNU General Public License version 3, or any later version -# See top-level LICENSE file for more information - -from django.shortcuts import render -from rest_framework import status -from rest_framework.generics import ListAPIView - -from swh.deposit.api.common import APIBase -from swh.deposit.api.utils import DefaultPagination, DepositSerializer -from swh.deposit.models import Deposit - - -class CollectionListAPI(ListAPIView, APIBase): - """Deposit request class to list the user deposits. - - HTTP verbs supported: ``GET`` - - """ - - serializer_class = DepositSerializer - pagination_class = DefaultPagination - - def get(self, request, *args, **kwargs): - """List the user's collection if the user has access to said collection. - - """ - self.checks(request, kwargs["collection_name"]) - paginated_result = super().get(request, *args, **kwargs) - data = paginated_result.data - # Build pagination link headers - links = [] - for link_name in ["next", "previous"]: - link = data.get(link_name) - if link is None: - continue - links.append(f'<{link}>; rel="{link_name}"') - response = render( - request, - "deposit/collection_list.xml", - context={ - "count": data["count"], - "results": [dict(d) for d in data["results"]], - }, - content_type="application/xml", - status=status.HTTP_200_OK, - ) - response._headers["Link"] = ",".join(links) - return response - - def get_queryset(self): - """List the deposits for the authenticated user (pagination is handled by the - `pagination_class` class attribute). - - """ - return Deposit.objects.filter(client=self.request.user.id).order_by("id") diff --git a/swh/deposit/api/urls.py b/swh/deposit/api/urls.py --- a/swh/deposit/api/urls.py +++ b/swh/deposit/api/urls.py @@ -10,18 +10,8 @@ from django.conf.urls import url from django.shortcuts import render -from ..config import ( - COL_IRI, - COLLECTION_LIST, - CONT_FILE_IRI, - EDIT_IRI, - EM_IRI, - SD_IRI, - SE_IRI, - STATE_IRI, -) +from ..config import COL_IRI, CONT_FILE_IRI, EDIT_IRI, EM_IRI, SD_IRI, SE_IRI, STATE_IRI from .collection import CollectionAPI -from .collection_list import CollectionListAPI from .content import ContentAPI from .edit import EditAPI from .edit_media import EditMediaAPI @@ -83,9 +73,4 @@ ), # specification is not clear about # File-IRI, we assume it's the same as # the Cont-IRI one - url( - r"^(?P[^/]+)/list/$", - CollectionListAPI.as_view(), - name=COLLECTION_LIST, - ), ] diff --git a/swh/deposit/config.py b/swh/deposit/config.py --- a/swh/deposit/config.py +++ b/swh/deposit/config.py @@ -22,7 +22,6 @@ SD_IRI = "servicedocument" COL_IRI = "upload" STATE_IRI = "state_iri" -COLLECTION_LIST = "collection-list" PRIVATE_GET_RAW_CONTENT = "private-download" PRIVATE_CHECK_DEPOSIT = "check-deposit" PRIVATE_PUT_DEPOSIT = "private-update" diff --git a/swh/deposit/tests/api/test_collection_list.py b/swh/deposit/tests/api/test_collection_list.py --- a/swh/deposit/tests/api/test_collection_list.py +++ b/swh/deposit/tests/api/test_collection_list.py @@ -9,11 +9,7 @@ from requests.utils import parse_header_links from rest_framework import status -from swh.deposit.config import ( - COLLECTION_LIST, - DEPOSIT_STATUS_DEPOSITED, - DEPOSIT_STATUS_PARTIAL, -) +from swh.deposit.config import COL_IRI, DEPOSIT_STATUS_DEPOSITED, DEPOSIT_STATUS_PARTIAL from swh.deposit.models import DepositCollection from swh.deposit.parsers import parse_xml @@ -22,7 +18,7 @@ """Deposit list should require authentication """ - url = reverse(COLLECTION_LIST, args=("test",)) + url = reverse(COL_IRI, args=("test",)) response = anonymous_client.get(url) assert response.status_code == status.HTTP_401_UNAUTHORIZED assert b"protected by basic authentication" in response.content @@ -40,7 +36,7 @@ coll2 = deposit_another_collection assert coll.name != coll2.name # but does not have access to that coll2 collection - url = reverse(COLLECTION_LIST, args=(coll2.name,)) + url = reverse(COL_IRI, args=(coll2.name,)) response = authenticated_client.get(url) # so it gets rejected access to the listing of that coll2 collection assert response.status_code == status.HTTP_403_FORBIDDEN @@ -64,7 +60,7 @@ deposit_id2 = str(deposited_deposit.id) coll = partial_deposit.collection # requesting the listing of the deposit for the user's collection - url = reverse(COLLECTION_LIST, args=(coll.name,)) + url = reverse(COL_IRI, args=(coll.name,)) response = authenticated_client.get(f"{url}?page_size=1") assert response.status_code == status.HTTP_200_OK