Skip to content

Commit 065c398

Browse files
authored
Merge pull request #26 from galaxy-genome-annotation/update_email
Improve user update method + add tests
2 parents 39a970b + 2e4e549 commit 065c398

File tree

9 files changed

+208
-14
lines changed

9 files changed

+208
-14
lines changed

README.rst

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ Or with the Arrow client:
8181
History
8282
-------
8383

84+
- 4.2
85+
- Improve user update method
86+
- Add tests for user api
8487
- 4.1
8588
- Fix loading attributes from gff3
8689
- Better handling of genome sequence update, with or without the no_reload_sequences option

apollo/users/__init__.py

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ def delete_user(self, user):
219219
"""
220220
return self.post('deleteUser', {'userToDelete': user})
221221

222-
def update_user(self, email, first_name, last_name, password, metadata={}):
222+
def update_user(self, email, first_name, last_name, password=None, metadata={}, new_email=None):
223223
"""
224224
Update an existing user
225225
@@ -233,21 +233,37 @@ def update_user(self, email, first_name, last_name, password, metadata={}):
233233
:param last_name: User's last name
234234
235235
:type password: str
236-
:param password: User's password
236+
:param password: User's password (omit to keep untouched)
237237
238238
:type metadata: dict
239239
:param metadata: User metadata
240240
241+
:type new_email: str
242+
:param new_email: User's new email (if you want to change it)
243+
241244
:rtype: dict
242245
:return: a dictionary containing user information
243246
"""
244247
data = {
245248
'email': email,
246249
'firstName': first_name,
247250
'lastName': last_name,
248-
'newPassword': password,
249251
'metadata': metadata,
250252
}
253+
254+
if password:
255+
data['newPassword'] = password
256+
257+
# If updating the email, we need to give apollo a userId
258+
if new_email:
259+
user = self.show_user(email)
260+
if not isinstance(user, list):
261+
user = [user]
262+
user = self._assert_user(user)
263+
264+
data['email'] = new_email
265+
data['userId'] = user['userId']
266+
251267
response = self.post('updateUser', data)
252268
return self._handle_empty(email, response)
253269

arrow/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '4.1'
1+
__version__ = '4.2'

arrow/commands/users/update_user.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,29 @@
77
@click.argument("email", type=str)
88
@click.argument("first_name", type=str)
99
@click.argument("last_name", type=str)
10-
@click.argument("password", type=str)
10+
@click.option(
11+
"--password",
12+
help="User's password (omit to keep untouched)",
13+
type=str
14+
)
1115
@click.option(
1216
"--metadata",
1317
help="User metadata",
1418
type=str
1519
)
20+
@click.option(
21+
"--new_email",
22+
help="User's new email (if you want to change it)",
23+
type=str
24+
)
1625
@pass_context
1726
@custom_exception
1827
@dict_output
19-
def cli(ctx, email, first_name, last_name, password, metadata={}):
28+
def cli(ctx, email, first_name, last_name, password="", metadata={}, new_email=""):
2029
"""Update an existing user
2130
2231
Output:
2332
2433
a dictionary containing user information
2534
"""
26-
return ctx.gi.users.update_user(email, first_name, last_name, password, metadata=metadata)
35+
return ctx.gi.users.update_user(email, first_name, last_name, password=password, metadata=metadata, new_email=new_email)

docs/commands/users.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ Update the permissions of a user on a specified organism
271271

272272
**Usage**::
273273

274-
arrow users update_user [OPTIONS] EMAIL FIRST_NAME LAST_NAME PASSWORD
274+
arrow users update_user [OPTIONS] EMAIL FIRST_NAME LAST_NAME
275275

276276
**Help**
277277

@@ -286,6 +286,8 @@ Update an existing user
286286
**Options**::
287287

288288

289-
--metadata TEXT User metadata
290-
-h, --help Show this message and exit.
289+
--password TEXT User's password (omit to keep untouched)
290+
--metadata TEXT User metadata
291+
--new_email TEXT User's new email (if you want to change it)
292+
-h, --help Show this message and exit.
291293

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
requests
22
biopython
3-
cachetools
3+
cachetools<4
44
click>=6.7
55
wrapt
66
pyyaml

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
setup(
1818
name="apollo",
19-
version='4.1',
19+
version='4.2',
2020
description="Apollo API library",
2121
long_description=readme,
2222
author="Helena Rasche;Anthony Bretaudeau",

test/__init__.py

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@ def waitOrgDeleted(self, org_id):
1717
"""
1818

1919
org_info = wa.organisms.show_organism(org_id)
20-
if 'directory' in org_info:
20+
tries = 1
21+
while 'directory' in org_info and tries < 10:
2122
time.sleep(1)
2223
org_info = wa.organisms.show_organism(org_id)
24+
tries += 1
2325

2426
return org_info
2527

