def test_get_order_bad(): """ Request orders using bad identifiers. All are expected to return 401, 403, or 404 depending on permissions. """ for _ in range(2): responses = make_request_all_roles(f"/api/v1/order/{uuid.uuid4()}") for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 404 elif response.role == "no-login": assert response.code == 401 else: assert response.code == 403 assert not response.data for _ in range(2): responses = make_request_all_roles(f"/api/v1/order/{random_string()}") for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 404 elif response.role == "no-login": assert response.code == 401 else: assert response.code == 403 assert not response.data
def test_get_collection_logs_permissions(mdb): """ Confirm that collection logs can only be accessed by the intended users. Checks: * DATA_MANAGEMENT can access any log. * DATA_EDIT can access entries where they are editors. * User in editors, but not DATA_EDIT cannot access logs. * Other users cannot access logs. """ collections = list(mdb["collections"].aggregate([{ "$sample": { "size": 5 } }])) session = requests.Session() helpers.as_user(session, helpers.USERS["data"]) for collection in collections: response = make_request(session, f'/api/v1/collection/{collection["_id"]}/log', ret_json=True) assert response.code == 200 assert "logs" in response.data coll_id = helpers.add_collection() responses = make_request_all_roles(f"/api/v1/collection/{coll_id}/log", ret_json=True) for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 200 assert "logs" 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 base_user = mdb["users"].find_one({"auth_ids": helpers.USERS["base"]}) mdb["collections"].update_one({"_id": coll_id}, {"$set": { "editors": [base_user["_id"]] }}) for collection in collections: responses = make_request_all_roles( f'/api/v1/collection/{collection["_id"]}/log', ret_json=True) for response in responses: if response.role in ("data", "root"): assert response.code == 200 assert "logs" 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_dataset_update_bad(dataset_for_tests): """Confirm that bad requests will be rejected.""" indata = {"dataset": {"title": "Updated title"}} ds_uuid = helpers.random_string() responses = helpers.make_request_all_roles(f"/api/v1/dataset/{ds_uuid}", method="PATCH", data=indata) for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 404 elif response.role == "no-login": assert response.code == 401 else: assert response.code == 403 assert not response.data ds_uuid = uuid.uuid4().hex responses = helpers.make_request_all_roles(f"/api/v1/dataset/{ds_uuid}", method="PATCH", data=indata) for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 404 elif response.role == "no-login": assert response.code == 401 else: assert response.code == 403 assert not response.data ds_uuid = dataset_for_tests session = requests.Session() helpers.as_user(session, helpers.USERS["data"]) indata = {"title": ""} response = helpers.make_request(session, f"/api/v1/dataset/{ds_uuid}", method="PATCH", data=indata) assert response.code == 400 assert not response.data indata = {"dataset": {"extra": "asd"}} response = helpers.make_request(session, f"/api/v1/dataset/{ds_uuid}", method="PATCH", data=indata) assert response.code == 400 assert not response.data indata = {"dataset": {"timestamp": "asd"}} response = helpers.make_request(session, f"/api/v1/dataset/{ds_uuid}", method="PATCH", data=indata) assert response.code == 400 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_list_oidc_types(): """List supported oidc logins""" responses = helpers.make_request_all_roles("/api/v1/login/oidc", ret_json=True) for response in responses: assert response.code == 200 assert response.data == {"entry": "/api/v1/login/oidc/entry"}
def test_request_no_permissions_required(): """Request target with no permission requirements.""" responses = helpers.make_request_all_roles("/api/v1/developer/hello", ret_json=True) for response in responses: assert response.code == 200 assert response.data == {"test": "success"}
def test_get_dataset_logs_permissions(mdb): """ Get dataset logs. Assert that DATA_MANAGEMENT or user in editors is required. """ dataset_data = mdb["datasets"].aggregate([{"$sample": {"size": 1}}]).next() order_data = mdb["orders"].find_one({"datasets": dataset_data["_id"]}) user_data = mdb["users"].find_one( {"$or": [{ "_id": { "$in": order_data["editors"] } }]}) responses = helpers.make_request_all_roles( f'/api/v1/dataset/{dataset_data["_id"]}/log', ret_json=True) for response in responses: if response.role in ("data", "root"): assert response.code == 200 assert "logs" 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 session = requests.Session() helpers.as_user(session, user_data["auth_ids"][0]) response = helpers.make_request( session, f'/api/v1/dataset/{dataset_data["_id"]}/log', ret_json=True) assert response.code == 200 assert "logs" in response.data
def test_list_current_user_info(): """Retrieve info about the current user.""" responses = make_request_all_roles("/api/v1/user/me", ret_json=True) for response in responses: assert response.code == 200 assert len(response.data["user"]) == 9 if response.role != "no-login": assert response.data["user"][ "name"] == f"{response.role.capitalize()}"
def test_csrf(): """Perform POST, POST and DELETE requests to confirm that CSRF works correctly.""" for method in ("POST", "PATCH", "POST", "DELETE"): responses = helpers.make_request_all_roles( "/api/v1/developer/csrftest", method=method, set_csrf=False, ret_json=True) for response in responses: assert response.code == 400 assert not response.data responses = helpers.make_request_all_roles( "/api/v1/developer/csrftest", method=method, ret_json=True) for response in responses: assert response.code == 200 assert response.data == {"test": "success"}
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_request_permission_data_management(): """Request requiring DATA_MANAGEMENT permissions.""" responses = helpers.make_request_all_roles( "/api/v1/developer/hello/DATA_MANAGEMENT", ret_json=True) for response in responses: if response.role in ("data", "root"): assert response.code == 200 assert response.data == {"test": "success"} else: assert response.code == 403 assert not response.data
def test_request_permission_owners_read(): """Request requiring OWNERS_READ permissions.""" responses = helpers.make_request_all_roles( "/api/v1/developer/hello/OWNERS_READ", ret_json=True) for response in responses: if response.role in ("owners", "data", "root"): assert response.code == 200 assert response.data == {"test": "success"} else: assert response.code == 403 assert not response.data
def test_request_login_required(): """Request target with no permission requirements apart from being logged in.""" responses = helpers.make_request_all_roles("/api/v1/developer/loginhello", ret_json=True) for response in responses: if response.role != "no-login": assert response.code == 200 assert response.data == {"test": "success"} else: assert response.code == 401 assert not response.data
def test_update_user(mdb): """Update the info for a user.""" user_info = mdb["users"].find_one({"auth_ids": USERS["base"]}) indata = {} responses = make_request_all_roles(f'/api/v1/user/{user_info["_id"]}', ret_json=True, method="PATCH", data=indata) for response in responses: if response.role in ("users", "root"): assert response.code == 400 new_user_info = mdb["users"].find_one( {"auth_ids": { "$in": user_info["auth_ids"] }}) assert user_info == new_user_info elif response.role == "no-login": assert response.code == 401 else: assert response.code == 403 assert not response.data indata = { "user": { "affiliation": "Updated University", "name": "Updated name" } } session = requests.session() for user_type in USERS: as_user(session, USERS[user_type]) response = make_request( session, f'/api/v1/user/{user_info["_id"]}', ret_json=True, method="PATCH", data=indata, ) if user_type in ("users", "root"): assert response.code == 200 assert not response.data new_user_info = mdb["users"].find_one( {"auth_ids": user_info["auth_ids"]}) for key in indata["user"]: assert new_user_info[key] == indata["user"][key] mdb["users"].update_one(new_user_info, {"$set": user_info}) elif user_type == "no-login": assert response.code == 401 assert not response.data else: assert response.code == 403 assert not response.data
def test_get_collection_permissions(mdb): """Test permissions for requesting a collection.""" collection = list(mdb["collections"].aggregate([{ "$sample": { "size": 1 } }]))[0] responses = make_request_all_roles( f'/api/v1/collection/{collection["_id"]}', ret_json=True) for response in responses: assert response.code == 200
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_list_all_orders(mdb): """ Confirm that orders are listed correctly. Checks: * DATA_MANAGEMENT lists all orders * DATA_EDIT gets all orders where they are editors * Other users get 403 or 401 * Order should contain id, title, tags, properties """ nr_orders = mdb["orders"].count_documents({}) responses = helpers.make_request_all_roles("/api/v1/order", ret_json=True) for response in responses: if response.role in ("data", "root"): assert response.code == 200 assert len(response.data["orders"]) == nr_orders assert set(response.data["orders"][0].keys()) == { "id", "properties", "tags", "title", } elif response.role == "no-login": assert response.code == 401 assert not response.data elif response.role == "edit": assert response.code == 200 edit_user = mdb["users"].find_one( {"auth_ids": helpers.USERS["edit"]}) edit_orders = mdb["orders"].count_documents( {"editors": edit_user["_id"]}) assert len(response.data["orders"]) == edit_orders else: assert response.code == 403 assert not response.data order_id = next(mdb["orders"].aggregate([{"$sample": {"size": 1}}])) user_info = mdb["users"].find_one({"_id": order_id["editors"][0]}) order_count = mdb["orders"].count_documents({"editors": user_info["_id"]}) session = requests.Session() helpers.as_user(session, user_info["auth_ids"][0]) response = helpers.make_request(session, "/api/v1/order", ret_json=True) assert response.code == 200 assert len(response.data["orders"]) == order_count assert set(response.data["orders"][0].keys()) == { "id", "properties", "tags", "title", }
def test_list_collections(mdb): """Request a list of all collections.""" responses = make_request_all_roles("/api/v1/collection", ret_json=True) for response in responses: assert response.code == 200 assert len(response.data["collections"] ) == mdb["collections"].count_documents({}) assert set(response.data["collections"][0].keys()) == { "id", "title", "tags", "properties", }
def test_list_user_datasets_permissions(): """ Confirm that users get the correct status code response. Tests: * Confirm that non-logged in users get 401, logged in users 200 """ responses = helpers.make_request_all_roles("/api/v1/dataset/user") for response in responses: if response.role == "no-login": assert response.code == 401 else: assert response.code == 200
def test_get_dataset_get_permissions(mdb): """ Confirm that anyone can access any dataset. Tests: * Get random dataset, confirm that everyone can access it """ orders = list(mdb["datasets"].aggregate([{"$sample": {"size": 2}}])) for order in orders: responses = helpers.make_request_all_roles( f'/api/v1/dataset/{order["_id"]}', ret_json=True) for response in responses: assert response.data["dataset"] assert response.code == 200
def test_dataset_update_empty(dataset_for_tests): """Confirm response 400 to an empty update request.""" ds_uuid = dataset_for_tests indata = {} responses = helpers.make_request_all_roles(f"/api/v1/dataset/{ds_uuid}", method="PATCH", data=indata) for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 400 elif response.role == "no-login": assert response.code == 401 else: assert response.code == 403 assert not response.data
def test_list_datasets(mdb): """ Confirm that listing datasets work as intended. Tests: * Confirm all datasets in the database are listed. * Confirm that the correct fields are included """ responses = helpers.make_request_all_roles("/api/v1/dataset", ret_json=True) expected_fields = {"title", "id", "tags", "properties"} for response in responses: assert response.code == 200 assert len( response.data["datasets"]) == mdb["datasets"].count_documents({}) assert set(response.data["datasets"][0].keys()) == expected_fields
def test_list_users(mdb): """ Retrieve list of users. Assert that USER_SEARCH is required. """ responses = make_request_all_roles("/api/v1/user", ret_json=True) for response in responses: if response.role in ("users", "root", "edit"): assert response.code == 200 assert len(response.data["users"]) == mdb["users"].count_documents( {}) elif response.role == "no-login": assert response.code == 401 assert not response.data else: assert response.code == 403 assert not response.data
def test_get_order_logs_permissions(mdb): """ Confirm that only the intended users can access the logs. Checks: * DATA_MANAGEMENT can access logs for any order * DATA_EDIT required to be in editors """ order_data = mdb["orders"].aggregate([{"$sample": {"size": 1}}]).next() edit_user = mdb["users"].find_one({"auth_ids": USERS["edit"]}) # in case the edit user is an editor mdb["orders"].update_one({"_id": order_data["_id"]}, {"$pull": { "editors": edit_user["_id"] }}) responses = helpers.make_request_all_roles( f'/api/v1/order/{order_data["_id"]}/log', ret_json=True) for response in responses: if response.role in ("data", "root"): assert response.code == 200 assert "logs" 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 session = requests.Session() mdb["orders"].update_one({"_id": order_data["_id"]}, {"$push": { "editors": edit_user["_id"] }}) print(mdb["orders"].find_one({"_id": order_data["_id"]})) print(edit_user) helpers.as_user(session, USERS["edit"]) response = make_request(session, f'/api/v1/order/{order_data["_id"]}/log', ret_json=True) assert response.code == 200 assert "logs" in response.data
def test_get_user_actions_access(mdb): """ Get user logs. Assert that USER_MANAGEMENT or actual user is required. """ user_uuid = mdb["users"].find_one({"auth_ids": USERS["base"]}, {"_id": 1})["_id"] responses = make_request_all_roles(f"/api/v1/user/{user_uuid}/actions", ret_json=True) for response in responses: if response.role in ("base", "users", "root"): assert response.code == 200 assert "logs" 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_get_order_permissions(mdb): """ Confirm that only the correct users can access order information. Checks: * DATA_MANAGEMENT can access any order * DATA_EDIT can access orders where they are * Other users cannot access data """ session = requests.Session() orders = list(mdb["orders"].aggregate([{ "$match": { "auth_ids": USER_RE } }, { "$sample": { "size": 2 } }])) for entry in orders: owner = mdb["users"].find_one({"_id": entry["editors"][0]}) responses = helpers.make_request_all_roles( f'/api/v1/entry/{entry["_id"]}', 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 assert not response.data else: assert response.code == 403 assert not response.data helpers.as_user(session, owner["auth_ids"][0]) response = make_request(session, f'/api/v1/entry/{entry["_id"]}') assert response.code == 200
def test_add_collection_permissions(): """ Test permissions for adding a collection. * Any user with ``DATA_EDIT`` can add a collection """ indata = {"collection": {"title": "Test add permissions title"}} indata["collection"].update(TEST_LABEL) responses = make_request_all_roles("/api/v1/collection", 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 assert len(response.data["id"]) == 38 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_order_permissions(): """ Confirm that only the intended users can create orders. Checks: * Only users with DATA_MANAGEMENT or DATA_EDIT can create orders """ indata = {"order": {"title": "Test order add title"}} indata["order"].update(TEST_LABEL) responses = make_request_all_roles("/api/v1/order", 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 assert len(response.data["id"]) == 38 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_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_add_order_bad(): """ Confirm that bad order content is rejected. Checks: * Bad uuid * No "order" field with data * Attempting to set _id * Bad field name * No data """ indata = { "order": { "description": "Test description", "authors": [str(uuid.uuid4())], "title": "Test title", } } indata["order"].update(TEST_LABEL) responses = make_request_all_roles("/api/v1/order", method="POST", 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 else: assert response.code == 403 assert not response.data indata = {"title": "Test title"} indata.update(TEST_LABEL) responses = make_request_all_roles("/api/v1/order", method="POST", 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 else: assert response.code == 403 assert not response.data indata = {"order": {"_id": str(uuid.uuid4()), "title": "Test title"}} indata["order"].update(TEST_LABEL) responses = make_request_all_roles("/api/v1/order", method="POST", data=indata, ret_json=True) for response in responses: if response.role in ("edit", "data", "root"): assert response.code == 403 elif response.role == "no-login": assert response.code == 401 else: assert response.code == 403 assert not response.data indata = {"order": {"made_up_property": [], "title": "Test title"}} indata["order"].update(TEST_LABEL) responses = make_request_all_roles("/api/v1/order", method="POST", 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 else: assert response.code == 403 assert not response.data indata["order"].update(TEST_LABEL) responses = make_request_all_roles("/api/v1/order", method="POST", 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 else: assert response.code == 403 assert not response.data