Skip to content

Commit b2ed13c

Browse files
authored
Merge pull request #715 from thomasyu888/fix-public-copy-bug
SYNPY-1027: Must copy file when AUTHETICATED_USERS are given DOWNLOAD permissions
2 parents ea05892 + 42a1ce0 commit b2ed13c

File tree

2 files changed

+100
-3
lines changed

2 files changed

+100
-3
lines changed

synapseutils/copy_functions.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -304,10 +304,9 @@ def _copyRecursive(syn, entity, destinationId, mapping=None, skipCopyAnnotations
304304
if not isinstance(ent, (Project, Folder, File, Link, Schema, Entity)):
305305
raise ValueError("Not able to copy this type of file")
306306

307-
profile_username = syn.username
308-
permissions = syn.getPermissions(ent, profile_username)
307+
permissions = syn.restGET("/entity/{}/permissions".format(ent.id))
309308
# Don't copy entities without DOWNLOAD permissions
310-
if "DOWNLOAD" not in permissions:
309+
if not permissions['canDownload']:
311310
print("%s not copied - this file lacks download permission" % ent.id)
312311
return mapping
313312

tests/unit/synapseutils/unit_test_synapseutils_copy.py

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import json
2+
import uuid
23

34
from mock import patch, call
45
from nose.tools import assert_raises, assert_equal
56

7+
import synapseclient
68
import synapseutils
79
from synapseutils.copy_functions import _copy_file_handles_batch, _create_batch_file_handle_copy_request, \
810
_batch_iterator_generator
@@ -285,3 +287,99 @@ def test__batch_iterator_generator__two_iterables(self):
285287
expected_result_list = [[[1, 2], [4, 5]], [[3], [6]]]
286288
result_list = list(_batch_iterator_generator(iterables, batch_size))
287289
assert_equal(expected_result_list, result_list)
290+
291+
292+
class TestCopyPermissions:
293+
"""Test copy entities with different permissions"""
294+
def setup(self):
295+
self.project_entity = synapseclient.Project(name=str(uuid.uuid4()),
296+
id="syn1234")
297+
self.second_project = synapseclient.Project(name=str(uuid.uuid4()),
298+
id="syn2345")
299+
self.file_ent = synapseclient.File(name='File',
300+
parent=self.project_entity.id,
301+
id="syn3456")
302+
303+
def test_dont_copy_read_permissions(self):
304+
"""Entities with READ permissions not copied"""
305+
permissions = {'canDownload': False}
306+
with patch.object(syn, "get",
307+
return_value=self.file_ent) as patch_syn_get,\
308+
patch.object(syn, "restGET",
309+
return_value=permissions) as patch_rest_get:
310+
copied_file = synapseutils.copy(syn, self.file_ent,
311+
destinationId=self.second_project.id,
312+
skipCopyWikiPage=True)
313+
assert_equal(copied_file, dict())
314+
patch_syn_get.assert_called_once_with(self.file_ent,
315+
downloadFile=False)
316+
rest_call = "/entity/{}/permissions".format(self.file_ent.id)
317+
patch_rest_get.assert_called_once_with(rest_call)
318+
319+
320+
class TestCopyAccessRestriction:
321+
"""Test that entities with access restrictions aren't copied"""
322+
def setup(self):
323+
self.project_entity = synapseclient.Project(name=str(uuid.uuid4()),
324+
id="syn1234")
325+
self.second_project = synapseclient.Project(name=str(uuid.uuid4()),
326+
id="syn2345")
327+
self.file_ent = synapseclient.File(name='File',
328+
parent=self.project_entity.id)
329+
self.file_ent.id = "syn3456"
330+
331+
def test_copy_entity_access_requirements(self):
332+
# TEST: Entity with access requirement not copied
333+
access_requirements = {'results': ["fee", "fi"]}
334+
permissions = {'canDownload': True}
335+
with patch.object(syn, "get",
336+
return_value=self.file_ent) as patch_syn_get,\
337+
patch.object(syn, "restGET",
338+
side_effects=[permissions,
339+
access_requirements]) as patch_rest_get:
340+
copied_file = synapseutils.copy(syn, self.file_ent,
341+
destinationId=self.second_project.id,
342+
skipCopyWikiPage=True)
343+
assert_equal(copied_file, dict())
344+
patch_syn_get.assert_called_once_with(self.file_ent,
345+
downloadFile=False)
346+
calls = [call('/entity/{}/accessRequirement'.format(self.file_ent.id)),
347+
call("/entity/{}/permissions".format(self.file_ent.id))]
348+
patch_rest_get.has_calls(calls)
349+
350+
351+
class TestCopy:
352+
"""Test that certain entities aren't copied"""
353+
def setup(self):
354+
self.project_entity = synapseclient.Project(name=str(uuid.uuid4()),
355+
id="syn1234")
356+
self.second_project = synapseclient.Project(name=str(uuid.uuid4()),
357+
id="syn2345")
358+
self.file_ent = synapseclient.File(name='File',
359+
parent=self.project_entity.id)
360+
self.file_ent.id = "syn3456"
361+
362+
def test_no_copy_types(self):
363+
"""Docker repositories and EntityViews aren't copied"""
364+
access_requirements = {'results': []}
365+
permissions = {'canDownload': True}
366+
with patch.object(syn, "get",
367+
return_value=self.project_entity) as patch_syn_get,\
368+
patch.object(syn, "restGET",
369+
side_effect=[permissions,
370+
access_requirements]) as patch_rest_get,\
371+
patch.object(syn, "getChildren") as patch_get_children:
372+
copied_file = synapseutils.copy(syn, self.project_entity,
373+
destinationId=self.second_project.id,
374+
skipCopyWikiPage=True)
375+
assert_equal(copied_file, {self.project_entity.id:
376+
self.second_project.id})
377+
calls = [call(self.project_entity, downloadFile=False),
378+
call(self.second_project.id)]
379+
patch_syn_get.assert_has_calls(calls)
380+
calls = [call('/entity/{}/accessRequirement'.format(self.file_ent.id)),
381+
call("/entity/{}/permissions".format(self.file_ent.id))]
382+
patch_rest_get.has_calls(calls)
383+
patch_get_children.assert_called_once_with(self.project_entity,
384+
includeTypes=['folder', 'file',
385+
'table', 'link'])

0 commit comments

Comments
 (0)