From 1fc3029d120fe70564e792308259e8f6677907a9 Mon Sep 17 00:00:00 2001 From: Samuel Paccoud - DINUM Date: Fri, 11 Oct 2024 20:42:16 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B(backend)=20fix=20dysfunctional=20p?= =?UTF-8?q?ermissions=20on=20document=20create?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When creating a document access, users were benefitting on the targeted document from the highest access right they have among all documents. This is because we forgot to filter on the document ID when retrieving the role of the user. We improved all tests to secure this issue. --- CHANGELOG.md | 4 +- src/backend/core/api/serializers.py | 1 + src/backend/core/factories.py | 18 +++++ .../documents/test_api_document_accesses.py | 38 ++++----- .../test_api_document_accesses_create.py | 16 ++-- .../test_api_document_invitations.py | 6 +- .../documents/test_api_document_versions.py | 8 +- .../test_api_documents_attachment_upload.py | 4 +- .../documents/test_api_documents_delete.py | 8 +- .../test_api_documents_link_configuration.py | 4 +- .../documents/test_api_documents_retrieve.py | 4 +- .../test_api_documents_retrieve_auth.py | 2 +- .../documents/test_api_documents_update.py | 16 ++-- .../test_api_template_accesses.py | 78 +++++++++---------- 14 files changed, 114 insertions(+), 93 deletions(-) rename src/backend/core/tests/{ => templates}/test_api_template_accesses.py (95%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 48e8fe0b..66450106 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ and this project adheres to - 🐛(frontend) invalidate queries after removing user #336 +## Fixed + +- 🐛(backend) Fix dysfunctional permissions on document create #329 ## [1.5.1] - 2024-10-10 @@ -30,7 +33,6 @@ and this project adheres to - 🐛(db) fix users duplicate #316 - ## [1.5.0] - 2024-10-09 ## Added diff --git a/src/backend/core/api/serializers.py b/src/backend/core/api/serializers.py index 6154ced3..d98049f2 100644 --- a/src/backend/core/api/serializers.py +++ b/src/backend/core/api/serializers.py @@ -69,6 +69,7 @@ class BaseAccessSerializer(serializers.ModelSerializer): if not self.Meta.model.objects.filter( # pylint: disable=no-member Q(user=user) | Q(team__in=user.teams), role__in=[models.RoleChoices.OWNER, models.RoleChoices.ADMIN], + **{self.Meta.resource_field_name: resource_id}, # pylint: disable=no-member ).exists(): raise exceptions.PermissionDenied( "You are not allowed to manage accesses for this resource." diff --git a/src/backend/core/factories.py b/src/backend/core/factories.py index c410615f..2ca7d17a 100644 --- a/src/backend/core/factories.py +++ b/src/backend/core/factories.py @@ -27,6 +27,24 @@ class UserFactory(factory.django.DjangoModelFactory): language = factory.fuzzy.FuzzyChoice([lang[0] for lang in settings.LANGUAGES]) password = make_password("password") + @factory.post_generation + def with_owned_document(self, create, extracted, **kwargs): + """ + Create a document for which the user is owner to check + that there is no interference + """ + if create and (extracted is True): + UserDocumentAccessFactory(user=self, role="owner") + + @factory.post_generation + def with_owned_template(self, create, extracted, **kwargs): + """ + Create a template for which the user is owner to check + that there is no interference + """ + if create and (extracted is True): + UserTemplateAccessFactory(user=self, role="owner") + class DocumentFactory(factory.django.DjangoModelFactory): """A factory to create documents""" diff --git a/src/backend/core/tests/documents/test_api_document_accesses.py b/src/backend/core/tests/documents/test_api_document_accesses.py index 6431b850..9d04d924 100644 --- a/src/backend/core/tests/documents/test_api_document_accesses.py +++ b/src/backend/core/tests/documents/test_api_document_accesses.py @@ -149,7 +149,7 @@ def test_api_document_accesses_retrieve_authenticated_unrelated(): Authenticated users should not be allowed to retrieve a document access for a document to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -246,7 +246,7 @@ def test_api_document_accesses_update_authenticated_unrelated(): Authenticated users should not be allowed to update a document access for a document to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -279,7 +279,7 @@ def test_api_document_accesses_update_authenticated_reader_or_editor( via, role, mock_user_teams ): """Readers or editors of a document should not be allowed to update its accesses.""" - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -321,7 +321,7 @@ def test_api_document_accesses_update_administrator_except_owner(via, mock_user_ A user who is a direct administrator in a document should be allowed to update a user access for this document, as long as they don't try to set the role to owner. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -378,7 +378,7 @@ def test_api_document_accesses_update_administrator_from_owner(via, mock_user_te A user who is an administrator in a document, should not be allowed to update the user access of an "owner" for this document. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -425,7 +425,7 @@ def test_api_document_accesses_update_administrator_to_owner(via, mock_user_team A user who is an administrator in a document, should not be allowed to update the user access of another user to grant document ownership. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -479,7 +479,7 @@ def test_api_document_accesses_update_owner(via, mock_user_teams): A user who is an owner in a document should be allowed to update a user access for this document whatever the role. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -535,7 +535,7 @@ def test_api_document_accesses_update_owner_self(via, mock_user_teams): A user who is owner of a document should be allowed to update their own user access provided there are other owners in the document. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -605,7 +605,7 @@ def test_api_document_accesses_delete_authenticated(): Authenticated users should not be allowed to delete a document access for a document to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -617,7 +617,7 @@ def test_api_document_accesses_delete_authenticated(): ) assert response.status_code == 403 - assert models.DocumentAccess.objects.count() == 1 + assert models.DocumentAccess.objects.count() == 2 @pytest.mark.parametrize("role", ["reader", "editor"]) @@ -627,7 +627,7 @@ def test_api_document_accesses_delete_reader_or_editor(via, role, mock_user_team Authenticated users should not be allowed to delete a document access for a document in which they are a simple reader or editor. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -643,7 +643,7 @@ def test_api_document_accesses_delete_reader_or_editor(via, role, mock_user_team access = factories.UserDocumentAccessFactory(document=document) - assert models.DocumentAccess.objects.count() == 2 + assert models.DocumentAccess.objects.count() == 3 assert models.DocumentAccess.objects.filter(user=access.user).exists() response = client.delete( @@ -651,7 +651,7 @@ def test_api_document_accesses_delete_reader_or_editor(via, role, mock_user_team ) assert response.status_code == 403 - assert models.DocumentAccess.objects.count() == 2 + assert models.DocumentAccess.objects.count() == 3 @pytest.mark.parametrize("via", VIA) @@ -699,7 +699,7 @@ def test_api_document_accesses_delete_administrator_on_owners(via, mock_user_tea Users who are administrators in a document should not be allowed to delete an ownership access from the document. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -717,7 +717,7 @@ def test_api_document_accesses_delete_administrator_on_owners(via, mock_user_tea access = factories.UserDocumentAccessFactory(document=document, role="owner") - assert models.DocumentAccess.objects.count() == 2 + assert models.DocumentAccess.objects.count() == 3 assert models.DocumentAccess.objects.filter(user=access.user).exists() response = client.delete( @@ -725,7 +725,7 @@ def test_api_document_accesses_delete_administrator_on_owners(via, mock_user_tea ) assert response.status_code == 403 - assert models.DocumentAccess.objects.count() == 2 + assert models.DocumentAccess.objects.count() == 3 @pytest.mark.parametrize("via", VIA) @@ -766,7 +766,7 @@ def test_api_document_accesses_delete_owners_last_owner(via, mock_user_teams): """ It should not be possible to delete the last owner access from a document """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -783,10 +783,10 @@ def test_api_document_accesses_delete_owners_last_owner(via, mock_user_teams): document=document, team="lasuite", role="owner" ) - assert models.DocumentAccess.objects.count() == 1 + assert models.DocumentAccess.objects.count() == 2 response = client.delete( f"/api/v1.0/documents/{document.id!s}/accesses/{access.id!s}/", ) assert response.status_code == 403 - assert models.DocumentAccess.objects.count() == 1 + assert models.DocumentAccess.objects.count() == 2 diff --git a/src/backend/core/tests/documents/test_api_document_accesses_create.py b/src/backend/core/tests/documents/test_api_document_accesses_create.py index 9c453073..bd96d04d 100644 --- a/src/backend/core/tests/documents/test_api_document_accesses_create.py +++ b/src/backend/core/tests/documents/test_api_document_accesses_create.py @@ -18,13 +18,13 @@ pytestmark = pytest.mark.django_db def test_api_document_accesses_create_anonymous(): """Anonymous users should not be allowed to create document accesses.""" - user = factories.UserFactory() document = factories.DocumentFactory() + other_user = factories.UserFactory() response = APIClient().post( f"/api/v1.0/documents/{document.id!s}/accesses/", { - "user": str(user.id), + "user_id": str(other_user.id), "document": str(document.id), "role": random.choice(models.RoleChoices.choices)[0], }, @@ -43,7 +43,7 @@ def test_api_document_accesses_create_authenticated_unrelated(): Authenticated users should not be allowed to create document accesses for a document to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -54,7 +54,7 @@ def test_api_document_accesses_create_authenticated_unrelated(): response = client.post( f"/api/v1.0/documents/{document.id!s}/accesses/", { - "user": str(other_user.id), + "user_id": str(other_user.id), }, format="json", ) @@ -69,7 +69,7 @@ def test_api_document_accesses_create_authenticated_reader_or_editor( via, role, mock_user_teams ): """Readers or editors of a document should not be allowed to create document accesses.""" - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -89,7 +89,7 @@ def test_api_document_accesses_create_authenticated_reader_or_editor( response = client.post( f"/api/v1.0/documents/{document.id!s}/accesses/", { - "user": str(other_user.id), + "user_id": str(other_user.id), "role": new_role, }, format="json", @@ -107,7 +107,7 @@ def test_api_document_accesses_create_authenticated_administrator(via, mock_user except for the "owner" role. An email should be sent to the accesses to notify them of the adding. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -129,7 +129,7 @@ def test_api_document_accesses_create_authenticated_administrator(via, mock_user response = client.post( f"/api/v1.0/documents/{document.id!s}/accesses/", { - "user": str(other_user.id), + "user_id": str(other_user.id), "role": "owner", }, format="json", diff --git a/src/backend/core/tests/documents/test_api_document_invitations.py b/src/backend/core/tests/documents/test_api_document_invitations.py index c9d0ecd6..f103b4f8 100644 --- a/src/backend/core/tests/documents/test_api_document_invitations.py +++ b/src/backend/core/tests/documents/test_api_document_invitations.py @@ -601,7 +601,7 @@ def test_api_document_invitations__update__forbidden__not_authenticated( """ Update of invitations is currently forbidden. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) invitation = factories.InvitationFactory() if via == USER: factories.UserDocumentAccessFactory( @@ -641,7 +641,7 @@ def test_api_document_invitations__delete__anonymous(): def test_api_document_invitations__delete__authenticated_outsider(): """Members unrelated to a document should not be allowed to cancel invitations.""" - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) document = factories.DocumentFactory() invitation = factories.InvitationFactory(document=document) @@ -684,7 +684,7 @@ def test_api_document_invitations__delete__privileged_members( @pytest.mark.parametrize("via", VIA) def test_api_document_invitations_delete_readers_or_editors(via, role, mock_user_teams): """Readers or editors should not be able to cancel invitation.""" - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) document = factories.DocumentFactory() if via == USER: factories.UserDocumentAccessFactory(document=document, user=user, role=role) diff --git a/src/backend/core/tests/documents/test_api_document_versions.py b/src/backend/core/tests/documents/test_api_document_versions.py index 69181218..e91012b2 100644 --- a/src/backend/core/tests/documents/test_api_document_versions.py +++ b/src/backend/core/tests/documents/test_api_document_versions.py @@ -39,7 +39,7 @@ def test_api_document_versions_list_authenticated_unrelated(reach): Authenticated users should not be allowed to list document versions for a document to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -231,7 +231,7 @@ def test_api_document_versions_retrieve_authenticated_unrelated(reach): Authenticated users should not be allowed to retrieve specific versions for a document to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -475,7 +475,7 @@ def test_api_document_versions_delete_authenticated(reach): Authenticated users should not be allowed to delete a document version for a public document to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -500,7 +500,7 @@ def test_api_document_versions_delete_reader_or_editor(via, role, mock_user_team Authenticated users should not be allowed to delete a document version for a document in which they are a simple reader or editor. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) diff --git a/src/backend/core/tests/documents/test_api_documents_attachment_upload.py b/src/backend/core/tests/documents/test_api_documents_attachment_upload.py index fab6f65c..064d0c1f 100644 --- a/src/backend/core/tests/documents/test_api_documents_attachment_upload.py +++ b/src/backend/core/tests/documents/test_api_documents_attachment_upload.py @@ -79,7 +79,7 @@ def test_api_documents_attachment_upload_authenticated_forbidden(reach, role): Users who are not related to a document can't upload attachments if the link reach and role don't allow it. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -134,7 +134,7 @@ def test_api_documents_attachment_upload_reader(via, mock_user_teams): """ Users who are simple readers on a document should not be allowed to upload an attachment. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) diff --git a/src/backend/core/tests/documents/test_api_documents_delete.py b/src/backend/core/tests/documents/test_api_documents_delete.py index 9ce6e226..ba12c8ff 100644 --- a/src/backend/core/tests/documents/test_api_documents_delete.py +++ b/src/backend/core/tests/documents/test_api_documents_delete.py @@ -30,7 +30,7 @@ def test_api_documents_delete_authenticated_unrelated(reach, role): Authenticated users should not be allowed to delete a document to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -42,7 +42,7 @@ def test_api_documents_delete_authenticated_unrelated(reach, role): ) assert response.status_code == 403 - assert models.Document.objects.count() == 1 + assert models.Document.objects.count() == 2 @pytest.mark.parametrize("role", ["reader", "editor", "administrator"]) @@ -52,7 +52,7 @@ def test_api_documents_delete_authenticated_not_owner(via, role, mock_user_teams Authenticated users should not be allowed to delete a document for which they are only a reader, editor or administrator. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -74,7 +74,7 @@ def test_api_documents_delete_authenticated_not_owner(via, role, mock_user_teams assert response.json() == { "detail": "You do not have permission to perform this action." } - assert models.Document.objects.count() == 1 + assert models.Document.objects.count() == 2 @pytest.mark.parametrize("via", VIA) diff --git a/src/backend/core/tests/documents/test_api_documents_link_configuration.py b/src/backend/core/tests/documents/test_api_documents_link_configuration.py index 4f8340d3..91f4d7e6 100644 --- a/src/backend/core/tests/documents/test_api_documents_link_configuration.py +++ b/src/backend/core/tests/documents/test_api_documents_link_configuration.py @@ -42,7 +42,7 @@ def test_api_documents_link_configuration_update_authenticated_unrelated(reach, Authenticated users should not be allowed to update the link configuration for a document to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -78,7 +78,7 @@ def test_api_documents_link_configuration_update_authenticated_related_forbidden Users who are readers or editors of a document should not be allowed to update the link configuration. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) diff --git a/src/backend/core/tests/documents/test_api_documents_retrieve.py b/src/backend/core/tests/documents/test_api_documents_retrieve.py index f37339f6..6d32ef08 100644 --- a/src/backend/core/tests/documents/test_api_documents_retrieve.py +++ b/src/backend/core/tests/documents/test_api_documents_retrieve.py @@ -133,7 +133,7 @@ def test_api_documents_retrieve_authenticated_unrelated_restricted(): Authenticated users should not be allowed to retrieve a document that is restricted and to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -208,7 +208,7 @@ def test_api_documents_retrieve_authenticated_related_team_none(mock_user_teams) """ mock_user_teams.return_value = [] - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) diff --git a/src/backend/core/tests/documents/test_api_documents_retrieve_auth.py b/src/backend/core/tests/documents/test_api_documents_retrieve_auth.py index 9e02e17c..6de7cb39 100644 --- a/src/backend/core/tests/documents/test_api_documents_retrieve_auth.py +++ b/src/backend/core/tests/documents/test_api_documents_retrieve_auth.py @@ -142,7 +142,7 @@ def test_api_documents_retrieve_auth_authenticated_restricted(): """ document = factories.DocumentFactory(link_reach="restricted") - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) diff --git a/src/backend/core/tests/documents/test_api_documents_update.py b/src/backend/core/tests/documents/test_api_documents_update.py index 5d400754..d0c1ae32 100644 --- a/src/backend/core/tests/documents/test_api_documents_update.py +++ b/src/backend/core/tests/documents/test_api_documents_update.py @@ -66,14 +66,14 @@ def test_api_documents_update_authenticated_unrelated_forbidden(reach, role): Authenticated users should not be allowed to update a document to which they are not related if the link configuration does not allow it. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) document = factories.DocumentFactory(link_reach=reach, link_role=role) - old_document_values = serializers.DocumentSerializer(instance=document).data + old_document_values = serializers.DocumentSerializer(instance=document).data new_document_values = serializers.DocumentSerializer( instance=factories.DocumentFactory() ).data @@ -111,14 +111,14 @@ def test_api_documents_update_anonymous_or_authenticated_unrelated( client = APIClient() if is_authenticated: - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client.force_login(user) else: user = AnonymousUser() document = factories.DocumentFactory(link_reach=reach, link_role=role) - old_document_values = serializers.DocumentSerializer(instance=document).data + old_document_values = serializers.DocumentSerializer(instance=document).data new_document_values = serializers.DocumentSerializer( instance=factories.DocumentFactory() ).data @@ -146,7 +146,7 @@ def test_api_documents_update_authenticated_reader(via, mock_user_teams): Users who are reader of a document but not administrators should not be allowed to update it. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -187,7 +187,7 @@ def test_api_documents_update_authenticated_editor_administrator_or_owner( via, role, mock_user_teams ): """A user who is editor, administrator or owner of a document should be allowed to update it.""" - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -227,7 +227,7 @@ def test_api_documents_update_authenticated_editor_administrator_or_owner( @pytest.mark.parametrize("via", VIA) def test_api_documents_update_authenticated_owners(via, mock_user_teams): """Administrators of a document should be allowed to update it.""" - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) @@ -269,7 +269,7 @@ def test_api_documents_update_administrator_or_owner_of_another(via, mock_user_t Being administrator or owner of a document should not grant authorization to update another document. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_document=True) client = APIClient() client.force_login(user) diff --git a/src/backend/core/tests/test_api_template_accesses.py b/src/backend/core/tests/templates/test_api_template_accesses.py similarity index 95% rename from src/backend/core/tests/test_api_template_accesses.py rename to src/backend/core/tests/templates/test_api_template_accesses.py index 734fa8b8..cca8deef 100644 --- a/src/backend/core/tests/test_api_template_accesses.py +++ b/src/backend/core/tests/templates/test_api_template_accesses.py @@ -1,6 +1,7 @@ """ Test template accesses API endpoints for users in impress's core app. """ +# pylint: disable=too-many-lines import random from uuid import uuid4 @@ -32,7 +33,7 @@ def test_api_template_accesses_list_authenticated_unrelated(): Authenticated users should not be allowed to list template accesses for a template to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -62,7 +63,7 @@ def test_api_template_accesses_list_authenticated_related(via, mock_user_teams): Authenticated users should be able to list template accesses for a template to which they are directly related, whatever their role in the template. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -146,7 +147,7 @@ def test_api_template_accesses_retrieve_authenticated_unrelated(): Authenticated users should not be allowed to retrieve a template access for a template to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -183,7 +184,7 @@ def test_api_template_accesses_retrieve_authenticated_related(via, mock_user_tea A user who is related to a template should be allowed to retrieve the associated template user accesses. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -213,13 +214,13 @@ def test_api_template_accesses_retrieve_authenticated_related(via, mock_user_tea def test_api_template_accesses_create_anonymous(): """Anonymous users should not be allowed to create template accesses.""" - user = factories.UserFactory() template = factories.TemplateFactory() + other_user = factories.UserFactory() response = APIClient().post( f"/api/v1.0/templates/{template.id!s}/accesses/", { - "user": str(user.id), + "user": str(other_user.id), "template": str(template.id), "role": random.choice(models.RoleChoices.choices)[0], }, @@ -238,7 +239,7 @@ def test_api_template_accesses_create_authenticated_unrelated(): Authenticated users should not be allowed to create template accesses for a template to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -264,7 +265,7 @@ def test_api_template_accesses_create_authenticated_editor_or_reader( via, role, mock_user_teams ): """Editors or readers of a template should not be allowed to create template accesses.""" - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -301,7 +302,7 @@ def test_api_template_accesses_create_authenticated_administrator(via, mock_user Administrators of a template should be able to create template accesses except for the "owner" role. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -365,7 +366,7 @@ def test_api_template_accesses_create_authenticated_owner(via, mock_user_teams): """ Owners of a template should be able to create template accesses whatever the role. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -434,14 +435,14 @@ def test_api_template_accesses_update_authenticated_unrelated(): Authenticated users should not be allowed to update a template access for a template to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) access = factories.UserTemplateAccessFactory() - old_values = serializers.TemplateAccessSerializer(instance=access).data + old_values = serializers.TemplateAccessSerializer(instance=access).data new_values = { "id": uuid4(), "user": factories.UserFactory().id, @@ -467,7 +468,7 @@ def test_api_template_accesses_update_authenticated_editor_or_reader( via, role, mock_user_teams ): """Editors or readers of a template should not be allowed to update its accesses.""" - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -509,7 +510,7 @@ def test_api_template_accesses_update_administrator_except_owner(via, mock_user_ A user who is a direct administrator in a template should be allowed to update a user access for this template, as long as they don't try to set the role to owner. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -529,8 +530,8 @@ def test_api_template_accesses_update_administrator_except_owner(via, mock_user_ template=template, role=random.choice(["administrator", "editor", "reader"]), ) - old_values = serializers.TemplateAccessSerializer(instance=access).data + old_values = serializers.TemplateAccessSerializer(instance=access).data new_values = { "id": uuid4(), "user_id": factories.UserFactory().id, @@ -566,7 +567,7 @@ def test_api_template_accesses_update_administrator_from_owner(via, mock_user_te A user who is an administrator in a template, should not be allowed to update the user access of an "owner" for this template. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -586,8 +587,8 @@ def test_api_template_accesses_update_administrator_from_owner(via, mock_user_te access = factories.UserTemplateAccessFactory( template=template, user=other_user, role="owner" ) - old_values = serializers.TemplateAccessSerializer(instance=access).data + old_values = serializers.TemplateAccessSerializer(instance=access).data new_values = { "id": uuid4(), "user_id": factories.UserFactory().id, @@ -613,7 +614,7 @@ def test_api_template_accesses_update_administrator_to_owner(via, mock_user_team A user who is an administrator in a template, should not be allowed to update the user access of another user to grant template ownership. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -635,8 +636,8 @@ def test_api_template_accesses_update_administrator_to_owner(via, mock_user_team user=other_user, role=random.choice(["administrator", "editor", "reader"]), ) - old_values = serializers.TemplateAccessSerializer(instance=access).data + old_values = serializers.TemplateAccessSerializer(instance=access).data new_values = { "id": uuid4(), "user_id": factories.UserFactory().id, @@ -667,7 +668,7 @@ def test_api_template_accesses_update_owner(via, mock_user_teams): A user who is an owner in a template should be allowed to update a user access for this template whatever the role. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -685,8 +686,8 @@ def test_api_template_accesses_update_owner(via, mock_user_teams): access = factories.UserTemplateAccessFactory( template=template, ) - old_values = serializers.TemplateAccessSerializer(instance=access).data + old_values = serializers.TemplateAccessSerializer(instance=access).data new_values = { "id": uuid4(), "user_id": factories.UserFactory().id, @@ -723,22 +724,21 @@ def test_api_template_accesses_update_owner_self(via, mock_user_teams): A user who is owner of a template should be allowed to update their own user access provided there are other owners in the template. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) template = factories.TemplateFactory() - access = None - if via == USER: - access = factories.UserTemplateAccessFactory( - template=template, user=user, role="owner" - ) - elif via == TEAM: + if via == TEAM: mock_user_teams.return_value = ["lasuite", "unknown"] access = factories.TeamTemplateAccessFactory( template=template, team="lasuite", role="owner" ) + else: + access = factories.UserTemplateAccessFactory( + template=template, user=user, role="owner" + ) old_values = serializers.TemplateAccessSerializer(instance=access).data new_role = random.choice(["administrator", "editor", "reader"]) @@ -787,7 +787,7 @@ def test_api_template_accesses_delete_authenticated(): Authenticated users should not be allowed to delete a template access for a template to which they are not related. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -799,7 +799,7 @@ def test_api_template_accesses_delete_authenticated(): ) assert response.status_code == 403 - assert models.TemplateAccess.objects.count() == 1 + assert models.TemplateAccess.objects.count() == 2 @pytest.mark.parametrize("role", ["reader", "editor"]) @@ -809,7 +809,7 @@ def test_api_template_accesses_delete_editor_or_reader(via, role, mock_user_team Authenticated users should not be allowed to delete a template access for a template in which they are a simple editor or reader. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -825,7 +825,7 @@ def test_api_template_accesses_delete_editor_or_reader(via, role, mock_user_team access = factories.UserTemplateAccessFactory(template=template) - assert models.TemplateAccess.objects.count() == 2 + assert models.TemplateAccess.objects.count() == 3 assert models.TemplateAccess.objects.filter(user=access.user).exists() response = client.delete( @@ -833,7 +833,7 @@ def test_api_template_accesses_delete_editor_or_reader(via, role, mock_user_team ) assert response.status_code == 403 - assert models.TemplateAccess.objects.count() == 2 + assert models.TemplateAccess.objects.count() == 3 @pytest.mark.parametrize("via", VIA) @@ -881,7 +881,7 @@ def test_api_template_accesses_delete_administrator_on_owners(via, mock_user_tea Users who are administrators in a template should not be allowed to delete an ownership access from the template. """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -899,7 +899,7 @@ def test_api_template_accesses_delete_administrator_on_owners(via, mock_user_tea access = factories.UserTemplateAccessFactory(template=template, role="owner") - assert models.TemplateAccess.objects.count() == 2 + assert models.TemplateAccess.objects.count() == 3 assert models.TemplateAccess.objects.filter(user=access.user).exists() response = client.delete( @@ -907,7 +907,7 @@ def test_api_template_accesses_delete_administrator_on_owners(via, mock_user_tea ) assert response.status_code == 403 - assert models.TemplateAccess.objects.count() == 2 + assert models.TemplateAccess.objects.count() == 3 @pytest.mark.parametrize("via", VIA) @@ -948,7 +948,7 @@ def test_api_template_accesses_delete_owners_last_owner(via, mock_user_teams): """ It should not be possible to delete the last owner access from a template """ - user = factories.UserFactory() + user = factories.UserFactory(with_owned_template=True) client = APIClient() client.force_login(user) @@ -965,10 +965,10 @@ def test_api_template_accesses_delete_owners_last_owner(via, mock_user_teams): template=template, team="lasuite", role="owner" ) - assert models.TemplateAccess.objects.count() == 1 + assert models.TemplateAccess.objects.count() == 2 response = client.delete( f"/api/v1.0/templates/{template.id!s}/accesses/{access.id!s}/", ) assert response.status_code == 403 - assert models.TemplateAccess.objects.count() == 1 + assert models.TemplateAccess.objects.count() == 2