diff --git a/swh/deposit/api/private/deposit_list.py b/swh/deposit/api/private/deposit_list.py new file mode 100644 index 00000000..3a649737 --- /dev/null +++ b/swh/deposit/api/private/deposit_list.py @@ -0,0 +1,37 @@ +# Copyright (C) 2018 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 rest_framework.generics import ListAPIView +from rest_framework.pagination import PageNumberPagination +from rest_framework import serializers + +from ...models import Deposit + + +class DefaultPagination(PageNumberPagination): + page_size = 100 + page_size_query_param = 'page_size' + + +class DepositSerializer(serializers.ModelSerializer): + class Meta: + model = Deposit + fields = ('id', 'reception_date', 'complete_date', 'status', + 'collection', 'external_id', 'client', + 'swh_id', 'swh_id_context', + 'swh_anchor_id', 'swh_anchor_id_context', + 'status', 'status_detail', 'parent') + + +class DepositList(ListAPIView): + """Deposit request class to list the deposit's status per page. + + HTTP verbs supported: GET + + """ + queryset = Deposit.objects.all().order_by('id') + serializer_class = DepositSerializer + pagination_class = DefaultPagination diff --git a/swh/deposit/api/private/urls.py b/swh/deposit/api/private/urls.py index 3a7e532a..14335f25 100644 --- a/swh/deposit/api/private/urls.py +++ b/swh/deposit/api/private/urls.py @@ -1,37 +1,41 @@ -# Copyright (C) 2017 The Software Heritage developers +# Copyright (C) 2017-2018 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.conf.urls import url -from ...config import PRIVATE_GET_RAW_CONTENT -from ...config import PRIVATE_PUT_DEPOSIT, PRIVATE_GET_DEPOSIT_METADATA -from ...config import PRIVATE_CHECK_DEPOSIT +from ...config import ( + PRIVATE_GET_RAW_CONTENT, PRIVATE_PUT_DEPOSIT, PRIVATE_GET_DEPOSIT_METADATA, + PRIVATE_CHECK_DEPOSIT, PRIVATE_LIST_DEPOSITS +) from .deposit_read import SWHDepositReadArchives from .deposit_read import SWHDepositReadMetadata from .deposit_update_status import SWHUpdateStatusDeposit from .deposit_check import SWHChecksDeposit +from .deposit_list import DepositList urlpatterns = [ # Retrieve deposit's raw archives' content # -> GET url(r'^(?P[^/]+)/(?P[^/]+)/raw/$', SWHDepositReadArchives.as_view(), name=PRIVATE_GET_RAW_CONTENT), # Update deposit's status # -> PUT url(r'^(?P[^/]+)/(?P[^/]+)/update/$', SWHUpdateStatusDeposit.as_view(), name=PRIVATE_PUT_DEPOSIT), # Retrieve metadata information on a specific deposit # -> GET url(r'^(?P[^/]+)/(?P[^/]+)/meta/$', SWHDepositReadMetadata.as_view(), name=PRIVATE_GET_DEPOSIT_METADATA), # Check archive and metadata information on a specific deposit # -> GET url(r'^(?P[^/]+)/(?P[^/]+)/check/$', SWHChecksDeposit.as_view(), name=PRIVATE_CHECK_DEPOSIT), + url(r'^deposits/$', DepositList.as_view(), + name=PRIVATE_LIST_DEPOSITS) ] diff --git a/swh/deposit/config.py b/swh/deposit/config.py index fca74e40..2e6b35e1 100644 --- a/swh/deposit/config.py +++ b/swh/deposit/config.py @@ -1,100 +1,101 @@ # Copyright (C) 2017-2018 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 import os import logging from swh.core.config import SWHConfig from swh.scheduler import get_scheduler # IRIs (Internationalized Resource identifier) sword 2.0 specified EDIT_SE_IRI = 'edit_se_iri' EM_IRI = 'em_iri' CONT_FILE_IRI = 'cont_file_iri' SD_IRI = 'servicedocument' COL_IRI = 'upload' STATE_IRI = 'state_iri' PRIVATE_GET_RAW_CONTENT = 'private-download' PRIVATE_CHECK_DEPOSIT = 'check-deposit' PRIVATE_PUT_DEPOSIT = 'private-update' PRIVATE_GET_DEPOSIT_METADATA = 'private-read' +PRIVATE_LIST_DEPOSITS = 'private-deposit-list' ARCHIVE_KEY = 'archive' METADATA_KEY = 'metadata' RAW_METADATA_KEY = 'raw-metadata' ARCHIVE_TYPE = 'archive' METADATA_TYPE = 'metadata' AUTHORIZED_PLATFORMS = ['development', 'production', 'testing'] DEPOSIT_STATUS_REJECTED = 'rejected' DEPOSIT_STATUS_PARTIAL = 'partial' DEPOSIT_STATUS_DEPOSITED = 'deposited' DEPOSIT_STATUS_VERIFIED = 'verified' DEPOSIT_STATUS_LOAD_SUCCESS = 'done' DEPOSIT_STATUS_LOAD_FAILURE = 'failed' # Revision author for deposit SWH_PERSON = { 'name': 'Software Heritage', 'fullname': 'Software Heritage', 'email': 'robot@softwareheritage.org' } def setup_django_for(platform): """Setup function for command line tools (swh.deposit.create_user, swh.deposit.scheduler.cli) to initialize the needed db access. Note: Do not import any django related module prior to this function call. Otherwise, this will raise an django.core.exceptions.ImproperlyConfigured error message. Args: platform (str): the platform the scheduling is running Raises: ValueError in case of wrong platform inputs. """ if platform not in AUTHORIZED_PLATFORMS: raise ValueError('Platform should be one of %s' % AUTHORIZED_PLATFORMS) os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'swh.deposit.settings.%s' % platform) import django django.setup() class SWHDefaultConfig(SWHConfig): """Mixin intended to enrich views with SWH configuration. """ CONFIG_BASE_FILENAME = 'deposit/server' DEFAULT_CONFIG = { 'max_upload_size': ('int', 209715200), 'checks': ('bool', True), 'scheduler': ('dict', { 'cls': 'remote', 'args': { 'url': 'http://localhost:5008/' } }) } ADDITIONAL_CONFIG = {} def __init__(self, **config): super().__init__() self.config = self.parse_config_file( additional_configs=[self.ADDITIONAL_CONFIG]) self.config.update(config) self.log = logging.getLogger('swh.deposit') if self.config['checks']: self.scheduler = get_scheduler(**self.config['scheduler']) diff --git a/swh/deposit/tests/api/test_deposit_list.py b/swh/deposit/tests/api/test_deposit_list.py new file mode 100644 index 00000000..401f04a5 --- /dev/null +++ b/swh/deposit/tests/api/test_deposit_list.py @@ -0,0 +1,64 @@ +# Copyright (C) 2017-2018 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.core.urlresolvers import reverse +from nose.tools import istest +from nose.plugins.attrib import attr +from rest_framework import status +from rest_framework.test import APITestCase + +from ...config import DEPOSIT_STATUS_PARTIAL, PRIVATE_LIST_DEPOSITS +from ..common import BasicTestCase, WithAuthTestCase, CommonCreationRoutine + + +@attr('fs') +class CheckDepositStatusesTest(APITestCase, WithAuthTestCase, + BasicTestCase, CommonCreationRoutine): + """Check deposit statuses endpoints. + + """ + def setUp(self): + super().setUp() + + @istest + def deposit_list(self): + """Deposit list api should return the deposits + + """ + deposit_id = self.create_deposit_partial() + deposit_id2 = self.create_deposit_partial() + + # NOTE: does not work as documented + # https://docs.djangoproject.com/en/1.11/ref/urlresolvers/#django.core.urlresolvers.reverse # noqa + # url = reverse(PRIVATE_LIST_DEPOSITS, kwargs={'page_size': 1}) + main_url = reverse(PRIVATE_LIST_DEPOSITS) + url = '%s?page_size=1' % main_url + response = self.client.get(url) + + self.assertEqual(response.status_code, status.HTTP_200_OK) + data = response.json() + self.assertEqual(data['count'], 2) # 2 deposits + expected_next = '%s?page=2&page_size=1' % main_url + self.assertTrue(data['next'].endswith(expected_next)) + self.assertIsNone(data['previous']) + self.assertEqual(len(data['results']), 1) # page of size 1 + deposit = data['results'][0] + self.assertEquals(deposit['id'], deposit_id) + self.assertEquals(deposit['status'], DEPOSIT_STATUS_PARTIAL) + + # then 2nd page + response2 = self.client.get(expected_next) + + self.assertEqual(response2.status_code, status.HTTP_200_OK) + data2 = response2.json() + + self.assertEqual(data2['count'], 2) # still 2 deposits + self.assertIsNone(data2['next']) + expected_previous = '%s?page_size=1' % main_url + self.assertTrue(data2['previous'].endswith(expected_previous)) + self.assertEqual(len(data2['results']), 1) # page of size 1 + deposit2 = data2['results'][0] + self.assertEquals(deposit2['id'], deposit_id2) + self.assertEquals(deposit2['status'], DEPOSIT_STATUS_PARTIAL)