diff --git a/arkindex/dataimport/api.py b/arkindex/dataimport/api.py index dd11c84bea50056a688f528e1251dd8f859a80e5..6c937ac32d4b4f6946189377ef880cf65251ae7e 100644 --- a/arkindex/dataimport/api.py +++ b/arkindex/dataimport/api.py @@ -44,6 +44,7 @@ from arkindex.dataimport.models import ( Worker, WorkerActivity, WorkerActivityState, + WorkerConfiguration, WorkerRun, WorkerVersion, ) @@ -65,6 +66,7 @@ from arkindex.dataimport.serializers.imports import ( from arkindex.dataimport.serializers.workers import ( RepositorySerializer, WorkerActivitySerializer, + WorkerConfigurationSerializer, WorkerSerializer, WorkerStatisticsSerializer, WorkerVersionEditSerializer, @@ -985,6 +987,30 @@ class WorkerRetrieve(WorkerACLMixin, RetrieveAPIView): return worker +@extend_schema( + tags=['repos'], + description=( + 'List configurations for a given worker ID.\n\n' + 'Requires a **read** access to the worker or its repository.' + ) +) +class WorkerConfigurationList(WorkerACLMixin, ListAPIView): + permission_classes = (IsVerified, ) + serializer_class = WorkerConfigurationSerializer + queryset = WorkerConfiguration.objects.none() + + def get_queryset(self): + worker = get_object_or_404( + Worker.objects.select_related('repository'), + pk=self.kwargs['pk'] + ) + + if not self.has_read_access(worker): + raise PermissionDenied(detail='You do not have a guest access to this worker.') + + return worker.configurations.order_by('name') + + @extend_schema(tags=['imports']) @extend_schema_view( get=extend_schema(description=( diff --git a/arkindex/dataimport/serializers/workers.py b/arkindex/dataimport/serializers/workers.py index 9352efdd187a5edff58de2aa53df0d125863dc57..7336296d11e154b524184ec0b80d384ec5353013 100644 --- a/arkindex/dataimport/serializers/workers.py +++ b/arkindex/dataimport/serializers/workers.py @@ -12,6 +12,7 @@ from arkindex.dataimport.models import ( Worker, WorkerActivity, WorkerActivityState, + WorkerConfiguration, WorkerVersion, WorkerVersionGPUUsage, WorkerVersionState, @@ -186,3 +187,13 @@ class WorkerStatisticsSerializer(serializers.Serializer): started = serializers.IntegerField(read_only=True) processed = serializers.IntegerField(read_only=True) error = serializers.IntegerField(read_only=True) + + +class WorkerConfigurationSerializer(serializers.ModelSerializer): + class Meta: + model = WorkerConfiguration + fields = ( + 'id', + 'name', + 'configuration', + ) diff --git a/arkindex/dataimport/tests/test_workers.py b/arkindex/dataimport/tests/test_workers.py index 2e9014ed3e6c540cbcb462cf11ba13e270a7a420..80cf65cc021bd4d94f688b38ec640d217393c3e0 100644 --- a/arkindex/dataimport/tests/test_workers.py +++ b/arkindex/dataimport/tests/test_workers.py @@ -959,3 +959,52 @@ class TestWorkersWorkerVersions(FixtureAPITestCase): data={'revision': str(self.rev2.id), 'configuration': {"test": "test2"}, 'gpu_usage': 'not_supported'}, format='json' ) self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + def test_configurations_list_requires_login(self): + response = self.client.get(reverse('api:worker-configurations', kwargs={'pk': str(self.worker_1.id)})) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + + def test_configurations_list_requires_verified(self): + self.user.verified_email = False + self.user.save() + self.client.force_login(self.user) + response = self.client.get(reverse('api:worker-configurations', kwargs={'pk': str(self.worker_1.id)})) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + + def test_configurations_list_no_rights(self): + self.worker_1.repository.memberships.filter(user=self.user).delete() + self.client.force_login(self.user) + with self.assertNumQueries(7): + response = self.client.get(reverse('api:worker-configurations', kwargs={'pk': str(self.worker_1.id)})) + self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN) + self.assertEqual(response.json(), {'detail': 'You do not have a guest access to this worker.'}) + + def test_configurations_list(self): + """ + A user is able to retrieve a worker configuation if he has a guest access on it or its repository + """ + repo2 = Repository.objects.create( + url='http://gitlab/repo2', + type=RepositoryType.Worker, + hook_token='hook-token2', + credentials=self.creds, + provider_name='GitLabProvider' + ) + worker_2 = repo2.workers.create(name='Worker 2', slug='worker_2', type='classifier') + config_1 = worker_2.configurations.create(name='config_1', configuration={'key': 'value'}) + config_2 = worker_2.configurations.create(name='config_2') + repo2.memberships.create(user=self.user, level=Role.Guest.value) + + self.client.force_login(self.user) + with self.assertNumQueries(9): + response = self.client.get(reverse('api:worker-configurations', kwargs={'pk': str(worker_2.id)})) + self.assertEqual(response.status_code, status.HTTP_200_OK) + self.assertListEqual(response.json()['results'], [{ + 'id': str(config_1.id), + 'name': 'config_1', + 'configuration': {'key': 'value'} + }, { + 'id': str(config_2.id), + 'name': 'config_2', + 'configuration': {} + }]) diff --git a/arkindex/project/api_v1.py b/arkindex/project/api_v1.py index 223210cc60d890a10be87e1bc356c13dace9dc86..2ec50ddd77a04f2d02ef708a0482999c078982a9 100644 --- a/arkindex/project/api_v1.py +++ b/arkindex/project/api_v1.py @@ -22,6 +22,7 @@ from arkindex.dataimport.api import ( RevisionRetrieve, StartProcess, UpdateWorkerActivity, + WorkerConfigurationList, WorkerList, WorkerRetrieve, WorkerRunDetails, @@ -205,6 +206,7 @@ api = [ # Workers path('workers/', WorkerList.as_view(), name='workers-list'), path('workers/<uuid:pk>/', WorkerRetrieve.as_view(), name='worker-retrieve'), + path('workers/<uuid:pk>/configurations/', WorkerConfigurationList.as_view(), name='worker-configurations'), path('workers/<uuid:pk>/versions/', WorkerVersionList.as_view(), name='worker-versions'), path('workers/versions/<uuid:pk>/', WorkerVersionRetrieve.as_view(), name='version-retrieve'), path('workers/versions/<uuid:pk>/activity/', UpdateWorkerActivity.as_view(), name='update-worker-activity'),