🚨(backend) fix list descendants
I am fixing the _list_descendants logic based on the parent path istead of the parent id and testing. Signed-off-by: charles <[email protected]>
This commit is contained in:
@@ -12,6 +12,7 @@ from core.models import DocumentAccess, RoleChoices, get_trashbin_cutoff
|
||||
ACTION_FOR_METHOD_TO_PERMISSION = {
|
||||
"versions_detail": {"DELETE": "versions_destroy", "GET": "versions_retrieve"},
|
||||
"children": {"GET": "children_list", "POST": "children_create"},
|
||||
"search": {"GET": "retrieve"},
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""
|
||||
Tests for Documents API endpoint in impress's core app: descendants
|
||||
Tests for search API endpoint in impress's core app when indexer is not
|
||||
available and a path param is given.
|
||||
"""
|
||||
|
||||
import random
|
||||
@@ -14,22 +15,55 @@ from core import factories
|
||||
pytestmark = pytest.mark.django_db
|
||||
|
||||
|
||||
def test_api_documents_descendants_list_anonymous_public_standalone():
|
||||
@pytest.fixture(autouse=True)
|
||||
def disable_indexer(indexer_settings):
|
||||
"""Disable search indexer for all tests in this file."""
|
||||
indexer_settings.SEARCH_INDEXER_CLASS = None
|
||||
|
||||
|
||||
def test_api_documents_descendants_list_anonymous_public_standalone(indexer_settings):
|
||||
"""Anonymous users should be allowed to retrieve the descendants of a public document."""
|
||||
document = factories.DocumentFactory(link_reach="public")
|
||||
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||
grand_child = factories.DocumentFactory(parent=child1)
|
||||
document = factories.DocumentFactory(link_reach="public", title="doc parent")
|
||||
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document, title="doc child")
|
||||
grand_child = factories.DocumentFactory(parent=child1, title="doc grand child")
|
||||
|
||||
factories.UserDocumentAccessFactory(document=child1)
|
||||
|
||||
response = APIClient().get(f"/api/v1.0/documents/{document.id!s}/descendants/")
|
||||
response = APIClient().get(
|
||||
"/api/v1.0/documents/search/",
|
||||
data={"q": "doc", "path": document.path}
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"count": 3,
|
||||
"count": 4,
|
||||
"next": None,
|
||||
"previous": None,
|
||||
"results": [
|
||||
{
|
||||
# the search should include the parent document itself
|
||||
"abilities": document.get_abilities(AnonymousUser()),
|
||||
"ancestors_link_reach": None,
|
||||
"ancestors_link_role": None,
|
||||
"computed_link_reach": "public",
|
||||
"computed_link_role": document.computed_link_role,
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 1,
|
||||
"excerpt": document.excerpt,
|
||||
"id": str(document.id),
|
||||
"is_favorite": False,
|
||||
"link_reach": document.link_reach,
|
||||
"link_role": document.link_role,
|
||||
"numchild": 2,
|
||||
"nb_accesses_ancestors": 0,
|
||||
"nb_accesses_direct": 0,
|
||||
"path": document.path,
|
||||
"title": document.title,
|
||||
"updated_at": document.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"user_role": None,
|
||||
},
|
||||
{
|
||||
"abilities": child1.get_abilities(AnonymousUser()),
|
||||
"ancestors_link_reach": "public",
|
||||
@@ -105,31 +139,58 @@ def test_api_documents_descendants_list_anonymous_public_standalone():
|
||||
}
|
||||
|
||||
|
||||
def test_api_documents_descendants_list_anonymous_public_parent():
|
||||
def test_api_documents_descendants_list_anonymous_public_parent(indexer_settings):
|
||||
"""
|
||||
Anonymous users should be allowed to retrieve the descendants of a document who
|
||||
has a public ancestor.
|
||||
"""
|
||||
grand_parent = factories.DocumentFactory(link_reach="public")
|
||||
grand_parent = factories.DocumentFactory(link_reach="public", title="grand parent doc")
|
||||
parent = factories.DocumentFactory(
|
||||
parent=grand_parent, link_reach=random.choice(["authenticated", "restricted"])
|
||||
parent=grand_parent, link_reach=random.choice(["authenticated", "restricted"]), title="parent doc"
|
||||
)
|
||||
document = factories.DocumentFactory(
|
||||
link_reach=random.choice(["authenticated", "restricted"]), parent=parent
|
||||
link_reach=random.choice(["authenticated", "restricted"]), parent=parent, title="document"
|
||||
)
|
||||
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||
grand_child = factories.DocumentFactory(parent=child1)
|
||||
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document, title="child doc")
|
||||
grand_child = factories.DocumentFactory(parent=child1, title="grand child doc")
|
||||
|
||||
factories.UserDocumentAccessFactory(document=child1)
|
||||
|
||||
response = APIClient().get(f"/api/v1.0/documents/{document.id!s}/descendants/")
|
||||
response = APIClient().get(
|
||||
"/api/v1.0/documents/search/",
|
||||
data={"q": "doc", "path": document.path}
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"count": 3,
|
||||
"count": 4,
|
||||
"next": None,
|
||||
"previous": None,
|
||||
"results": [
|
||||
{
|
||||
# the search should include the parent document itself
|
||||
"abilities": document.get_abilities(AnonymousUser()),
|
||||
"ancestors_link_reach": "public",
|
||||
"ancestors_link_role": grand_parent.link_role,
|
||||
"computed_link_reach": document.computed_link_reach,
|
||||
"computed_link_role": document.computed_link_role,
|
||||
"created_at": document.created_at.isoformat().replace("+00:00", "Z"),
|
||||
"creator": str(document.creator.id),
|
||||
"deleted_at": None,
|
||||
"depth": 3,
|
||||
"excerpt": document.excerpt,
|
||||
"id": str(document.id),
|
||||
"is_favorite": False,
|
||||
"link_reach": document.link_reach,
|
||||
"link_role": document.link_role,
|
||||
"numchild": 2,
|
||||
"nb_accesses_ancestors": 0,
|
||||
"nb_accesses_direct": 0,
|
||||
"path": document.path,
|
||||
"title": document.title,
|
||||
"updated_at": document.updated_at.isoformat().replace("+00:00", "Z"),
|
||||
"user_role": None,
|
||||
},
|
||||
{
|
||||
"abilities": child1.get_abilities(AnonymousUser()),
|
||||
"ancestors_link_reach": "public",
|
||||
@@ -204,15 +265,18 @@ def test_api_documents_descendants_list_anonymous_public_parent():
|
||||
|
||||
|
||||
@pytest.mark.parametrize("reach", ["restricted", "authenticated"])
|
||||
def test_api_documents_descendants_list_anonymous_restricted_or_authenticated(reach):
|
||||
def test_api_documents_descendants_list_anonymous_restricted_or_authenticated(reach, indexer_settings):
|
||||
"""
|
||||
Anonymous users should not be able to retrieve descendants of a document that is not public.
|
||||
"""
|
||||
document = factories.DocumentFactory(link_reach=reach)
|
||||
child = factories.DocumentFactory(parent=document)
|
||||
_grand_child = factories.DocumentFactory(parent=child)
|
||||
document = factories.DocumentFactory(title="parent", link_reach=reach)
|
||||
child = factories.DocumentFactory(title="child", parent=document)
|
||||
_grand_child = factories.DocumentFactory(title="grand child", parent=child)
|
||||
|
||||
response = APIClient().get(f"/api/v1.0/documents/{document.id!s}/descendants/")
|
||||
response = APIClient().get(
|
||||
"/api/v1.0/documents/search/",
|
||||
data={"q": "doc", "path": document.path}
|
||||
)
|
||||
|
||||
assert response.status_code == 401
|
||||
assert response.json() == {
|
||||
@@ -222,7 +286,7 @@ def test_api_documents_descendants_list_anonymous_restricted_or_authenticated(re
|
||||
|
||||
@pytest.mark.parametrize("reach", ["public", "authenticated"])
|
||||
def test_api_documents_descendants_list_authenticated_unrelated_public_or_authenticated(
|
||||
reach,
|
||||
reach, indexer_settings
|
||||
):
|
||||
"""
|
||||
Authenticated users should be able to retrieve the descendants of a public/authenticated
|
||||
@@ -232,17 +296,19 @@ def test_api_documents_descendants_list_authenticated_unrelated_public_or_authen
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
|
||||
document = factories.DocumentFactory(link_reach=reach)
|
||||
document = factories.DocumentFactory(link_reach=reach, title="parent")
|
||||
child1, child2 = factories.DocumentFactory.create_batch(
|
||||
2, parent=document, link_reach="restricted"
|
||||
2, parent=document, link_reach="restricted", title="child"
|
||||
)
|
||||
grand_child = factories.DocumentFactory(parent=child1)
|
||||
grand_child = factories.DocumentFactory(parent=child1, title="grand child")
|
||||
|
||||
factories.UserDocumentAccessFactory(document=child1)
|
||||
|
||||
response = client.get(
|
||||
f"/api/v1.0/documents/{document.id!s}/descendants/",
|
||||
"/api/v1.0/documents/search/",
|
||||
data={"q": "child", "path": document.path}
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
"count": 3,
|
||||
@@ -324,7 +390,7 @@ def test_api_documents_descendants_list_authenticated_unrelated_public_or_authen
|
||||
|
||||
@pytest.mark.parametrize("reach", ["public", "authenticated"])
|
||||
def test_api_documents_descendants_list_authenticated_public_or_authenticated_parent(
|
||||
reach,
|
||||
reach, indexer_settings
|
||||
):
|
||||
"""
|
||||
Authenticated users should be allowed to retrieve the descendants of a document who
|
||||
@@ -335,17 +401,20 @@ def test_api_documents_descendants_list_authenticated_public_or_authenticated_pa
|
||||
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)
|
||||
grand_parent = factories.DocumentFactory(link_reach=reach, title="grand parent")
|
||||
parent = factories.DocumentFactory(parent=grand_parent, link_reach="restricted", title="parent")
|
||||
document = factories.DocumentFactory(link_reach="restricted", parent=parent, title="document")
|
||||
child1, child2 = factories.DocumentFactory.create_batch(
|
||||
2, parent=document, link_reach="restricted"
|
||||
2, parent=document, link_reach="restricted", title="child"
|
||||
)
|
||||
grand_child = factories.DocumentFactory(parent=child1)
|
||||
grand_child = factories.DocumentFactory(parent=child1, title="grand child")
|
||||
|
||||
factories.UserDocumentAccessFactory(document=child1)
|
||||
|
||||
response = client.get(f"/api/v1.0/documents/{document.id!s}/descendants/")
|
||||
response = client.get(
|
||||
"/api/v1.0/documents/search/",
|
||||
data={"q": "child", "path": document.path}
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
@@ -426,7 +495,7 @@ def test_api_documents_descendants_list_authenticated_public_or_authenticated_pa
|
||||
}
|
||||
|
||||
|
||||
def test_api_documents_descendants_list_authenticated_unrelated_restricted():
|
||||
def test_api_documents_descendants_list_authenticated_unrelated_restricted(indexer_settings):
|
||||
"""
|
||||
Authenticated users should not be allowed to retrieve the descendants of a document that is
|
||||
restricted and to which they are not related.
|
||||
@@ -435,42 +504,47 @@ def test_api_documents_descendants_list_authenticated_unrelated_restricted():
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
|
||||
document = factories.DocumentFactory(link_reach="restricted")
|
||||
child1, _child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||
_grand_child = factories.DocumentFactory(parent=child1)
|
||||
document = factories.DocumentFactory(link_reach="restricted", title="parent")
|
||||
child1, _child2 = factories.DocumentFactory.create_batch(2, parent=document, title="child")
|
||||
_grand_child = factories.DocumentFactory(parent=child1, title="grand child")
|
||||
|
||||
factories.UserDocumentAccessFactory(document=child1)
|
||||
|
||||
response = client.get(
|
||||
f"/api/v1.0/documents/{document.id!s}/descendants/",
|
||||
"/api/v1.0/documents/search/",
|
||||
data={"q": "child", "path": document.path}
|
||||
)
|
||||
|
||||
assert response.status_code == 403
|
||||
assert response.json() == {
|
||||
"detail": "You do not have permission to perform this action."
|
||||
}
|
||||
|
||||
|
||||
def test_api_documents_descendants_list_authenticated_related_direct():
|
||||
def test_api_documents_descendants_list_authenticated_related_direct(indexer_settings):
|
||||
"""
|
||||
Authenticated users should be allowed to retrieve the descendants of a document
|
||||
to which they are directly related whatever the role.
|
||||
"""
|
||||
indexer_settings.SEARCH_INDEXER_QUERY_URL = None
|
||||
|
||||
user = factories.UserFactory()
|
||||
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
|
||||
document = factories.DocumentFactory()
|
||||
document = factories.DocumentFactory(title="parent")
|
||||
access = factories.UserDocumentAccessFactory(document=document, user=user)
|
||||
factories.UserDocumentAccessFactory(document=document)
|
||||
|
||||
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document, title="child")
|
||||
factories.UserDocumentAccessFactory(document=child1)
|
||||
|
||||
grand_child = factories.DocumentFactory(parent=child1)
|
||||
grand_child = factories.DocumentFactory(parent=child1, title="grand child")
|
||||
|
||||
response = client.get(
|
||||
f"/api/v1.0/documents/{document.id!s}/descendants/",
|
||||
"/api/v1.0/documents/search/",
|
||||
data={"q": "child", "path": document.path}
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
@@ -551,7 +625,7 @@ def test_api_documents_descendants_list_authenticated_related_direct():
|
||||
}
|
||||
|
||||
|
||||
def test_api_documents_descendants_list_authenticated_related_parent():
|
||||
def test_api_documents_descendants_list_authenticated_related_parent(indexer_settings):
|
||||
"""
|
||||
Authenticated users should be allowed to retrieve the descendants of a document if they
|
||||
are related to one of its ancestors whatever the role.
|
||||
@@ -561,21 +635,22 @@ def test_api_documents_descendants_list_authenticated_related_parent():
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
|
||||
grand_parent = factories.DocumentFactory(link_reach="restricted")
|
||||
grand_parent = factories.DocumentFactory(link_reach="restricted", title="parent")
|
||||
grand_parent_access = factories.UserDocumentAccessFactory(
|
||||
document=grand_parent, user=user
|
||||
)
|
||||
|
||||
parent = factories.DocumentFactory(parent=grand_parent, link_reach="restricted")
|
||||
document = factories.DocumentFactory(parent=parent, link_reach="restricted")
|
||||
parent = factories.DocumentFactory(parent=grand_parent, link_reach="restricted", title="parent")
|
||||
document = factories.DocumentFactory(parent=parent, link_reach="restricted", title="document")
|
||||
|
||||
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document, title="child")
|
||||
factories.UserDocumentAccessFactory(document=child1)
|
||||
|
||||
grand_child = factories.DocumentFactory(parent=child1)
|
||||
grand_child = factories.DocumentFactory(parent=child1, title="grand child")
|
||||
|
||||
response = client.get(
|
||||
f"/api/v1.0/documents/{document.id!s}/descendants/",
|
||||
"/api/v1.0/documents/search/",
|
||||
data={"q": "child", "path": document.path}
|
||||
)
|
||||
assert response.status_code == 200
|
||||
assert response.json() == {
|
||||
@@ -656,7 +731,7 @@ def test_api_documents_descendants_list_authenticated_related_parent():
|
||||
}
|
||||
|
||||
|
||||
def test_api_documents_descendants_list_authenticated_related_child():
|
||||
def test_api_documents_descendants_list_authenticated_related_child(indexer_settings):
|
||||
"""
|
||||
Authenticated users should not be allowed to retrieve all the descendants of a document
|
||||
as a result of being related to one of its children.
|
||||
@@ -673,7 +748,8 @@ def test_api_documents_descendants_list_authenticated_related_child():
|
||||
factories.UserDocumentAccessFactory(document=document)
|
||||
|
||||
response = client.get(
|
||||
f"/api/v1.0/documents/{document.id!s}/descendants/",
|
||||
"/api/v1.0/documents/search/",
|
||||
data={"q": "doc", "path": document.path}
|
||||
)
|
||||
assert response.status_code == 403
|
||||
assert response.json() == {
|
||||
@@ -682,24 +758,30 @@ def test_api_documents_descendants_list_authenticated_related_child():
|
||||
|
||||
|
||||
def test_api_documents_descendants_list_authenticated_related_team_none(
|
||||
mock_user_teams,
|
||||
mock_user_teams, indexer_settings
|
||||
):
|
||||
"""
|
||||
Authenticated users should not be able to retrieve the descendants of a restricted document
|
||||
related to teams in which the user is not.
|
||||
"""
|
||||
indexer_settings.SEARCH_INDEXER_QUERY_URL = None
|
||||
|
||||
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)
|
||||
document = factories.DocumentFactory(link_reach="restricted", title="document")
|
||||
factories.DocumentFactory.create_batch(2, parent=document, title="child")
|
||||
|
||||
factories.TeamDocumentAccessFactory(document=document, team="myteam")
|
||||
|
||||
response = client.get(f"/api/v1.0/documents/{document.id!s}/descendants/")
|
||||
response = client.get(
|
||||
"/api/v1.0/documents/search/",
|
||||
data={"q": "doc", "path": document.path}
|
||||
)
|
||||
|
||||
assert response.status_code == 403
|
||||
assert response.json() == {
|
||||
"detail": "You do not have permission to perform this action."
|
||||
@@ -707,7 +789,7 @@ def test_api_documents_descendants_list_authenticated_related_team_none(
|
||||
|
||||
|
||||
def test_api_documents_descendants_list_authenticated_related_team_members(
|
||||
mock_user_teams,
|
||||
mock_user_teams, indexer_settings
|
||||
):
|
||||
"""
|
||||
Authenticated users should be allowed to retrieve the descendants of a document to which they
|
||||
@@ -719,13 +801,16 @@ def test_api_documents_descendants_list_authenticated_related_team_members(
|
||||
client = APIClient()
|
||||
client.force_login(user)
|
||||
|
||||
document = factories.DocumentFactory(link_reach="restricted")
|
||||
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document)
|
||||
grand_child = factories.DocumentFactory(parent=child1)
|
||||
document = factories.DocumentFactory(link_reach="restricted", title="parent")
|
||||
child1, child2 = factories.DocumentFactory.create_batch(2, parent=document, title="child")
|
||||
grand_child = factories.DocumentFactory(parent=child1, title="grand child")
|
||||
|
||||
access = factories.TeamDocumentAccessFactory(document=document, team="myteam")
|
||||
|
||||
response = client.get(f"/api/v1.0/documents/{document.id!s}/descendants/")
|
||||
response = client.get(
|
||||
"/api/v1.0/documents/search/",
|
||||
data={"q": "child", "path": document.path}
|
||||
)
|
||||
|
||||
# pylint: disable=R0801
|
||||
assert response.status_code == 200
|
||||
|
||||
Reference in New Issue
Block a user