@@ -29,8 +31,38 @@ def waitOrgCreated(self, org_id):
2931
"""
3032

3133
org_info = wa.organisms.show_organism(org_id)
32-
if 'directory' not in org_info:
34+
tries = 1
35+
while 'directory' not in org_info and tries < 10:
3336
time.sleep(1)
3437
org_info = wa.organisms.show_organism(org_id)
38+
tries += 1
3539

3640
return org_info
41+
42+
def waitUserDeleted(self, user_id):
43+
"""
44+
Wait for an user to be really deleted from Apollo
45+
"""
46+
47+
user_info = wa.users.show_user(user_id)
48+
tries = 1
49+
while 'userId' in user_info and tries < 10:
50+
time.sleep(1)
51+
user_info = wa.users.show_user(user_id)
52+
tries += 1
53+
54+
return user_info
55+
56+
def waitUserCreated(self, user_id):
57+
"""
58+
Wait for an user to be really created from Apollo
59+
"""
60+
61+
user_info = wa.users.show_user(user_id)
62+
tries = 1
63+
while 'userId' not in user_info and tries < 10:
64+
time.sleep(1)
65+
user_info = wa.users.show_user(user_id)
66+
tries += 1
67+
68+
return user_info

test/user_test.py

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import time
2+
3+
from . import ApolloTestCase, wa
4+
5+
6+
class UserTest(ApolloTestCase):
7+
8+
def test_get_users(self):
9+
10+
users = wa.users.get_users()
11+
12+
# We at least have admin + junior + temp from setup
13+
assert len(users) >= 3
14+
15+
first_user = users[0]
16+
17+
assert 'firstName' in first_user
18+
assert 'lastName' in first_user
19+
assert 'inactive' in first_user
20+
assert 'role' in first_user
21+
assert 'availableGroups' in first_user
22+
assert 'userCount' in first_user
23+
assert 'searchName' in first_user
24+
assert 'groups' in first_user
25+
assert 'userId' in first_user
26+
assert 'organismPermissions' in first_user
27+
assert 'username' in first_user
28+
29+
def test_show_user(self):
30+
31+
users = wa.users.get_users()
32+
33+
user_id = users[0]['userId']
34+
35+
user_info = wa.users.show_user(user_id)
36+
37+
# userCount changes depending on what was requested to Apollo
38+
del user_info['userCount']
39+
del users[0]['userCount']
40+
41+
assert user_info == users[0]
42+
43+
def test_create_user(self):
44+
45+
meta = {"bla": "bli"}
46+
res = wa.users.create_user("trash@bx.psu.edu", 'Poutrelle', 'Lapinou', 'superpassword', role="user", metadata=meta)
47+
self.waitUserCreated(res['userId'])
48+
49+
res = wa.users.show_user('trash@bx.psu.edu')
50+
51+
assert res['username'] == 'trash@bx.psu.edu'
52+
assert res['firstName'] == 'Poutrelle'
53+
assert res['lastName'] == 'Lapinou'
54+
assert res['role'] == 'USER'
55+
56+
def test_delete_user(self):
57+
58+
user_info = wa.users.create_user("trash@bx.psu.edu", 'Tempxx', 'oraryxx', 'coolpasswordxx', role="user")
59+
self.waitUserCreated(user_info['userId'])
60+
61+
wa.users.delete_user(user_info['username'])
62+
self.waitUserDeleted(user_info['userId'])
63+
64+
users = wa.users.get_users()
65+
66+
for user in users:
67+
assert user['username'] != 'trash@bx.psu.edu'
68+
69+
def test_update_user(self):
70+
71+
user_info = wa.users.create_user("trash@bx.psu.edu", 'Tempxx', 'oraryxx', 'coolpasswordxx', role="user")
72+
self.waitUserCreated(user_info['userId'])
73+
74+
wa.users.update_user(user_info['username'], 'firstname2', 'lastname2')
75+
76+
time.sleep(3)
77+
res = wa.users.show_user('trash@bx.psu.edu')
78+
79+
assert res['username'] == 'trash@bx.psu.edu'
80+
assert res['firstName'] == 'firstname2'
81+
assert res['lastName'] == 'lastname2'
82+
assert res['role'] == 'USER'
83+
84+
def test_update_user_email(self):
85+
86+
user_info = wa.users.create_user("trash@bx.psu.edu", 'Tempxx', 'oraryxx', 'coolpasswordxx', role="user")
87+
self.waitUserCreated(user_info['userId'])
88+
89+
wa.users.update_user(user_info['username'], 'firstname2', 'lastname2', new_email='updated@bx.psu.edu')
90+
91+
time.sleep(3)
92+
res = wa.users.show_user('updated@bx.psu.edu')
93+
94+
assert res['username'] == 'updated@bx.psu.edu'
95+
assert res['firstName'] == 'firstname2'
96+
assert res['lastName'] == 'lastname2'
97+
assert res['role'] == 'USER'
98+
99+
def setUp(self):
100+
# Make sure the user is not already there
101+
temp_user_info = wa.users.show_user('test_temp@bx.psu.edu')
102+
if 'username' in temp_user_info:
103+
wa.users.delete_user(temp_user_info['username'])
104+
self.waitUserDeleted(temp_user_info['userId'])
105+
106+
temp_user_info = wa.users.show_user('trash@bx.psu.edu')
107+
if 'username' in temp_user_info:
108+
wa.users.delete_user(temp_user_info['username'])
109+
self.waitUserDeleted(temp_user_info['userId'])
110+
111+
temp_user_info = wa.users.show_user('updated@bx.psu.edu')
112+
if 'username' in temp_user_info:
113+
wa.users.delete_user(temp_user_info['username'])
114+
self.waitUserDeleted(temp_user_info['userId'])
115+
116+
wa.users.create_user("test_temp@bx.psu.edu", 'Temp', 'orary', 'coolpassword', role="user")
117+
118+
def tearDown(self):
119+
temp_user_info = wa.users.show_user('test_temp@bx.psu.edu')
120+
if temp_user_info and 'username' in temp_user_info:
121+
wa.users.delete_user(temp_user_info['username'])
122+
self.waitUserDeleted(temp_user_info['userId'])
123+
124+
temp_user_info = wa.users.show_user('trash@bx.psu.edu')
125+
if 'username' in temp_user_info:
126+
wa.users.delete_user(temp_user_info['username'])
127+
self.waitUserDeleted(temp_user_info['userId'])
128+
129+
temp_user_info = wa.users.show_user('updated@bx.psu.edu')
130+
if 'username' in temp_user_info:
131+
wa.users.delete_user(temp_user_info['username'])
132+
self.waitUserDeleted(temp_user_info['userId'])

0 commit comments

Comments
 (0)