From 7b5698a370c7ef10e3e5cc231bd240b26612c71d Mon Sep 17 00:00:00 2001 From: Anthony LC Date: Fri, 31 May 2024 17:06:39 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=91=94(backend)=20object=20user=20on=20Do?= =?UTF-8?q?cumentAccessSerializer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit user field was displaying the userid, but we need to return the user object on the DocumentAccessSerializer, so we can show the user email on the frontend. We add the user_id field in write_only mode, so we can keep create and update. --- src/backend/core/api/serializers.py | 12 +++++++- src/backend/core/models.py | 1 + .../documents/test_api_documents_retrieve.py | 20 ++++++++++--- .../templates/test_api_templates_retrieve.py | 9 ++++++ .../core/tests/test_api_document_accesses.py | 29 ++++++++++++++----- .../tests/test_models_document_accesses.py | 19 ++++++++++++ .../tests/test_models_template_accesses.py | 19 ++++++++++++ 7 files changed, 96 insertions(+), 13 deletions(-) diff --git a/src/backend/core/api/serializers.py b/src/backend/core/api/serializers.py index f97db290..a855caba 100644 --- a/src/backend/core/api/serializers.py +++ b/src/backend/core/api/serializers.py @@ -91,10 +91,19 @@ class BaseAccessSerializer(serializers.ModelSerializer): class DocumentAccessSerializer(BaseAccessSerializer): """Serialize document accesses.""" + user_id = serializers.PrimaryKeyRelatedField( + queryset=models.User.objects.all(), + write_only=True, + source="user", + required=False, + allow_null=True, + ) + user = UserSerializer(read_only=True) + class Meta: model = models.DocumentAccess resource_field_name = "document" - fields = ["id", "user", "team", "role", "abilities"] + fields = ["id", "user", "user_id", "team", "role", "abilities"] read_only_fields = ["id", "abilities"] @@ -126,6 +135,7 @@ class DocumentSerializer(BaseResourceSerializer): """Serialize documents.""" content = serializers.CharField(required=False) + accesses = DocumentAccessSerializer(many=True, read_only=True) class Meta: model = models.Document diff --git a/src/backend/core/models.py b/src/backend/core/models.py index c0434536..61c7c2df 100644 --- a/src/backend/core/models.py +++ b/src/backend/core/models.py @@ -289,6 +289,7 @@ class BaseAccess(BaseModel): return { "destroy": can_delete, "update": bool(set_role_to), + "partial_update": bool(set_role_to), "retrieve": bool(roles), "set_role_to": set_role_to, } 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 e3e81eff..c852174f 100644 --- a/src/backend/core/tests/documents/test_api_documents_retrieve.py +++ b/src/backend/core/tests/documents/test_api_documents_retrieve.py @@ -5,6 +5,7 @@ import pytest from rest_framework.test import APIClient from core import factories +from core.api import serializers pytestmark = pytest.mark.django_db @@ -112,30 +113,32 @@ def test_api_documents_retrieve_authenticated_related_direct(): document = factories.DocumentFactory() access1 = factories.UserDocumentAccessFactory(document=document, user=user) access2 = factories.UserDocumentAccessFactory(document=document) + access1_user = serializers.UserSerializer(instance=user).data + access2_user = serializers.UserSerializer(instance=access2.user).data response = client.get( f"/api/v1.0/documents/{document.id!s}/", ) assert response.status_code == 200 content = response.json() - assert sorted(content.pop("accesses"), key=lambda x: x["user"]) == sorted( + assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted( [ { "id": str(access1.id), - "user": str(user.id), + "user": access1_user, "team": "", "role": access1.role, "abilities": access1.get_abilities(user), }, { "id": str(access2.id), - "user": str(access2.user.id), + "user": access2_user, "team": "", "role": access2.role, "abilities": access2.get_abilities(user), }, ], - key=lambda x: x["user"], + key=lambda x: x["id"], ) assert response.json() == { "id": str(document.id), @@ -226,6 +229,7 @@ def test_api_documents_retrieve_authenticated_related_team_members( "retrieve": True, "set_role_to": [], "update": False, + "partial_update": False, } assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted( [ @@ -332,6 +336,7 @@ def test_api_documents_retrieve_authenticated_related_team_administrators( "retrieve": True, "set_role_to": ["administrator", "editor"], "update": True, + "partial_update": True, }, }, { @@ -344,6 +349,7 @@ def test_api_documents_retrieve_authenticated_related_team_administrators( "retrieve": True, "set_role_to": ["administrator", "reader"], "update": True, + "partial_update": True, }, }, { @@ -356,6 +362,7 @@ def test_api_documents_retrieve_authenticated_related_team_administrators( "retrieve": True, "set_role_to": ["editor", "reader"], "update": True, + "partial_update": True, }, }, { @@ -368,6 +375,7 @@ def test_api_documents_retrieve_authenticated_related_team_administrators( "retrieve": True, "set_role_to": [], "update": False, + "partial_update": False, }, }, { @@ -446,6 +454,7 @@ def test_api_documents_retrieve_authenticated_related_team_owners( "retrieve": True, "set_role_to": ["owner", "administrator", "editor"], "update": True, + "partial_update": True, }, }, { @@ -458,6 +467,7 @@ def test_api_documents_retrieve_authenticated_related_team_owners( "retrieve": True, "set_role_to": ["owner", "administrator", "reader"], "update": True, + "partial_update": True, }, }, { @@ -470,6 +480,7 @@ def test_api_documents_retrieve_authenticated_related_team_owners( "retrieve": True, "set_role_to": ["owner", "editor", "reader"], "update": True, + "partial_update": True, }, }, { @@ -485,6 +496,7 @@ def test_api_documents_retrieve_authenticated_related_team_owners( if other_access.role == "owner" else [], "update": other_access.role == "owner", + "partial_update": other_access.role == "owner", }, }, { diff --git a/src/backend/core/tests/templates/test_api_templates_retrieve.py b/src/backend/core/tests/templates/test_api_templates_retrieve.py index e83bdda0..06ca5f84 100644 --- a/src/backend/core/tests/templates/test_api_templates_retrieve.py +++ b/src/backend/core/tests/templates/test_api_templates_retrieve.py @@ -225,6 +225,7 @@ def test_api_templates_retrieve_authenticated_related_team_readers_or_editors( "retrieve": True, "set_role_to": [], "update": False, + "partial_update": False, } assert sorted(content.pop("accesses"), key=lambda x: x["id"]) == sorted( [ @@ -331,6 +332,7 @@ def test_api_templates_retrieve_authenticated_related_team_administrators( "retrieve": True, "set_role_to": ["administrator", "editor"], "update": True, + "partial_update": True, }, }, { @@ -343,6 +345,7 @@ def test_api_templates_retrieve_authenticated_related_team_administrators( "retrieve": True, "set_role_to": ["administrator", "reader"], "update": True, + "partial_update": True, }, }, { @@ -355,6 +358,7 @@ def test_api_templates_retrieve_authenticated_related_team_administrators( "retrieve": True, "set_role_to": ["editor", "reader"], "update": True, + "partial_update": True, }, }, { @@ -367,6 +371,7 @@ def test_api_templates_retrieve_authenticated_related_team_administrators( "retrieve": True, "set_role_to": [], "update": False, + "partial_update": False, }, }, { @@ -445,6 +450,7 @@ def test_api_templates_retrieve_authenticated_related_team_owners( "retrieve": True, "set_role_to": ["owner", "administrator", "editor"], "update": True, + "partial_update": True, }, }, { @@ -457,6 +463,7 @@ def test_api_templates_retrieve_authenticated_related_team_owners( "retrieve": True, "set_role_to": ["owner", "administrator", "reader"], "update": True, + "partial_update": True, }, }, { @@ -469,6 +476,7 @@ def test_api_templates_retrieve_authenticated_related_team_owners( "retrieve": True, "set_role_to": ["owner", "editor", "reader"], "update": True, + "partial_update": True, }, }, { @@ -484,6 +492,7 @@ def test_api_templates_retrieve_authenticated_related_team_owners( if other_access.role == "owner" else [], "update": other_access.role == "owner", + "partial_update": other_access.role == "owner", }, }, { diff --git a/src/backend/core/tests/test_api_document_accesses.py b/src/backend/core/tests/test_api_document_accesses.py index 7251529a..e632ec26 100644 --- a/src/backend/core/tests/test_api_document_accesses.py +++ b/src/backend/core/tests/test_api_document_accesses.py @@ -92,6 +92,9 @@ def test_api_document_accesses_list_authenticated_related(via, mock_user_get_tea f"/api/v1.0/documents/{document.id!s}/accesses/", ) + access2_user = serializers.UserSerializer(instance=access2.user).data + base_user = serializers.UserSerializer(instance=user).data + assert response.status_code == 200 content = response.json() assert len(content["results"]) == 3 @@ -99,7 +102,7 @@ def test_api_document_accesses_list_authenticated_related(via, mock_user_get_tea [ { "id": str(user_access.id), - "user": str(user.id) if via == "user" else None, + "user": base_user if via == "user" else None, "team": "lasuite" if via == "team" else "", "role": user_access.role, "abilities": user_access.get_abilities(user), @@ -113,7 +116,7 @@ def test_api_document_accesses_list_authenticated_related(via, mock_user_get_tea }, { "id": str(access2.id), - "user": str(access2.user.id), + "user": access2_user, "team": "", "role": access2.role, "abilities": access2.get_abilities(user), @@ -197,10 +200,12 @@ def test_api_document_accesses_retrieve_authenticated_related(via, mock_user_get f"/api/v1.0/documents/{document.id!s}/accesses/{access.id!s}/", ) + access_user = serializers.UserSerializer(instance=access.user).data + assert response.status_code == 200 assert response.json() == { "id": str(access.id), - "user": str(access.user.id), + "user": access_user, "team": "", "role": access.role, "abilities": access.get_abilities(user), @@ -340,7 +345,7 @@ def test_api_document_accesses_create_authenticated_administrator( response = client.post( f"/api/v1.0/documents/{document.id!s}/accesses/", { - "user": str(other_user.id), + "user_id": str(other_user.id), "role": role, }, format="json", @@ -349,12 +354,13 @@ def test_api_document_accesses_create_authenticated_administrator( assert response.status_code == 201 assert models.DocumentAccess.objects.filter(user=other_user).count() == 1 new_document_access = models.DocumentAccess.objects.filter(user=other_user).get() + other_user = serializers.UserSerializer(instance=other_user).data assert response.json() == { "abilities": new_document_access.get_abilities(user), "id": str(new_document_access.id), "team": "", "role": role, - "user": str(other_user.id), + "user": other_user, } @@ -384,7 +390,7 @@ def test_api_document_accesses_create_authenticated_owner(via, mock_user_get_tea response = client.post( f"/api/v1.0/documents/{document.id!s}/accesses/", { - "user": str(other_user.id), + "user_id": str(other_user.id), "role": role, }, format="json", @@ -393,9 +399,10 @@ def test_api_document_accesses_create_authenticated_owner(via, mock_user_get_tea assert response.status_code == 201 assert models.DocumentAccess.objects.filter(user=other_user).count() == 1 new_document_access = models.DocumentAccess.objects.filter(user=other_user).get() + other_user = serializers.UserSerializer(instance=other_user).data assert response.json() == { "id": str(new_document_access.id), - "user": str(other_user.id), + "user": other_user, "team": "", "role": role, "abilities": new_document_access.get_abilities(user), @@ -759,7 +766,13 @@ def test_api_document_accesses_update_owner_self(via, mock_user_get_teams): response = client.put( f"/api/v1.0/documents/{document.id!s}/accesses/{access.id!s}/", - data={**old_values, "role": new_role}, + data={ + **old_values, + "role": new_role, + "user_id": old_values.get("user", {}).get("id") + if old_values.get("user") is not None + else None, + }, format="json", ) diff --git a/src/backend/core/tests/test_models_document_accesses.py b/src/backend/core/tests/test_models_document_accesses.py index 8d5a3dec..4e94423b 100644 --- a/src/backend/core/tests/test_models_document_accesses.py +++ b/src/backend/core/tests/test_models_document_accesses.py @@ -87,6 +87,7 @@ def test_models_document_access_get_abilities_anonymous(): "destroy": False, "retrieve": False, "update": False, + "partial_update": False, "set_role_to": [], } @@ -100,6 +101,7 @@ def test_models_document_access_get_abilities_authenticated(): "destroy": False, "retrieve": False, "update": False, + "partial_update": False, "set_role_to": [], } @@ -119,6 +121,7 @@ def test_models_document_access_get_abilities_for_owner_of_self_allowed(): "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["administrator", "editor", "reader"], } @@ -133,6 +136,7 @@ def test_models_document_access_get_abilities_for_owner_of_self_last(): "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -149,6 +153,7 @@ def test_models_document_access_get_abilities_for_owner_of_owner(): "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["administrator", "editor", "reader"], } @@ -165,6 +170,7 @@ def test_models_document_access_get_abilities_for_owner_of_administrator(): "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["owner", "editor", "reader"], } @@ -181,6 +187,7 @@ def test_models_document_access_get_abilities_for_owner_of_editor(): "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["owner", "administrator", "reader"], } @@ -197,6 +204,7 @@ def test_models_document_access_get_abilities_for_owner_of_reader(): "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["owner", "administrator", "editor"], } @@ -216,6 +224,7 @@ def test_models_document_access_get_abilities_for_administrator_of_owner(): "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -232,6 +241,7 @@ def test_models_document_access_get_abilities_for_administrator_of_administrator "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["editor", "reader"], } @@ -248,6 +258,7 @@ def test_models_document_access_get_abilities_for_administrator_of_editor(): "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["administrator", "reader"], } @@ -264,6 +275,7 @@ def test_models_document_access_get_abilities_for_administrator_of_reader(): "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["administrator", "editor"], } @@ -283,6 +295,7 @@ def test_models_document_access_get_abilities_for_editor_of_owner(): "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -299,6 +312,7 @@ def test_models_document_access_get_abilities_for_editor_of_administrator(): "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -320,6 +334,7 @@ def test_models_document_access_get_abilities_for_editor_of_editor_user( "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -339,6 +354,7 @@ def test_models_document_access_get_abilities_for_reader_of_owner(): "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -355,6 +371,7 @@ def test_models_document_access_get_abilities_for_reader_of_administrator(): "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -376,6 +393,7 @@ def test_models_document_access_get_abilities_for_reader_of_reader_user( "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -395,5 +413,6 @@ def test_models_document_access_get_abilities_preset_role(django_assert_num_quer "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } diff --git a/src/backend/core/tests/test_models_template_accesses.py b/src/backend/core/tests/test_models_template_accesses.py index b15a19bb..e3ebd340 100644 --- a/src/backend/core/tests/test_models_template_accesses.py +++ b/src/backend/core/tests/test_models_template_accesses.py @@ -87,6 +87,7 @@ def test_models_template_access_get_abilities_anonymous(): "destroy": False, "retrieve": False, "update": False, + "partial_update": False, "set_role_to": [], } @@ -100,6 +101,7 @@ def test_models_template_access_get_abilities_authenticated(): "destroy": False, "retrieve": False, "update": False, + "partial_update": False, "set_role_to": [], } @@ -119,6 +121,7 @@ def test_models_template_access_get_abilities_for_owner_of_self_allowed(): "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["administrator", "editor", "reader"], } @@ -133,6 +136,7 @@ def test_models_template_access_get_abilities_for_owner_of_self_last(): "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -149,6 +153,7 @@ def test_models_template_access_get_abilities_for_owner_of_owner(): "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["administrator", "editor", "reader"], } @@ -165,6 +170,7 @@ def test_models_template_access_get_abilities_for_owner_of_administrator(): "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["owner", "editor", "reader"], } @@ -181,6 +187,7 @@ def test_models_template_access_get_abilities_for_owner_of_editor(): "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["owner", "administrator", "reader"], } @@ -197,6 +204,7 @@ def test_models_template_access_get_abilities_for_owner_of_reader(): "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["owner", "administrator", "editor"], } @@ -216,6 +224,7 @@ def test_models_template_access_get_abilities_for_administrator_of_owner(): "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -232,6 +241,7 @@ def test_models_template_access_get_abilities_for_administrator_of_administrator "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["editor", "reader"], } @@ -248,6 +258,7 @@ def test_models_template_access_get_abilities_for_administrator_of_editor(): "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["administrator", "reader"], } @@ -264,6 +275,7 @@ def test_models_template_access_get_abilities_for_administrator_of_reader(): "destroy": True, "retrieve": True, "update": True, + "partial_update": True, "set_role_to": ["administrator", "editor"], } @@ -283,6 +295,7 @@ def test_models_template_access_get_abilities_for_editor_of_owner(): "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -299,6 +312,7 @@ def test_models_template_access_get_abilities_for_editor_of_administrator(): "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -320,6 +334,7 @@ def test_models_template_access_get_abilities_for_editor_of_editor_user( "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -339,6 +354,7 @@ def test_models_template_access_get_abilities_for_reader_of_owner(): "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -355,6 +371,7 @@ def test_models_template_access_get_abilities_for_reader_of_administrator(): "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -376,6 +393,7 @@ def test_models_template_access_get_abilities_for_reader_of_reader_user( "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], } @@ -395,5 +413,6 @@ def test_models_template_access_get_abilities_preset_role(django_assert_num_quer "destroy": False, "retrieve": True, "update": False, + "partial_update": False, "set_role_to": [], }