Skip to content

Commit 746dcc7

Browse files
authored
Merge pull request #299 from Duke-GCB/297-prevent-invalid-share-users
prevent sharing with delivery recipient
2 parents 01e2d80 + 3f435f6 commit 746dcc7

2 files changed

Lines changed: 82 additions & 17 deletions

File tree

ddsc/ddsclient.py

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from ddsc.sdk.client import Client
1919

2020
NO_PROJECTS_FOUND_MESSAGE = 'No projects found.'
21+
INVALID_DELIVERY_RECIPIENT_MSG = 'Delivery recipient cannot be a share user. Remove recipient from --share-users and try again.'
2122
TWO_SECONDS = 2
2223

2324

@@ -128,19 +129,14 @@ def make_user_list(self, emails, usernames):
128129
:return: [RemoteUser]: details about any users referenced the two parameters
129130
"""
130131
to_users = []
131-
remaining_emails = [] if not emails else list(emails)
132-
remaining_usernames = [] if not usernames else list(usernames)
133-
for user in self.remote_store.fetch_users():
134-
if user.email in remaining_emails:
132+
if emails:
133+
for email in emails:
134+
user = self.remote_store.get_or_register_user_by_email(email)
135135
to_users.append(user)
136-
remaining_emails.remove(user.email)
137-
elif user.username in remaining_usernames:
136+
if usernames:
137+
for username in usernames:
138+
user = self.remote_store.get_or_register_user_by_username(username)
138139
to_users.append(user)
139-
remaining_usernames.remove(user.username)
140-
if remaining_emails or remaining_usernames:
141-
unable_to_find_users = ','.join(remaining_emails + remaining_usernames)
142-
msg = "Unable to find users for the following email/usernames: {}".format(unable_to_find_users)
143-
raise ValueError(msg)
144140
return to_users
145141

146142

@@ -347,6 +343,8 @@ def run(self, args):
347343
if copy_project:
348344
new_project_name = self.get_new_project_name(project.name)
349345
to_user = self.remote_store.lookup_or_register_user_by_email_or_username(email, username)
346+
if to_user.id in [share_user.id for share_user in share_users]:
347+
raise ValueError(INVALID_DELIVERY_RECIPIENT_MSG)
350348
try:
351349
path_filter = PathFilter(args.include_paths, args.exclude_paths)
352350
dest_email = self.service.deliver(project, new_project_name, to_user, share_users,

ddsc/tests/test_ddsclient.py

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
from __future__ import absolute_import
22
from unittest import TestCase
33
from ddsc.ddsclient import BaseCommand, UploadCommand, ListCommand, DownloadCommand, ClientCommand, MoveCommand
4-
from ddsc.ddsclient import ShareCommand, DeliverCommand, InfoCommand, read_argument_file_contents
4+
from ddsc.ddsclient import ShareCommand, DeliverCommand, InfoCommand, read_argument_file_contents, \
5+
INVALID_DELIVERY_RECIPIENT_MSG
56
from mock import patch, MagicMock, Mock, call, ANY
67

78

@@ -36,10 +37,13 @@ def test_fetch_project(self, mock_remote_store):
3637
def test_make_user_list(self, mock_remote_store):
3738
mock_config = MagicMock()
3839
base_cmd = BaseCommand(mock_config)
39-
mock_remote_store.return_value.fetch_users.return_value = [
40+
mock_remote_store.return_value.get_or_register_user_by_username.side_effect = [
4041
Mock(username='joe', email='joe@joe.joe'),
4142
Mock(username='bob', email='bob@bob.bob'),
42-
Mock(username='tim', email='tim@tim.tim'),
43+
]
44+
mock_remote_store.return_value.get_or_register_user_by_email.side_effect = [
45+
Mock(username='joe', email='joe@joe.joe'),
46+
ValueError("Invalid")
4347
]
4448

4549
# Find users by username
@@ -48,15 +52,22 @@ def test_make_user_list(self, mock_remote_store):
4852
'bob'
4953
])
5054
self.assertEqual([user.email for user in results], ['joe@joe.joe', 'bob@bob.bob'])
55+
mock_remote_store.return_value.get_or_register_user_by_username.assert_has_calls([
56+
call("joe"),
57+
call("bob")
58+
])
5159

5260
# Find users by email
5361
results = base_cmd.make_user_list(emails=['joe@joe.joe'], usernames=None)
5462
self.assertEqual([user.username for user in results], ['joe'])
63+
mock_remote_store.return_value.get_or_register_user_by_email.assert_has_calls([
64+
call("joe@joe.joe")
65+
])
5566

56-
# Should get an error for invalid emails or usernames
67+
# Should get an error for invalid users
5768
with self.assertRaises(ValueError) as raisedError:
58-
base_cmd.make_user_list(emails=['no@no.no'], usernames=['george'])
59-
self.assertEqual('Unable to find users for the following email/usernames: no@no.no,george',
69+
base_cmd.make_user_list(emails=['no@no.no'], usernames=[])
70+
self.assertEqual('Invalid',
6071
str(raisedError.exception))
6172

6273

@@ -278,6 +289,62 @@ def test_run_message(self, mock_d4s2_project, mock_remote_store):
278289
args, kwargs = mock_remote_store.return_value.fetch_remote_project.call_args
279290
self.assertEqual('456', args[0].get_id_or_raise())
280291

292+
@patch('ddsc.ddsclient.RemoteStore')
293+
@patch('ddsc.ddsclient.D4S2Project')
294+
def test_run_share_users_good(self, mock_d4s2_project, mock_remote_store):
295+
mock_to_user = Mock()
296+
mock_share_user = Mock()
297+
mock_remote_store.return_value.lookup_or_register_user_by_email_or_username.return_value = mock_to_user
298+
mock_remote_store.return_value.get_or_register_user_by_username.return_value = mock_share_user
299+
cmd = DeliverCommand(MagicMock())
300+
cmd.get_new_project_name = Mock()
301+
cmd.get_new_project_name.return_value = 'NewProjectName'
302+
myargs = Mock(project_name='mouse',
303+
project_id=None,
304+
email=None,
305+
resend=False,
306+
username='joe123',
307+
share_usernames=['joe456'],
308+
share_emails=[],
309+
copy_project=True,
310+
include_paths=None,
311+
exclude_paths=None,
312+
msg_file=None)
313+
cmd.run(myargs)
314+
mock_d4s2_project.return_value.deliver.assert_called_with(
315+
mock_remote_store.return_value.fetch_remote_project.return_value,
316+
'NewProjectName',
317+
mock_to_user,
318+
[mock_share_user],
319+
False,
320+
ANY,
321+
''
322+
)
323+
324+
@patch('ddsc.ddsclient.RemoteStore')
325+
@patch('ddsc.ddsclient.D4S2Project')
326+
def test_run_share_users_invalid(self, mock_d4s2_project, mock_remote_store):
327+
mock_remote_user = Mock()
328+
mock_remote_store.return_value.lookup_or_register_user_by_email_or_username.return_value = mock_remote_user
329+
mock_remote_store.return_value.get_or_register_user_by_username.return_value = mock_remote_user
330+
cmd = DeliverCommand(MagicMock())
331+
cmd.get_new_project_name = Mock()
332+
cmd.get_new_project_name.return_value = 'NewProjectName'
333+
myargs = Mock(project_name='mouse',
334+
project_id=None,
335+
email=None,
336+
resend=False,
337+
username='joe123',
338+
share_usernames=['joe123'],
339+
share_emails=[],
340+
copy_project=True,
341+
include_paths=None,
342+
exclude_paths=None,
343+
msg_file=None)
344+
with self.assertRaises(ValueError) as raised_exception:
345+
cmd.run(myargs)
346+
self.assertEqual(str(raised_exception.exception), INVALID_DELIVERY_RECIPIENT_MSG)
347+
281348

282349
class TestDDSClient(TestCase):
283350
def test_read_argument_file_contents(self):

0 commit comments

Comments
 (0)