Skip to content
Snippets Groups Projects
Commit 5d3624a1 authored by Valentin Rigal's avatar Valentin Rigal Committed by ml bonhomme
Browse files

Restrict ML classes edition to project admins

parent 32b8a4a8
No related branches found
No related tags found
1 merge request!2308Restrict ML classes edition to project admins
import uuid
from textwrap import dedent
from django.db import transaction
from django.utils.functional import cached_property
......@@ -300,16 +301,22 @@ class CorpusMLClassPagination(PageNumberPagination):
@extend_schema_view(
get=extend_schema(
operation_id="ListCorpusMLClasses",
description=dedent("""
List available classes in a corpus.
Requires a **guest** access to the corpus.
"""),
),
post=extend_schema(
operation_id="CreateMLClass",
description="Create an ML class in a corpus",
description=dedent("""
Create an ML class in a corpus.
Requires an **admin** access to the corpus.
"""),
)
)
class CorpusMLClassList(CorpusACLMixin, ListCreateAPIView):
"""
List available classes in a corpus
"""
serializer_class = MLClassSerializer
pagination_class = CorpusMLClassPagination
# For OpenAPI type discovery: a corpus ID is in the path
......@@ -322,7 +329,7 @@ class CorpusMLClassList(CorpusACLMixin, ListCreateAPIView):
def corpus(self):
role = Role.Guest
if self.request.method == "POST":
role = Role.Contributor
role = Role.Admin
return self.get_corpus(self.kwargs["pk"], role=role)
def check_permissions(self, *args, **kwargs):
......@@ -357,10 +364,26 @@ class CorpusMLClassList(CorpusACLMixin, ListCreateAPIView):
@extend_schema(tags=["classifications"])
@extend_schema_view(
get=extend_schema(description="Retrieve a ML class."),
patch=extend_schema(description="Rename a ML class."),
put=extend_schema(description="Rename a ML class."),
delete=extend_schema(description="Delete a ML class if it is not used by any classification."),
get=extend_schema(description=dedent("""
Retrieve an ML class.
Requires a **guest** access to the corpus.
""")),
patch=extend_schema(description=dedent("""
Rename an ML class.
Requires an **admin** access to the corpus.
""")),
put=extend_schema(description=dedent("""
Rename an ML class.
Requires an **admin** access to the corpus.
""")),
delete=extend_schema(description=dedent("""
Delete an ML class if it is not used by any classification.
Requires an **admin** access to the corpus.
""")),
)
class MLClassRetrieve(CorpusACLMixin, RetrieveUpdateDestroyAPIView):
serializer_class = MLClassSerializer
......@@ -372,7 +395,7 @@ class MLClassRetrieve(CorpusACLMixin, RetrieveUpdateDestroyAPIView):
def corpus(self):
role = Role.Guest
if self.request and self.request.method != "GET":
role = Role.Contributor
role = Role.Admin
return self.get_corpus(self.kwargs["corpus"], role=role)
......
......@@ -236,12 +236,12 @@ class TestClasses(FixtureAPITestCase):
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
@patch("arkindex.project.mixins.has_access", return_value=False)
def test_update_requires_contributor(self, has_access_mock):
self.user.rights.update(level=Role.Guest.value)
def test_update_requires_admin(self, has_access_mock):
self.user.rights.update(level=Role.Contributor.value)
self.client.force_login(self.user)
response = self.client.put(reverse("api:ml-class-retrieve", kwargs={"corpus": self.corpus.id, "mlclass": self.text.id}), {"name": "new name"})
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertDictEqual(response.json(), {"detail": "You do not have contributor access to this corpus."})
self.assertDictEqual(response.json(), {"detail": "You do not have admin access to this corpus."})
def test_partial_update(self):
self.client.force_login(self.superuser)
......@@ -266,12 +266,12 @@ class TestClasses(FixtureAPITestCase):
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
@patch("arkindex.project.mixins.has_access", return_value=False)
def test_partial_update_requires_contributor(self, has_access_mock):
self.user.rights.update(level=Role.Guest.value)
def test_partial_update_requires_admin(self, has_access_mock):
self.user.rights.update(level=Role.Contributor.value)
self.client.force_login(self.user)
response = self.client.patch(reverse("api:ml-class-retrieve", kwargs={"corpus": self.corpus.id, "mlclass": self.text.id}), {"name": "new name"})
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertDictEqual(response.json(), {"detail": "You do not have contributor access to this corpus."})
self.assertDictEqual(response.json(), {"detail": "You do not have admin access to this corpus."})
def test_destroy(self):
self.client.force_login(self.superuser)
......@@ -300,12 +300,12 @@ class TestClasses(FixtureAPITestCase):
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
@patch("arkindex.project.mixins.has_access", return_value=False)
def test_destroy_requires_contributor(self, has_access_mock):
self.user.rights.update(level=Role.Guest.value)
def test_destroy_requires_admin(self, has_access_mock):
self.user.rights.update(level=Role.Contributor.value)
self.client.force_login(self.user)
response = self.client.delete(reverse("api:ml-class-retrieve", kwargs={"corpus": self.corpus.id, "mlclass": self.text.id}))
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
self.assertDictEqual(response.json(), {"detail": "You do not have contributor access to this corpus."})
self.assertDictEqual(response.json(), {"detail": "You do not have admin access to this corpus."})
def test_list_elements_db_queries(self):
with self.assertNumQueries(5):
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment