def test_delete_order_permissions(mdb): """ Confirm that permissions for deleting order are correct. Checks: * DATA_MANAGER can delete any order * DATA_EDIT can delete orders where they are editors * Other users cannot delete any order, even if they are editors """ order_id = helpers.add_order() session = requests.Session() for role in helpers.USERS: helpers.as_user(session, USERS[role]) response = helpers.make_request(session, f"/api/v1/order/{order_id}", method="DELETE", ret_json=True) if role in ("edit", "data", "root"): assert response.code == 200 order_id = helpers.add_order() elif role == "no-login": assert response.code == 401 else: assert response.code == 403 assert not response.data edit_user = mdb["users"].find_one({"auth_ids": USERS["edit"]}) mdb["orders"].update_one({"_id": order_id}, {"$pull": { "editors": edit_user["_id"] }}) helpers.as_user(session, USERS["edit"]) response = helpers.make_request(session, f"/api/v1/order/{order_id}", method="DELETE", ret_json=True) assert response.code == 403 assert not response.data base_user = mdb["users"].find_one({"auth_ids": USERS["base"]}) mdb["orders"].update_one({"_id": order_id}, {"$push": { "editors": base_user["_id"] }}) helpers.as_user(session, USERS["base"]) response = helpers.make_request(session, f"/api/v1/order/{order_id}", method="DELETE", ret_json=True) assert response.code == 403 assert not response.data
def test_prepare_order_response(mdb): """ Confirm that the order is prepared the intended way. Checks: """ order_id = helpers.add_order() dataset_id = helpers.add_dataset(order_id) order_data = mdb["orders"].find_one({"_id": order_id}) user_fields = { "_id": 1, "affiliation": 1, "contact": 1, "name": 1, "orcid": 1, "url": 1, } edit_user = mdb["users"].find_one({"auth_ids": helpers.USERS["edit"]}, projection=user_fields) edit_user["_id"] = str(edit_user["_id"]) order.prepare_order_response(order_data, mdb) for field in ("editors", "authors", "generators"): assert order_data[field] == [edit_user] assert order_data["datasets"] == [{ "title": "Test title from fixture", "_id": dataset_id }] assert order_data["organisation"] == edit_user
def test_get_dataset(mdb): """ Confirm that datasets are returned correctly. Tests: * Confirm that the correct dataset is returned * Confirm that the dataset is not listed in ``related`` """ session = requests.Session() order_id = helpers.add_order() ds_id = helpers.add_dataset(order_id) ds_id2 = helpers.add_dataset(order_id) coll_id = helpers.add_collection([ds_id]) coll_id2 = helpers.add_collection([ds_id]) helpers.as_user(session, helpers.USERS["edit"]) order_data = mdb["orders"].find_one({"_id": order_id}) response = helpers.make_request(session, f"/api/v1/dataset/{ds_id}") assert response.code == 200 result = response.data["dataset"] assert result["order"]["id"] == str(order_id) assert set(entry["id"] for entry in result["related"]) == {str(ds_id2)} assert set(entry["id"] for entry in result["collections"]) == { str(coll_id), str(coll_id2) } assert set(entry["id"] for entry in result["authors"]) == set( str(entry) for entry in order_data["authors"]) assert set(entry["id"] for entry in result["generators"]) == set( str(entry) for entry in order_data["generators"]) assert result["organisation"]["id"] == str(order_data["organisation"]) assert set(entry["id"] for entry in result["editors"]) == set( str(entry) for entry in order_data["editors"]) helpers.as_user(session, helpers.USERS["base"]) order_data = mdb["orders"].find_one({"_id": order_id}) response = helpers.make_request(session, f"/api/v1/dataset/{ds_id}") assert response.code == 200 result = response.data["dataset"] assert "order" not in result assert set(entry["id"] for entry in result["related"]) == {str(ds_id2)} assert set(entry["id"] for entry in result["collections"]) == { str(coll_id), str(coll_id2) } assert set(entry["id"] for entry in result["authors"]) == set( str(entry) for entry in order_data["authors"]) assert set(entry["id"] for entry in result["generators"]) == set( str(entry) for entry in order_data["generators"]) assert result["organisation"]["id"] == str(order_data["organisation"]) assert "editors" not in result mdb["orders"].delete_one({"_id": order_id}) mdb["datasets"].delete_one({"_id": ds_id}) mdb["datasets"].delete_one({"_id": ds_id2}) mdb["collections"].delete_one({"_id": coll_id}) mdb["collections"].delete_one({"_id": coll_id2})
def test_add_order(self, mocked_get_user, mocked_get_product): mocked_get_user.return_value = "Fizi Yadav" user = mocked_get_user() self.assertEqual(user, "Fizi Yadav") mocked_get_product.return_value = ("Paleo Box", 10.0) product, price = mocked_get_product() with self.app.application.app_context(): order_id = add_order("xyz123", user, "paleo-box", product, price) self.assertEqual(order_id, 1)
def test_add_dataset_data(mdb): """ Confirm that values are set correctly and logs are created. Checks: * All values can be set correctly * Dataset is added correctly to the order * Description is escaped """ order_id = helpers.add_order() indata = { "dataset": { "title": "New add dataset data title", "description": "<br />", "tags": ["testing", "add_dataset"], } } indata["dataset"].update(TEST_LABEL) session = requests.session() helpers.as_user(session, USERS["data"]) response = helpers.make_request( session, f"/api/v1/order/{order_id}/dataset", method="POST", data=indata, ret_json=True, ) assert response.code == 200 assert "id" in response.data assert len(response.data["id"]) == 38 order_info = mdb["orders"].find_one({"_id": order_id}) assert len(order_info["datasets"]) == 1 added_ds = mdb["datasets"].find_one({"_id": response.data["id"]}) for key in indata["dataset"]: if key == "description": assert added_ds[key] == "<br />" else: assert added_ds[key] == indata["dataset"][key] response = helpers.make_request( session, f"/api/v1/order/{order_id}/dataset", method="POST", data=indata, ret_json=True, ) assert response.code == 200 assert "id" in response.data assert len(response.data["id"]) == 38 order_info = mdb["orders"].find_one({"_id": order_id}) assert len(order_info["datasets"]) == 2
def test_dataset_update_permissions(mdb): """ Confirm that permissions for updating datasets are correct. Checks: * DATA_MANAGER can update any dataset * DATA_EDIT can update datasets where they are editors (in the order) * Other users cannot update any dataset, even if they are editors """ session = requests.Session() order_id = helpers.add_order() ds_id = helpers.add_dataset(order_id) indata = {"dataset": {"title": "Updated dataset permissions title"}} responses = helpers.make_request_all_roles(f"/api/v1/dataset/{ds_id}", method="PATCH", data=indata) for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 200 elif response.role == "no-login": assert response.code == 401 else: assert response.code == 403 assert not response.data indata = {"dataset": {"title": "Updated dataset permissions title 2"}} edit_user = mdb["users"].find_one({"auth_ids": helpers.USERS["edit"]}) mdb["orders"].update_one({"_id": order_id}, {"$pull": { "editors": edit_user["_id"] }}) helpers.as_user(session, helpers.USERS["edit"]) response = helpers.make_request(session, f"/api/v1/dataset/{ds_id}", method="PATCH", data=indata) assert response.code == 403 assert not response.data base_user = mdb["users"].find_one({"auth_ids": helpers.USERS["base"]}) mdb["orders"].update_one({"_id": order_id}, {"$push": { "editors": base_user["_id"] }}) helpers.as_user(session, helpers.USERS["base"]) response = helpers.make_request(session, f"/api/v1/dataset/{ds_id}", method="PATCH", data=indata) assert response.code == 403 assert not response.data
def test_add_dataset_permissions(mdb): """ Confirm that permissions for adding datasets are correct. Checks: * DATA_MANAGEMENT can add datasets to any order * DATA_EDIT can add datasets to orders where they are editors * No other users can add datasets """ order_id = helpers.add_order() indata = {"dataset": {"title": "New add dataset permissions title"}} indata["dataset"].update(TEST_LABEL) responses = helpers.make_request_all_roles( f"/api/v1/order/{order_id}/dataset", method="POST", data=indata, ret_json=True) for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 200 assert "id" in response.data elif response.role == "no-login": assert response.code == 401 assert not response.data else: assert response.code == 403 assert not response.data edit_user = mdb["users"].find_one({"auth_ids": USERS["edit"]}) mdb["orders"].update_one({"_id": order_id}, {"$pull": { "editors": edit_user["_id"] }}) responses = helpers.make_request_all_roles( f"/api/v1/order/{order_id}/dataset", method="POST", data=indata, ret_json=True) for response in responses: if response.role in ("data", "root"): assert response.code == 200 assert "id" in response.data elif response.role == "no-login": assert response.code == 401 assert not response.data else: assert response.code == 403 assert not response.data
def test_add_dataset_log(mdb): """ Confirm that logs are added correctly when datasets are added. Checks: * An add log is created for the dataset * An edit log is created for the order """ order_id = helpers.add_order() indata = { "dataset": { "title": "New add dataset log title", "description": "<br />", "tags": ["testing", "add_dataset"], } } indata["dataset"].update(TEST_LABEL) session = requests.session() helpers.as_user(session, USERS["data"]) response = helpers.make_request( session, f"/api/v1/order/{order_id}/dataset", method="POST", data=indata, ret_json=True, ) assert response.code == 200 assert "id" in response.data ds_add_log_count = mdb["logs"].count_documents({ "data_type": "dataset", "data._id": response.data["id"], "action": "add", }) assert ds_add_log_count == 1 order_edit_log_count = mdb["logs"].count_documents({ "data_type": "order", "data._id": order_id, "action": "edit" }) assert order_edit_log_count == 1
def edit_order(order_id): error = None order_details, filters_dict = helpers.get_orderlist(session, **{"order_id": order_id}) if request.method == "POST": form = CreateOrder_Form(request.form) error = helpers.add_order(form, session["name"], "Edit") flash("Order Successfully Edited.") return redirect(url_for("dashboard.main")) return render_template( "edit_order.html", order_list=order_details, CreateOrder_Form=CreateOrder_Form(request.form), username=session["name"], error=error, search_form=SearchForm(request.form), )
def create_order(): error = None if request.method == "POST": form = CreateOrder_Form(request.form) error = helpers.add_order(form, session["name"], "New") if error: error = "Order ID already exists." else: flash("Order Successfully Created.") return redirect(url_for("dashboard.main")) return render_template( "create_order.html", CreateOrder_Form=CreateOrder_Form(request.form), username=session["name"], error=error, search_form=SearchForm(request.form), )
def test_update_order_permissions(mdb): """ Confirm orders can only be modified by the indented users. Checks: * Order be edited by DATA_MANAGEMENT * Order be edited by DATA_EDIT if user is in editors * Order cannot be edited by DATA_EDIT if user is in editors * Other users cannot edit order """ order_id = helpers.add_order() edit_user = mdb["users"].find_one({"auth_ids": USERS["edit"]}) indata = {"order": {"title": "Test update order title"}} responses = helpers.make_request_all_roles(f"/api/v1/order/{order_id}", method="PATCH", data=indata, ret_json=True) for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 200 elif response.role == "no-login": assert response.code == 401 else: assert response.code == 403 assert not response.data mdb["orders"].update_one({"_id": order_id}, {"$pull": { "editors": edit_user["_id"] }}) responses = helpers.make_request_all_roles(f"/api/v1/order/{order_id}", method="PATCH", data=indata, ret_json=True) for response in responses: if response.role in ("data", "root"): assert response.code == 200 elif response.role == "no-login": assert response.code == 401 else: assert response.code == 403 assert not response.data
def test_dataset_update_data(mdb): """ Confirm that the dataset is updated correctly. Tests: * All fields are correctly updated * Confirm that description is escaped * Confirm that a log entry is created """ session = requests.Session() ds_id = helpers.add_dataset(helpers.add_order()) indata = { "dataset": { "description": "<br />", "title": "Test title - dataset update data", } } indata["dataset"].update(TEST_LABEL) helpers.as_user(session, helpers.USERS["data"]) response = helpers.make_request(session, f"/api/v1/dataset/{ds_id}", method="PATCH", data=indata) assert response.code == 200 assert not response.data dataset = mdb["datasets"].find_one({"_id": ds_id}) assert dataset["title"] == indata["dataset"]["title"] assert dataset["description"] == "<br />" assert mdb["logs"].find_one({ "data._id": ds_id, "action": "edit", "data_type": "dataset" })
def test_delete_order_data(mdb): """ Confirm that order deletion works as intended. Checks: * Entry is deleted - A delete log is created for the order * Related datasets are deleted - A delete log is created for each dataset * References to datasets from collections are deleted - An edit log is created for each collection with removed datasets """ session = requests.Session() helpers.as_user(session, helpers.USERS["data"]) order_id = helpers.add_order() ds_ids = [helpers.add_dataset(order_id) for _ in range(5)] extra_ds_ids = [ ds["_id"] for ds in mdb["datasets"].aggregate([{ "$sample": { "size": 2 } }]) ] collection_id = helpers.add_collection(ds_ids + extra_ds_ids) response = helpers.make_request(session, f"/api/v1/order/{order_id}", method="DELETE", ret_json=True) assert response.code == 200 assert not response.data assert (mdb["logs"].count_documents({ "data_type": "order", "action": "delete", "data._id": order_id }) == 1) assert not mdb["datasets"].find_one({"_id": ds_ids}) assert mdb["logs"].count_documents({ "data_type": "dataset", "action": "delete", "data._id": { "$in": ds_ids } }) == len(ds_ids) coll_data = mdb["collections"].find_one({"_id": collection_id}) for ds_id in ds_ids: assert ds_id not in coll_data["datasets"] assert mdb["logs"].find_one({ "data_type": "collection", "action": "edit", "data._id": collection_id }) # clean up added orders for entry in mdb["orders"].find(TEST_LABEL): response = helpers.make_request(session, f'/api/v1/order/{entry["_id"]}', method="DELETE") assert response.code == 200 assert not mdb["orders"].find_one({"_id": entry["_id"]}) assert not mdb["datasets"].find_one( {"_id": { "$in": entry["datasets"] }}) assert not mdb["collections"].find_one( {"datasets": { "$in": entry["datasets"] }})
def test_update_order_bad(mdb): """ Confirm that bad data is rejected. Checks: * Bad uuid * No uuid list (only str) * No "orders" property with data * Bad order uuid * Bad order string * No data """ order_id = helpers.add_order() edit_user = mdb["users"].find_one({"auth_ids": USERS["edit"]}) indata = { "orders": { "description": "Test description", "authors": [str(uuid.uuid4())], "title": "Test title", } } responses = make_request_all_roles(f"/api/v1/order/{order_id}", method="PATCH", data=indata, ret_json=True) for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 400 elif response.role == "no-login": assert response.code == 401 assert not response.data else: assert response.code == 403 assert not response.data indata = { "description": "Test description", "editors": [str(edit_user["_id"])], "title": "Test title", } responses = make_request_all_roles(f"/api/v1/order/{order_id}", method="PATCH", data=indata, ret_json=True) for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 400 elif response.role == "no-login": assert response.code == 401 assert not response.data else: assert response.code == 403 assert not response.data indata = {"order": {"title": "Test title"}} responses = make_request_all_roles(f"/api/v1/order/{uuid.uuid4()}", method="PATCH", data=indata, ret_json=True) for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 404 elif response.role == "no-login": assert response.code == 401 assert not response.data else: assert response.code == 403 assert not response.data indata = {"order": {"title": "Test title"}} responses = make_request_all_roles( f"/api/v1/order/{helpers.random_string()}", method="PATCH", data=indata, ret_json=True, ) for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 404 elif response.role == "no-login": assert response.code == 401 assert not response.data else: assert response.code == 403 assert not response.data responses = make_request_all_roles( f"/api/v1/order/{order_id}", method="PATCH", ret_json=True, ) for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 400 elif response.role == "no-login": assert response.code == 401 assert not response.data else: assert response.code == 403 assert not response.data
def test_update_order_data(mdb): """ Confirm that data is updated correctly. Checks: * All fields are correctly updated * Confirm that description is escaped * DATA_MANAGEMENT can remove themselves from editors * DATA_EDIT cannot remove themselves from editors * Confirm that a log entry is created """ root_user = mdb["users"].find_one({"auth_ids": USERS["root"]}) session = requests.Session() for test_user in ("edit", "data"): order_id = helpers.add_order() current_user = mdb["users"].find_one({"auth_ids": USERS[test_user]}) helpers.as_user(session, USERS[test_user]) indata = { "order": { "description": "<br />", "authors": [str(root_user["_id"])], "editors": [str(current_user["_id"]), str(root_user["_id"])], "generators": [str(root_user["_id"])], "organisation": str(root_user["_id"]), "title": "Test update order title", "tags": ["testing", "updated"], } } indata["order"].update(TEST_LABEL) response = helpers.make_request( session, f"/api/v1/order/{order_id}", method="PATCH", data=indata, ret_json=True, ) # to make comparisons shorter indata = indata["order"] assert response.code == 200 assert not response.data order = mdb["orders"].find_one({"_id": order_id}) user_list = [root_user["_id"]] assert order["title"] == indata["title"] # confirm that description is escaped assert order["description"] == "<br />" for field in ("authors", "generators"): assert order[field] == user_list assert order["editors"] == [current_user["_id"]] + user_list assert order["organisation"] == root_user["_id"] indata = { "order": { "editors": [str(root_user["_id"])], } } response = helpers.make_request( session, f"/api/v1/order/{order_id}", method="PATCH", data=indata, ret_json=True, ) log_count = 1 if test_user == "edit": assert response.code == 400 elif test_user == "data": assert response.code == 200 log_count = 2 assert (len( list(mdb["logs"].find({ "data._id": order_id, "action": "edit", "data_type": "order", "user": current_user["_id"], }))) == log_count)
def test_delete_dataset(mdb): """ Confirm that datasets are deleted correctly. Tests: * Check that datasets are deleted correctly * Check that references to the dataset are deleted in orders and collections * Check that logs are created correctly """ session = requests.Session() order_id = helpers.add_order() ds_id = helpers.add_dataset(order_id) coll_id = helpers.add_collection([ds_id]) coll_id2 = helpers.add_collection([ds_id]) helpers.as_user(session, helpers.USERS["edit"]) response = helpers.make_request(session, f"/api/v1/dataset/{ds_id}", method="DELETE") assert response.code == 200 assert not mdb["datasets"].find_one({"_id": ds_id}) assert (mdb["logs"].count_documents({ "data_type": "dataset", "action": "delete", "data._id": ds_id }) == 1) assert not mdb["orders"].find_one({"datasets": ds_id}) assert (mdb["logs"].count_documents({ "data_type": "order", "comment": "Dataset deleted", "action": "edit", "data._id": order_id, }) == 1) assert not mdb["collections"].find_one({"datasets": ds_id}) assert (mdb["logs"].count_documents({ "data_type": "collection", "comment": "Dataset deleted", "action": "edit", "data._id": { "$in": (coll_id, coll_id2) }, }) == 2) # clean up added datasets for ds in mdb["datasets"].find(TEST_LABEL): response = helpers.make_request(session, f'/api/v1/dataset/{ds["_id"]}', method="DELETE") if response.code == 200: assert not mdb["datasets"].find_one({"_id": ds["_id"]}) assert not mdb["orders"].find_one({"datasets": ds["_id"]}) assert not mdb["collections"].find_one({"datasets": ds["_id"]}) helpers.as_user(session, helpers.USERS["data"]) # clean up added datasets for ds in mdb["datasets"].find(TEST_LABEL): response = helpers.make_request(session, f'/api/v1/dataset/{ds["_id"]}', method="DELETE") assert response.code == 200 assert not mdb["datasets"].find_one({"_id": ds["_id"]}) assert not mdb["orders"].find_one({"datasets": ds["_id"]}) assert not mdb["collections"].find_one({"datasets": ds["_id"]})
def test_add_dataset_bad_fields(): """ Confirm that bad inputs to add_dataset are handled gracefully. Checks: * Empty input * No {"datasets": {}} * Try to set _id * Empty title * No title * Bad field name * No data * Non-json data """ order_id = helpers.add_order() session = requests.Session() helpers.as_user(session, helpers.USERS["data"]) indata = {} response = make_request(session, f"/api/v1/order/{order_id}/dataset", method="POST", data=indata) assert response.code == 400 assert not response.data indata = {"title": "Bad add title"} response = make_request(session, f"/api/v1/order/{order_id}/dataset", method="POST", data=indata) assert response.code == 400 assert not response.data indata = {"dataset": {"_id": str(uuid.uuid4()), "title": "Bad add title"}} response = make_request(session, f"/api/v1/order/{order_id}/dataset", method="POST", data=indata) assert response.code == 403 assert not response.data indata = {"dataset": {"title": ""}} response = make_request(session, f"/api/v1/order/{order_id}/dataset", method="POST", data=indata) assert response.code == 400 assert not response.data indata = {"dataset": {"description": "Bad add description"}} response = make_request(session, f"/api/v1/order/{order_id}/dataset", method="POST", data=indata) assert response.code == 400 assert not response.data indata = {"dataset": {"title": "Bad add title", "bad_field": "asd"}} response = make_request(session, f"/api/v1/order/{order_id}/dataset", method="POST", data=indata) assert response.code == 400 assert not response.data response = make_request(session, f"/api/v1/order/{order_id}/dataset", method="POST") assert response.code == 400 assert not response.data indata = "hegg" response = session.post( f"{helpers.BASE_URL}/api/v1/order/{order_id}/dataset", data=indata, headers={"Content-Type": "application/json"}, ) assert response.status_code == 400 assert not response.text