Skip to content

Commit a400eb9

Browse files
committed
Add test for update group endpoint and switch patch/put semantics
1 parent 519881a commit a400eb9

File tree

2 files changed

+68
-50
lines changed

2 files changed

+68
-50
lines changed

pydatalab/src/pydatalab/routes/v0_1/admin.py

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -342,10 +342,22 @@ def create_group():
342342
"description": request_json.get("description"),
343343
"managers": request_json.get("managers"),
344344
}
345+
346+
if group_json["managers"]:
347+
group_json["managers"] = [ObjectId(u) for u in request_json["managers"]]
348+
345349
try:
346350
group = Group(**group_json)
347351
except Exception as e:
348-
return jsonify({"status": "error", "message": f"Invalid group data: {str(e)}"}), 400
352+
raise BadRequest(f"Invalid new group data: {str(e)}")
353+
354+
bad_managers = [
355+
m for m in group_json["managers"] if not flask_mongo.db.users.find_one({"_id": m})
356+
]
357+
if bad_managers:
358+
raise BadRequest(
359+
f"Manager(s) with ID(s) {bad_managers} not found; cannot create group {group_json['group_id']}"
360+
)
349361

350362
try:
351363
group_immutable_id = flask_mongo.db.groups.insert_one(group.dict()).inserted_id
@@ -360,22 +372,19 @@ def create_group():
360372
return jsonify({"status": "error", "message": "Unable to create group."}), 400
361373

362374

363-
@ADMIN.route("/groups", methods=["DELETE"])
364-
def delete_group():
365-
request_json = request.get_json()
366-
367-
group_id = request_json.get("immutable_id")
368-
if group_id is not None:
369-
result = flask_mongo.db.groups.delete_one({"_id": ObjectId(group_id)})
375+
@ADMIN.route("/groups/<group_immutable_id>", methods=["DELETE"])
376+
def delete_group(group_immutable_id: str):
377+
if group_immutable_id is not None:
378+
result = flask_mongo.db.groups.delete_one({"_id": ObjectId(group_immutable_id)})
370379

371380
if result.deleted_count == 1:
372381
return jsonify({"status": "success"}), 200
373382

374383
return jsonify({"status": "error", "message": "Unable to delete group."}), 400
375384

376385

377-
@ADMIN.route("/groups/<group_immutable_id>", methods=["PUT"])
378-
def update_group(group_immutable_id):
386+
@ADMIN.route("/groups/<group_immutable_id>", methods=["PATCH"])
387+
def update_group(group_immutable_id: str):
379388
request_json = request.get_json()
380389

381390
existing_group = flask_mongo.db.groups.find_one({"_id": ObjectId(group_immutable_id)})
@@ -391,7 +400,14 @@ def update_group(group_immutable_id):
391400
update_data["description"] = request_json["description"]
392401

393402
if "managers" in request_json:
394-
update_data["managers"] = request_json["managers"]
403+
update_data["managers"] = [ObjectId(u) for u in request_json["managers"]]
404+
bad_managers = [
405+
m for m in update_data["managers"] if not flask_mongo.db.users.find_one({"_id": m})
406+
]
407+
if bad_managers:
408+
raise BadRequest(
409+
f"Manager(s) with ID(s) {bad_managers} not found; cannot update group {group_immutable_id}"
410+
)
395411

396412
try:
397413
temp_group_data = {**existing_group, **update_data}
@@ -417,8 +433,8 @@ def update_group(group_immutable_id):
417433
return jsonify({"status": "error", "message": f"Failed to update group: {str(e)}"}), 500
418434

419435

420-
@ADMIN.route("/groups/<group_immutable_id>", methods=["PATCH"])
421-
def add_user_to_group(group_immutable_id):
436+
@ADMIN.route("/groups/<group_immutable_id>", methods=["PUT"])
437+
def add_user_to_group(group_immutable_id: str):
422438
request_json = request.get_json()
423439

424440
user_id = request_json.get("user_id")

pydatalab/tests/server/test_users.py

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ def test_get_current_user_unauthenticated(unauthenticated_client):
55
assert resp.status_code == 401
66

77

8-
def test_get_current_user(client, real_mongo_client):
8+
def test_get_current_user(client, database):
99
"""Test that the API key for the demo user has been set correctly."""
1010

1111
resp = client.get("/get-current-user/")
@@ -26,21 +26,21 @@ def test_get_current_user_admin(admin_client):
2626
assert resp_json["role"] == "admin"
2727

2828

