✨(backend) add API endpoint to list a document's children
This endpoint is nested under a document's detail endpoint.
This commit is contained in:
committed by
Anthony LC
parent
4333b46901
commit
7ff4bc457f
@@ -489,6 +489,26 @@ class DocumentViewSet(
|
|||||||
{"id": str(document.id)}, status=status.HTTP_201_CREATED
|
{"id": str(document.id)}, status=status.HTTP_201_CREATED
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@drf.decorators.action(
|
||||||
|
detail=True,
|
||||||
|
methods=["get", "post"],
|
||||||
|
serializer_class=serializers.ListDocumentSerializer,
|
||||||
|
)
|
||||||
|
# pylint: disable=unused-argument
|
||||||
|
def children(self, request, pk, *args, **kwargs):
|
||||||
|
"""Custom action to retrieve children of a document"""
|
||||||
|
document = self.get_object()
|
||||||
|
queryset = document.get_children()
|
||||||
|
queryset = self.annotate_queryset(queryset)
|
||||||
|
|
||||||
|
page = self.paginate_queryset(queryset)
|
||||||
|
if page is not None:
|
||||||
|
serializer = self.get_serializer(page, many=True)
|
||||||
|
return self.get_paginated_response(serializer.data)
|
||||||
|
|
||||||
|
serializer = self.get_serializer(queryset, many=True)
|
||||||
|
return drf.response.Response(serializer.data)
|
||||||
|
|
||||||
@drf.decorators.action(detail=True, methods=["get"], url_path="versions")
|
@drf.decorators.action(detail=True, methods=["get"], url_path="versions")
|
||||||
def versions_list(self, request, *args, **kwargs):
|
def versions_list(self, request, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -584,6 +584,7 @@ class Document(MP_Node, BaseModel):
|
|||||||
"ai_transform": can_update,
|
"ai_transform": can_update,
|
||||||
"ai_translate": can_update,
|
"ai_translate": can_update,
|
||||||
"attachment_upload": can_update,
|
"attachment_upload": can_update,
|
||||||
|
"children": can_get,
|
||||||
"collaboration_auth": can_get,
|
"collaboration_auth": can_get,
|
||||||
"destroy": RoleChoices.OWNER in roles,
|
"destroy": RoleChoices.OWNER in roles,
|
||||||
"favorite": can_get and user.is_authenticated,
|
"favorite": can_get and user.is_authenticated,
|
||||||
|
|||||||
@@ -0,0 +1,526 @@
|
|||||||
|
"""
|
||||||
|
Tests for Documents API endpoint in impress's core app: retrieve
|
||||||
|
"""
|
||||||
|
|
||||||
|
import random
|
||||||
|
|
||||||
|
from django.contrib.auth.models import AnonymousUser
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from rest_framework.test import APIClient
|
||||||
|
|
||||||
|
from core import factories
|
||||||
|
|
||||||
|
pytestmark = pytest.mark.django_db
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_documents_children_list_anonymous_public_standalone():
|
||||||
|
"""Anonymous users should be allowed to retrieve the children of a public documents."""
|
||||||
|
document = factories.DocumentFactory(link_reach="public")
|
||||||
|
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||||
|
factories.UserDocumentAccessFactory(document=child1)
|
||||||
|
|
||||||
|
response = APIClient().get(f"/api/v1.0/documents/{document.id!s}/children/")
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json() == {
|
||||||
|
"count": 2,
|
||||||
|
"next": None,
|
||||||
|
"previous": None,
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"abilities": child1.get_abilities(AnonymousUser()),
|
||||||
|
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
"creator": str(child1.creator.id),
|
||||||
|
"depth": 2,
|
||||||
|
"excerpt": child1.excerpt,
|
||||||
|
"id": str(child1.id),
|
||||||
|
"is_favorite": False,
|
||||||
|
"link_reach": child1.link_reach,
|
||||||
|
"link_role": child1.link_role,
|
||||||
|
"numchild": 0,
|
||||||
|
"nb_accesses": 1,
|
||||||
|
"path": child1.path,
|
||||||
|
"title": child1.title,
|
||||||
|
"updated_at": child1.updated_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"abilities": child2.get_abilities(AnonymousUser()),
|
||||||
|
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
"creator": str(child2.creator.id),
|
||||||
|
"depth": 2,
|
||||||
|
"excerpt": child2.excerpt,
|
||||||
|
"id": str(child2.id),
|
||||||
|
"is_favorite": False,
|
||||||
|
"link_reach": child2.link_reach,
|
||||||
|
"link_role": child2.link_role,
|
||||||
|
"numchild": 0,
|
||||||
|
"nb_accesses": 0,
|
||||||
|
"path": child2.path,
|
||||||
|
"title": child2.title,
|
||||||
|
"updated_at": child2.updated_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_documents_children_list_anonymous_public_parent():
|
||||||
|
"""
|
||||||
|
Anonymous users should be allowed to retrieve the children of a document who
|
||||||
|
has a public ancestor.
|
||||||
|
"""
|
||||||
|
grand_parent = factories.DocumentFactory(link_reach="public")
|
||||||
|
parent = factories.DocumentFactory(
|
||||||
|
parent=grand_parent, link_reach=random.choice(["authenticated", "restricted"])
|
||||||
|
)
|
||||||
|
document = factories.DocumentFactory(
|
||||||
|
link_reach=random.choice(["authenticated", "restricted"]), parent=parent
|
||||||
|
)
|
||||||
|
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||||
|
factories.UserDocumentAccessFactory(document=child1)
|
||||||
|
|
||||||
|
response = APIClient().get(f"/api/v1.0/documents/{document.id!s}/children/")
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json() == {
|
||||||
|
"count": 2,
|
||||||
|
"next": None,
|
||||||
|
"previous": None,
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"abilities": child1.get_abilities(AnonymousUser()),
|
||||||
|
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
"creator": str(child1.creator.id),
|
||||||
|
"depth": 4,
|
||||||
|
"excerpt": child1.excerpt,
|
||||||
|
"id": str(child1.id),
|
||||||
|
"is_favorite": False,
|
||||||
|
"link_reach": child1.link_reach,
|
||||||
|
"link_role": child1.link_role,
|
||||||
|
"numchild": 0,
|
||||||
|
"nb_accesses": 1,
|
||||||
|
"path": child1.path,
|
||||||
|
"title": child1.title,
|
||||||
|
"updated_at": child1.updated_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"abilities": child2.get_abilities(AnonymousUser()),
|
||||||
|
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
"creator": str(child2.creator.id),
|
||||||
|
"depth": 4,
|
||||||
|
"excerpt": child2.excerpt,
|
||||||
|
"id": str(child2.id),
|
||||||
|
"is_favorite": False,
|
||||||
|
"link_reach": child2.link_reach,
|
||||||
|
"link_role": child2.link_role,
|
||||||
|
"numchild": 0,
|
||||||
|
"nb_accesses": 0,
|
||||||
|
"path": child2.path,
|
||||||
|
"title": child2.title,
|
||||||
|
"updated_at": child2.updated_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("reach", ["restricted", "authenticated"])
|
||||||
|
def test_api_documents_children_list_anonymous_restricted_or_authenticated(reach):
|
||||||
|
"""
|
||||||
|
Anonymous users should not be able to retrieve children of a document that is not public.
|
||||||
|
"""
|
||||||
|
document = factories.DocumentFactory(link_reach=reach)
|
||||||
|
factories.DocumentFactory.create_batch(2, parent=document)
|
||||||
|
|
||||||
|
response = APIClient().get(f"/api/v1.0/documents/{document.id!s}/children/")
|
||||||
|
|
||||||
|
assert response.status_code == 401
|
||||||
|
assert response.json() == {
|
||||||
|
"detail": "Authentication credentials were not provided."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("reach", ["public", "authenticated"])
|
||||||
|
def test_api_documents_children_list_authenticated_unrelated_public_or_authenticated(
|
||||||
|
reach,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Authenticated users should be able to retrieve the children of a public/authenticated
|
||||||
|
document to which they are not related.
|
||||||
|
"""
|
||||||
|
user = factories.UserFactory()
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
document = factories.DocumentFactory(link_reach=reach)
|
||||||
|
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||||
|
factories.UserDocumentAccessFactory(document=child1)
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/documents/{document.id!s}/children/",
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json() == {
|
||||||
|
"count": 2,
|
||||||
|
"next": None,
|
||||||
|
"previous": None,
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"abilities": child1.get_abilities(user),
|
||||||
|
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
"creator": str(child1.creator.id),
|
||||||
|
"depth": 2,
|
||||||
|
"excerpt": child1.excerpt,
|
||||||
|
"id": str(child1.id),
|
||||||
|
"is_favorite": False,
|
||||||
|
"link_reach": child1.link_reach,
|
||||||
|
"link_role": child1.link_role,
|
||||||
|
"numchild": 0,
|
||||||
|
"nb_accesses": 1,
|
||||||
|
"path": child1.path,
|
||||||
|
"title": child1.title,
|
||||||
|
"updated_at": child1.updated_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"abilities": child2.get_abilities(user),
|
||||||
|
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
"creator": str(child2.creator.id),
|
||||||
|
"depth": 2,
|
||||||
|
"excerpt": child2.excerpt,
|
||||||
|
"id": str(child2.id),
|
||||||
|
"is_favorite": False,
|
||||||
|
"link_reach": child2.link_reach,
|
||||||
|
"link_role": child2.link_role,
|
||||||
|
"numchild": 0,
|
||||||
|
"nb_accesses": 0,
|
||||||
|
"path": child2.path,
|
||||||
|
"title": child2.title,
|
||||||
|
"updated_at": child2.updated_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("reach", ["public", "authenticated"])
|
||||||
|
def test_api_documents_children_list_authenticated_public_or_authenticated_parent(
|
||||||
|
reach,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Authenticated users should be allowed to retrieve the children of a document who
|
||||||
|
has a public or authenticated ancestor.
|
||||||
|
"""
|
||||||
|
user = factories.UserFactory()
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
grand_parent = factories.DocumentFactory(link_reach=reach)
|
||||||
|
parent = factories.DocumentFactory(parent=grand_parent, link_reach="restricted")
|
||||||
|
document = factories.DocumentFactory(link_reach="restricted", parent=parent)
|
||||||
|
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||||
|
factories.UserDocumentAccessFactory(document=child1)
|
||||||
|
|
||||||
|
response = client.get(f"/api/v1.0/documents/{document.id!s}/children/")
|
||||||
|
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json() == {
|
||||||
|
"count": 2,
|
||||||
|
"next": None,
|
||||||
|
"previous": None,
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"abilities": child1.get_abilities(user),
|
||||||
|
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
"creator": str(child1.creator.id),
|
||||||
|
"depth": 4,
|
||||||
|
"excerpt": child1.excerpt,
|
||||||
|
"id": str(child1.id),
|
||||||
|
"is_favorite": False,
|
||||||
|
"link_reach": child1.link_reach,
|
||||||
|
"link_role": child1.link_role,
|
||||||
|
"numchild": 0,
|
||||||
|
"nb_accesses": 1,
|
||||||
|
"path": child1.path,
|
||||||
|
"title": child1.title,
|
||||||
|
"updated_at": child1.updated_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"abilities": child2.get_abilities(user),
|
||||||
|
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
"creator": str(child2.creator.id),
|
||||||
|
"depth": 4,
|
||||||
|
"excerpt": child2.excerpt,
|
||||||
|
"id": str(child2.id),
|
||||||
|
"is_favorite": False,
|
||||||
|
"link_reach": child2.link_reach,
|
||||||
|
"link_role": child2.link_role,
|
||||||
|
"numchild": 0,
|
||||||
|
"nb_accesses": 0,
|
||||||
|
"path": child2.path,
|
||||||
|
"title": child2.title,
|
||||||
|
"updated_at": child2.updated_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_documents_children_list_authenticated_unrelated_restricted():
|
||||||
|
"""
|
||||||
|
Authenticated users should not be allowed to retrieve the children of a document that is
|
||||||
|
restricted and to which they are not related.
|
||||||
|
"""
|
||||||
|
user = factories.UserFactory(with_owned_document=True)
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
document = factories.DocumentFactory(link_reach="restricted")
|
||||||
|
child1, _child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||||
|
factories.UserDocumentAccessFactory(document=child1)
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/documents/{document.id!s}/children/",
|
||||||
|
)
|
||||||
|
assert response.status_code == 403
|
||||||
|
assert response.json() == {
|
||||||
|
"detail": "You do not have permission to perform this action."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_documents_children_list_authenticated_related_direct():
|
||||||
|
"""
|
||||||
|
Authenticated users should be allowed to retrieve the children of a document
|
||||||
|
to which they are directly related whatever the role.
|
||||||
|
"""
|
||||||
|
user = factories.UserFactory()
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
document = factories.DocumentFactory()
|
||||||
|
factories.UserDocumentAccessFactory(document=document, user=user)
|
||||||
|
factories.UserDocumentAccessFactory(document=document)
|
||||||
|
|
||||||
|
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||||
|
factories.UserDocumentAccessFactory(document=child1)
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/documents/{document.id!s}/children/",
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json() == {
|
||||||
|
"count": 2,
|
||||||
|
"next": None,
|
||||||
|
"previous": None,
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"abilities": child1.get_abilities(user),
|
||||||
|
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
"creator": str(child1.creator.id),
|
||||||
|
"depth": 2,
|
||||||
|
"excerpt": child1.excerpt,
|
||||||
|
"id": str(child1.id),
|
||||||
|
"is_favorite": False,
|
||||||
|
"link_reach": child1.link_reach,
|
||||||
|
"link_role": child1.link_role,
|
||||||
|
"numchild": 0,
|
||||||
|
"nb_accesses": 3,
|
||||||
|
"path": child1.path,
|
||||||
|
"title": child1.title,
|
||||||
|
"updated_at": child1.updated_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"abilities": child2.get_abilities(user),
|
||||||
|
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
"creator": str(child2.creator.id),
|
||||||
|
"depth": 2,
|
||||||
|
"excerpt": child2.excerpt,
|
||||||
|
"id": str(child2.id),
|
||||||
|
"is_favorite": False,
|
||||||
|
"link_reach": child2.link_reach,
|
||||||
|
"link_role": child2.link_role,
|
||||||
|
"numchild": 0,
|
||||||
|
"nb_accesses": 2,
|
||||||
|
"path": child2.path,
|
||||||
|
"title": child2.title,
|
||||||
|
"updated_at": child2.updated_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_documents_children_list_authenticated_related_parent():
|
||||||
|
"""
|
||||||
|
Authenticated users should be allowed to retrieve the children of a document if they
|
||||||
|
are related to one of its ancestors whatever the role.
|
||||||
|
"""
|
||||||
|
user = factories.UserFactory()
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
grand_parent = factories.DocumentFactory(link_reach="restricted")
|
||||||
|
parent = factories.DocumentFactory(parent=grand_parent, link_reach="restricted")
|
||||||
|
document = factories.DocumentFactory(parent=parent, link_reach="restricted")
|
||||||
|
|
||||||
|
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||||
|
factories.UserDocumentAccessFactory(document=child1)
|
||||||
|
|
||||||
|
factories.UserDocumentAccessFactory(document=grand_parent, user=user)
|
||||||
|
factories.UserDocumentAccessFactory(document=grand_parent)
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/documents/{document.id!s}/children/",
|
||||||
|
)
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json() == {
|
||||||
|
"count": 2,
|
||||||
|
"next": None,
|
||||||
|
"previous": None,
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"abilities": child1.get_abilities(user),
|
||||||
|
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
"creator": str(child1.creator.id),
|
||||||
|
"depth": 4,
|
||||||
|
"excerpt": child1.excerpt,
|
||||||
|
"id": str(child1.id),
|
||||||
|
"is_favorite": False,
|
||||||
|
"link_reach": child1.link_reach,
|
||||||
|
"link_role": child1.link_role,
|
||||||
|
"numchild": 0,
|
||||||
|
"nb_accesses": 3,
|
||||||
|
"path": child1.path,
|
||||||
|
"title": child1.title,
|
||||||
|
"updated_at": child1.updated_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"abilities": child2.get_abilities(user),
|
||||||
|
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
"creator": str(child2.creator.id),
|
||||||
|
"depth": 4,
|
||||||
|
"excerpt": child2.excerpt,
|
||||||
|
"id": str(child2.id),
|
||||||
|
"is_favorite": False,
|
||||||
|
"link_reach": child2.link_reach,
|
||||||
|
"link_role": child2.link_role,
|
||||||
|
"numchild": 0,
|
||||||
|
"nb_accesses": 2,
|
||||||
|
"path": child2.path,
|
||||||
|
"title": child2.title,
|
||||||
|
"updated_at": child2.updated_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_documents_children_list_authenticated_related_child():
|
||||||
|
"""
|
||||||
|
Authenticated users should not be allowed to retrieve all the children of a document
|
||||||
|
as a result of being related to one of its children.
|
||||||
|
"""
|
||||||
|
user = factories.UserFactory()
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
document = factories.DocumentFactory(link_reach="restricted")
|
||||||
|
child1, _child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||||
|
|
||||||
|
factories.UserDocumentAccessFactory(document=child1, user=user)
|
||||||
|
factories.UserDocumentAccessFactory(document=document)
|
||||||
|
|
||||||
|
response = client.get(
|
||||||
|
f"/api/v1.0/documents/{document.id!s}/children/",
|
||||||
|
)
|
||||||
|
assert response.status_code == 403
|
||||||
|
assert response.json() == {
|
||||||
|
"detail": "You do not have permission to perform this action."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_documents_children_list_authenticated_related_team_none(mock_user_teams):
|
||||||
|
"""
|
||||||
|
Authenticated users should not be able to retrieve the children of a restricted document
|
||||||
|
related to teams in which the user is not.
|
||||||
|
"""
|
||||||
|
mock_user_teams.return_value = []
|
||||||
|
|
||||||
|
user = factories.UserFactory(with_owned_document=True)
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
document = factories.DocumentFactory(link_reach="restricted")
|
||||||
|
factories.DocumentFactory.create_batch(2, parent=document)
|
||||||
|
|
||||||
|
factories.TeamDocumentAccessFactory(document=document, team="myteam")
|
||||||
|
|
||||||
|
response = client.get(f"/api/v1.0/documents/{document.id!s}/children/")
|
||||||
|
assert response.status_code == 403
|
||||||
|
assert response.json() == {
|
||||||
|
"detail": "You do not have permission to perform this action."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_api_documents_children_list_authenticated_related_team_members(
|
||||||
|
mock_user_teams,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Authenticated users should be allowed to retrieve the children of a document to which they
|
||||||
|
are related via a team whatever the role.
|
||||||
|
"""
|
||||||
|
mock_user_teams.return_value = ["myteam"]
|
||||||
|
|
||||||
|
user = factories.UserFactory()
|
||||||
|
|
||||||
|
client = APIClient()
|
||||||
|
client.force_login(user)
|
||||||
|
|
||||||
|
document = factories.DocumentFactory(link_reach="restricted")
|
||||||
|
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||||
|
|
||||||
|
factories.TeamDocumentAccessFactory(document=document, team="myteam")
|
||||||
|
|
||||||
|
response = client.get(f"/api/v1.0/documents/{document.id!s}/children/")
|
||||||
|
|
||||||
|
# pylint: disable=R0801
|
||||||
|
assert response.status_code == 200
|
||||||
|
assert response.json() == {
|
||||||
|
"count": 2,
|
||||||
|
"next": None,
|
||||||
|
"previous": None,
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"abilities": child1.get_abilities(user),
|
||||||
|
"created_at": child1.created_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
"creator": str(child1.creator.id),
|
||||||
|
"depth": 2,
|
||||||
|
"excerpt": child1.excerpt,
|
||||||
|
"id": str(child1.id),
|
||||||
|
"is_favorite": False,
|
||||||
|
"link_reach": child1.link_reach,
|
||||||
|
"link_role": child1.link_role,
|
||||||
|
"numchild": 0,
|
||||||
|
"nb_accesses": 1,
|
||||||
|
"path": child1.path,
|
||||||
|
"title": child1.title,
|
||||||
|
"updated_at": child1.updated_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"abilities": child2.get_abilities(user),
|
||||||
|
"created_at": child2.created_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
"creator": str(child2.creator.id),
|
||||||
|
"depth": 2,
|
||||||
|
"excerpt": child2.excerpt,
|
||||||
|
"id": str(child2.id),
|
||||||
|
"is_favorite": False,
|
||||||
|
"link_reach": child2.link_reach,
|
||||||
|
"link_role": child2.link_role,
|
||||||
|
"numchild": 0,
|
||||||
|
"nb_accesses": 1,
|
||||||
|
"path": child2.path,
|
||||||
|
"title": child2.title,
|
||||||
|
"updated_at": child2.updated_at.isoformat().replace("+00:00", "Z"),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ def test_api_documents_retrieve_anonymous_public_standalone():
|
|||||||
"ai_transform": document.link_role == "editor",
|
"ai_transform": document.link_role == "editor",
|
||||||
"ai_translate": document.link_role == "editor",
|
"ai_translate": document.link_role == "editor",
|
||||||
"attachment_upload": document.link_role == "editor",
|
"attachment_upload": document.link_role == "editor",
|
||||||
|
"children": True,
|
||||||
"collaboration_auth": True,
|
"collaboration_auth": True,
|
||||||
"destroy": False,
|
"destroy": False,
|
||||||
# Anonymous user can't favorite a document even with read access
|
# Anonymous user can't favorite a document even with read access
|
||||||
@@ -77,6 +78,7 @@ def test_api_documents_retrieve_anonymous_public_parent():
|
|||||||
"ai_transform": grand_parent.link_role == "editor",
|
"ai_transform": grand_parent.link_role == "editor",
|
||||||
"ai_translate": grand_parent.link_role == "editor",
|
"ai_translate": grand_parent.link_role == "editor",
|
||||||
"attachment_upload": grand_parent.link_role == "editor",
|
"attachment_upload": grand_parent.link_role == "editor",
|
||||||
|
"children": True,
|
||||||
"collaboration_auth": True,
|
"collaboration_auth": True,
|
||||||
"destroy": False,
|
"destroy": False,
|
||||||
# Anonymous user can't favorite a document even with read access
|
# Anonymous user can't favorite a document even with read access
|
||||||
@@ -161,6 +163,7 @@ def test_api_documents_retrieve_authenticated_unrelated_public_or_authenticated(
|
|||||||
"ai_transform": document.link_role == "editor",
|
"ai_transform": document.link_role == "editor",
|
||||||
"ai_translate": document.link_role == "editor",
|
"ai_translate": document.link_role == "editor",
|
||||||
"attachment_upload": document.link_role == "editor",
|
"attachment_upload": document.link_role == "editor",
|
||||||
|
"children": True,
|
||||||
"collaboration_auth": True,
|
"collaboration_auth": True,
|
||||||
"destroy": False,
|
"destroy": False,
|
||||||
"favorite": True,
|
"favorite": True,
|
||||||
@@ -218,6 +221,7 @@ def test_api_documents_retrieve_authenticated_public_or_authenticated_parent(rea
|
|||||||
"ai_transform": grand_parent.link_role == "editor",
|
"ai_transform": grand_parent.link_role == "editor",
|
||||||
"ai_translate": grand_parent.link_role == "editor",
|
"ai_translate": grand_parent.link_role == "editor",
|
||||||
"attachment_upload": grand_parent.link_role == "editor",
|
"attachment_upload": grand_parent.link_role == "editor",
|
||||||
|
"children": True,
|
||||||
"collaboration_auth": True,
|
"collaboration_auth": True,
|
||||||
"destroy": False,
|
"destroy": False,
|
||||||
"favorite": True,
|
"favorite": True,
|
||||||
@@ -382,6 +386,7 @@ def test_api_documents_retrieve_authenticated_related_parent():
|
|||||||
"ai_transform": access.role != "reader",
|
"ai_transform": access.role != "reader",
|
||||||
"ai_translate": access.role != "reader",
|
"ai_translate": access.role != "reader",
|
||||||
"attachment_upload": access.role != "reader",
|
"attachment_upload": access.role != "reader",
|
||||||
|
"children": True,
|
||||||
"collaboration_auth": True,
|
"collaboration_auth": True,
|
||||||
"destroy": access.role == "owner",
|
"destroy": access.role == "owner",
|
||||||
"favorite": True,
|
"favorite": True,
|
||||||
|
|||||||
@@ -109,6 +109,7 @@ def test_models_documents_get_abilities_forbidden(is_authenticated, reach, role)
|
|||||||
"ai_transform": False,
|
"ai_transform": False,
|
||||||
"ai_translate": False,
|
"ai_translate": False,
|
||||||
"attachment_upload": False,
|
"attachment_upload": False,
|
||||||
|
"children": False,
|
||||||
"collaboration_auth": False,
|
"collaboration_auth": False,
|
||||||
"destroy": False,
|
"destroy": False,
|
||||||
"favorite": False,
|
"favorite": False,
|
||||||
@@ -146,6 +147,7 @@ def test_models_documents_get_abilities_reader(is_authenticated, reach):
|
|||||||
"ai_transform": False,
|
"ai_transform": False,
|
||||||
"ai_translate": False,
|
"ai_translate": False,
|
||||||
"attachment_upload": False,
|
"attachment_upload": False,
|
||||||
|
"children": True,
|
||||||
"collaboration_auth": True,
|
"collaboration_auth": True,
|
||||||
"destroy": False,
|
"destroy": False,
|
||||||
"favorite": is_authenticated,
|
"favorite": is_authenticated,
|
||||||
@@ -183,6 +185,7 @@ def test_models_documents_get_abilities_editor(is_authenticated, reach):
|
|||||||
"ai_transform": True,
|
"ai_transform": True,
|
||||||
"ai_translate": True,
|
"ai_translate": True,
|
||||||
"attachment_upload": True,
|
"attachment_upload": True,
|
||||||
|
"children": True,
|
||||||
"collaboration_auth": True,
|
"collaboration_auth": True,
|
||||||
"destroy": False,
|
"destroy": False,
|
||||||
"favorite": is_authenticated,
|
"favorite": is_authenticated,
|
||||||
@@ -209,6 +212,7 @@ def test_models_documents_get_abilities_owner():
|
|||||||
"ai_transform": True,
|
"ai_transform": True,
|
||||||
"ai_translate": True,
|
"ai_translate": True,
|
||||||
"attachment_upload": True,
|
"attachment_upload": True,
|
||||||
|
"children": True,
|
||||||
"collaboration_auth": True,
|
"collaboration_auth": True,
|
||||||
"destroy": True,
|
"destroy": True,
|
||||||
"favorite": True,
|
"favorite": True,
|
||||||
@@ -234,6 +238,7 @@ def test_models_documents_get_abilities_administrator():
|
|||||||
"ai_transform": True,
|
"ai_transform": True,
|
||||||
"ai_translate": True,
|
"ai_translate": True,
|
||||||
"attachment_upload": True,
|
"attachment_upload": True,
|
||||||
|
"children": True,
|
||||||
"collaboration_auth": True,
|
"collaboration_auth": True,
|
||||||
"destroy": False,
|
"destroy": False,
|
||||||
"favorite": True,
|
"favorite": True,
|
||||||
@@ -262,6 +267,7 @@ def test_models_documents_get_abilities_editor_user(django_assert_num_queries):
|
|||||||
"ai_transform": True,
|
"ai_transform": True,
|
||||||
"ai_translate": True,
|
"ai_translate": True,
|
||||||
"attachment_upload": True,
|
"attachment_upload": True,
|
||||||
|
"children": True,
|
||||||
"collaboration_auth": True,
|
"collaboration_auth": True,
|
||||||
"destroy": False,
|
"destroy": False,
|
||||||
"favorite": True,
|
"favorite": True,
|
||||||
@@ -292,6 +298,7 @@ def test_models_documents_get_abilities_reader_user(django_assert_num_queries):
|
|||||||
"ai_transform": False,
|
"ai_transform": False,
|
||||||
"ai_translate": False,
|
"ai_translate": False,
|
||||||
"attachment_upload": False,
|
"attachment_upload": False,
|
||||||
|
"children": True,
|
||||||
"collaboration_auth": True,
|
"collaboration_auth": True,
|
||||||
"destroy": False,
|
"destroy": False,
|
||||||
"favorite": True,
|
"favorite": True,
|
||||||
@@ -323,6 +330,7 @@ def test_models_documents_get_abilities_preset_role(django_assert_num_queries):
|
|||||||
"ai_transform": False,
|
"ai_transform": False,
|
||||||
"ai_translate": False,
|
"ai_translate": False,
|
||||||
"attachment_upload": False,
|
"attachment_upload": False,
|
||||||
|
"children": True,
|
||||||
"collaboration_auth": True,
|
"collaboration_auth": True,
|
||||||
"destroy": False,
|
"destroy": False,
|
||||||
"favorite": True,
|
"favorite": True,
|
||||||
|
|||||||
Reference in New Issue
Block a user