Skip to content

Commit e148c23

Browse files
lunikaAntoLC
authored andcommitted
🛂(back) restrict duplicate with accesses to admin or owner
Only admin or owner should be able to duplicate a document with existing accesses.
1 parent e82e6a1 commit e148c23

File tree

2 files changed

+50
-4
lines changed

2 files changed

+50
-4
lines changed

src/backend/core/api/viewsets.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -954,6 +954,8 @@ def duplicate(self, request, *args, **kwargs):
954954
)
955955
serializer.is_valid(raise_exception=True)
956956
with_accesses = serializer.validated_data.get("with_accesses", False)
957+
roles = set(document.get_roles(request.user))
958+
is_owner_or_admin = bool(roles.intersection(set(models.PRIVILEGED_ROLES)))
957959

958960
base64_yjs_content = document.content
959961

@@ -985,7 +987,7 @@ def duplicate(self, request, *args, **kwargs):
985987
]
986988

987989
# If accesses should be duplicated, add other users' accesses as per original document
988-
if with_accesses:
990+
if with_accesses and is_owner_or_admin:
989991
original_accesses = models.DocumentAccess.objects.filter(
990992
document=document
991993
).exclude(user=request.user)

src/backend/core/tests/documents/test_api_documents_duplicate.py

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,14 +168,17 @@ def test_api_documents_duplicate_success(index):
168168
assert response.status_code == 403
169169

170170

171-
def test_api_documents_duplicate_with_accesses():
172-
"""Accesses should be duplicated if the user requests it specifically."""
171+
@pytest.mark.parametrize("role", ["owner", "administrator"])
172+
def test_api_documents_duplicate_with_accesses_admin(role):
173+
"""
174+
Accesses should be duplicated if the user requests it specifically and is owner or admin.
175+
"""
173176
user = factories.UserFactory()
174177
client = APIClient()
175178
client.force_login(user)
176179

177180
document = factories.DocumentFactory(
178-
users=[user],
181+
users=[(user, role)],
179182
title="document with accesses",
180183
)
181184
user_access = factories.UserDocumentAccessFactory(document=document)
@@ -205,3 +208,44 @@ def test_api_documents_duplicate_with_accesses():
205208
assert duplicated_accesses.get(user=user).role == "owner"
206209
assert duplicated_accesses.get(user=user_access.user).role == user_access.role
207210
assert duplicated_accesses.get(team=team_access.team).role == team_access.role
211+
212+
213+
@pytest.mark.parametrize("role", ["editor", "reader"])
214+
def test_api_documents_duplicate_with_accesses_non_admin(role):
215+
"""
216+
Accesses should not be duplicated if the user requests it specifically and is not owner
217+
or admin.
218+
"""
219+
user = factories.UserFactory()
220+
client = APIClient()
221+
client.force_login(user)
222+
223+
document = factories.DocumentFactory(
224+
users=[(user, role)],
225+
title="document with accesses",
226+
)
227+
factories.UserDocumentAccessFactory(document=document)
228+
factories.TeamDocumentAccessFactory(document=document)
229+
230+
# Duplicate the document via the API endpoint requesting to duplicate accesses
231+
response = client.post(
232+
f"/api/v1.0/documents/{document.id!s}/duplicate/",
233+
{"with_accesses": True},
234+
format="json",
235+
)
236+
237+
assert response.status_code == 201
238+
239+
duplicated_document = models.Document.objects.get(id=response.json()["id"])
240+
assert duplicated_document.title == "Copy of document with accesses"
241+
assert duplicated_document.content == document.content
242+
assert duplicated_document.link_reach == document.link_reach
243+
assert duplicated_document.link_role == document.link_role
244+
assert duplicated_document.creator == user
245+
assert duplicated_document.duplicated_from == document
246+
assert duplicated_document.attachments == []
247+
248+
# Check that accesses were duplicated and the user who did the duplicate is forced as owner
249+
duplicated_accesses = duplicated_document.accesses
250+
assert duplicated_accesses.count() == 1
251+
assert duplicated_accesses.get(user=user).role == "owner"

0 commit comments

Comments
 (0)