29-
def test_role(admin_client, real_mongo_client, user_id):
29+
def test_role(admin_client, database, user_id):
3030
endpoint = f"/roles/{str(user_id)}"
3131
admin_request = {"role": "manager"}
3232
resp = admin_client.patch(endpoint, json=admin_request)
3333
assert resp.status_code == 200
34-
user = real_mongo_client.get_database().roles.find_one({"_id": user_id})
34+
user = database.roles.find_one({"_id": user_id})
3535
assert user["role"] == "manager"
3636

3737

38-
def test_role_update_by_user(client, real_mongo_client, user_id):
38+
def test_role_update_by_user(client, database, user_id):
3939
endpoint = f"/roles/{str(user_id)}"
4040
user_request = {"role": "admin"}
4141
resp = client.patch(endpoint, json=user_request)
4242
assert resp.status_code == 403
43-
user = real_mongo_client.get_database().roles.find_one({"_id": user_id})
43+
user = database.roles.find_one({"_id": user_id})
4444
assert user["role"] == "manager"
4545

4646

@@ -58,20 +58,20 @@ def test_list_groups(admin_client, client):
5858
assert resp.status_code == 403
5959

6060

61-
def test_user_update(client, unauthenticated_client, real_mongo_client, user_id, admin_user_id):
61+
def test_user_update(client, unauthenticated_client, database, user_id, admin_user_id):
6262
endpoint = f"/users/{str(user_id)}"
6363
# Test display name update
6464
user_request = {"display_name": "Test Person II"}
6565
resp = client.patch(endpoint, json=user_request)
6666
assert resp.status_code == 200
67-
user = real_mongo_client.get_database().users.find_one({"_id": user_id})
67+
user = database.users.find_one({"_id": user_id})
6868
assert user["display_name"] == "Test Person II"
6969

7070
# Test contact email update
7171
user_request = {"contact_email": "test2@example.org"}
7272
resp = client.patch(endpoint, json=user_request)
7373
assert resp.status_code == 200
74-
user = real_mongo_client.get_database().users.find_one({"_id": user_id})
74+
user = database.users.find_one({"_id": user_id})
7575
assert user["contact_email"] == "test2@example.org"
7676
assert user["identities"][-1]["identifier"] == "test2@example.org"
7777
assert not user["identities"][-1]["verified"]
@@ -80,48 +80,48 @@ def test_user_update(client, unauthenticated_client, real_mongo_client, user_id,
8080
user_request = {"display_name": None}
8181
resp = client.patch(endpoint, json=user_request)
8282
assert resp.status_code == 200
83-
user = real_mongo_client.get_database().users.find_one({"_id": user_id})
83+
user = database.users.find_one({"_id": user_id})
8484
assert user["display_name"] == "Test Person II"
8585

8686
# Test that contact_email -> None or empty DOES remove email
8787
user_request = {"contact_email": None}
8888
resp = client.patch(endpoint, json=user_request)
8989
assert resp.status_code == 200
90-
user = real_mongo_client.get_database().users.find_one({"_id": user_id})
90+
user = database.users.find_one({"_id": user_id})
9191
assert user["contact_email"] is None
9292

9393
# Check empty string does the same, but reset email first
9494
user_request = {"contact_email": "test2@example.org"}
9595
resp = client.patch(endpoint, json=user_request)
9696
assert resp.status_code == 200
97-
user = real_mongo_client.get_database().users.find_one({"_id": user_id})
97+
user = database.users.find_one({"_id": user_id})
9898
assert user["contact_email"] == "test2@example.org"
9999
user_request = {"contact_email": ""}
100100
resp = client.patch(endpoint, json=user_request)
101101
assert resp.status_code == 200
102-
user = real_mongo_client.get_database().users.find_one({"_id": user_id})
102+
user = database.users.find_one({"_id": user_id})
103103
assert user["contact_email"] is None
104104

105105
# Test bad display name does not update
106106
user_request = {"display_name": " "}
107107
resp = client.patch(endpoint, json=user_request)
108108
assert resp.status_code == 400
109-
user = real_mongo_client.get_database().users.find_one({"_id": user_id})
109+
user = database.users.find_one({"_id": user_id})
110110
assert user["display_name"] == "Test Person II"
111111

112112
# Test bad contact email does not update
113113
user_request = {"contact_email": "not_an_email"}
114114
resp = client.patch(endpoint, json=user_request)
115115
assert resp.status_code == 400
116-
user = real_mongo_client.get_database().users.find_one({"_id": user_id})
116+
user = database.users.find_one({"_id": user_id})
117117
assert user["contact_email"] is None
118118

119119
# Test that user cannot update admin account
120120
endpoint = f"/users/{str(admin_user_id)}"
121121
user_request = {"display_name": "Test Person"}
122122
resp = client.patch(endpoint, json=user_request)
123123
assert resp.status_code == 403
124-
user = real_mongo_client.get_database().users.find_one({"_id": admin_user_id})
124+
user = database.users.find_one({"_id": admin_user_id})
125125
assert user["display_name"] == "Test Admin"
126126

127127
# Test that differing user auth can/cannot search for users
@@ -140,18 +140,18 @@ def test_user_update(client, unauthenticated_client, real_mongo_client, user_id,
140140
assert resp.status_code == 401
141141

142142

143-
def test_user_update_admin(admin_client, real_mongo_client, user_id):
143+
def test_user_update_admin(admin_client, database, user_id):
144144
endpoint = f"/users/{str(user_id)}"
145145
# Test admin override of display name
146146
user_request = {"display_name": "Test Person"}
147147
resp = admin_client.patch(endpoint, json=user_request)
148148
assert resp.status_code == 200
149-
user = real_mongo_client.get_database().users.find_one({"_id": user_id})
149+
user = database.users.find_one({"_id": user_id})
150150
assert user["display_name"] == "Test Person"
151151

152152

153-
def test_create_group(
154-
admin_client, client, unauthenticated_client, real_mongo_client, another_user_id
153+
def test_groups(
154+
admin_client, client, unauthenticated_client, database, admin_id, user_id, another_user_id
155155
):
156156
from bson import ObjectId
157157

@@ -172,7 +172,7 @@ def test_create_group(
172172
resp = admin_client.put("/groups", json=good_group)
173173
assert resp.status_code == 200
174174
group_immutable_id = ObjectId(resp.json["group_immutable_id"])
175-
assert real_mongo_client.get_database().groups.find_one({"_id": group_immutable_id})
175+
assert database.groups.find_one({"_id": group_immutable_id})
176176

177177
# Group ID must be unique
178178
resp = admin_client.put("/groups", json=good_group)
@@ -181,41 +181,43 @@ def test_create_group(
181181
# Request must come from admin
182182
# Make ID unique so that this would otherwise pass
183183
good_group["group_id"] = "my-new-group-2"
184-
resp = unauthenticated_client.put("/groups", json=good_group)
184+
resp = unauthenticated_client.patch("/groups", json=good_group)
185185
assert resp.status_code == 401
186-
assert (
187-
real_mongo_client.get_database().groups.find_one({"group_id": good_group["group_id"]})
188-
is None
189-
)
186+
assert database.groups.find_one({"group_id": good_group["group_id"]}) is None
190187

191188
# Request must come from admin
192189
resp = client.put("/groups", json=good_group)
193190
assert resp.status_code == 403
194-
assert (
195-
real_mongo_client.get_database().groups.find_one({"group_id": good_group["group_id"]})
196-
is None
197-
)
191+
assert database.groups.find_one({"group_id": good_group["group_id"]}) is None
198192

199193
# Check a user can search groups
200194
resp = client.get("/search/groups?query=New")
201195
assert resp.status_code == 200
202196
assert len(resp.json["data"]) == 1
203197

204198
# Check that a user can be added to the group by an admin
205-
resp = admin_client.patch(f"/groups/{group_immutable_id}", json={"user_id": another_user_id})
199+
resp = admin_client.put(f"/groups/{group_immutable_id}", json={"user_id": another_user_id})
206200
assert resp.status_code == 200
207201

208-
user_groups = real_mongo_client.get_database().users.find_one(
209-
{"_id": ObjectId(another_user_id)}
210-
)["groups"]
202+
user_groups = database.users.find_one({"_id": ObjectId(another_user_id)})["groups"]
211203
assert user_groups[1]["immutable_id"] == group_immutable_id
212204
assert len(user_groups) == 2
213205

214206
# Check that repeated addition is idempotent
215-
resp = admin_client.patch(f"/groups/{group_immutable_id}", json={"user_id": another_user_id})
207+
resp = admin_client.put(f"/groups/{group_immutable_id}", json={"user_id": another_user_id})
216208
assert resp.status_code == 304
217209

218-
user_groups = real_mongo_client.get_database().users.find_one(
219-
{"_id": ObjectId(another_user_id)}
220-
)["groups"]
210+
user_groups = database.users.find_one({"_id": ObjectId(another_user_id)})["groups"]
221211
assert len(user_groups) == 2
212+
213+
# Test that an admin can update a group's details/managers
214+
new_details = {
215+
"display_name": "My Newly Named Group",
216+
"group_id": "my-new-group-renamed",
217+
"description": "A group for testing the group update mechanism",
218+
"managers": [admin_id, user_id, another_user_id],
219+
}
220+
221+
resp = admin_client.patch(f"/groups/{group_immutable_id}", json=new_details)
222+
assert resp.status_code == 200
223+
assert database.groups.find_one({"group_id": new_details["group_id"]}) is not None

0 commit comments

Comments
 (0)