def test_delete_permission(cidc_api, clean_db, monkeypatch): """Check that deleting a permission works as expected.""" gcloud_client = mock_gcloud_client(monkeypatch) current_user_id, other_user_id = setup_permissions(cidc_api, monkeypatch) with cidc_api.app_context(): perm = Permissions.find_for_user(current_user_id)[0] client = cidc_api.test_client() # Non-admins are not allowed to delete gcloud_client.reset_mock() res = client.delete(f"permissions/{perm.id}") assert res.status_code == 401 assert "not authorized to access this endpoint" in res.json["_error"][ "message"] gcloud_client.grant_download_access.assert_not_called() gcloud_client.revoke_download_access.assert_not_called() make_admin(current_user_id, cidc_api) # Requester must supply an If-Match header gcloud_client.reset_mock() res = client.delete(f"permissions/{perm.id}") assert res.status_code == 428 gcloud_client.grant_download_access.assert_not_called() gcloud_client.revoke_download_access.assert_not_called() headers = {"If-Match": "foobar"} # Returns NotFound if no record exists gcloud_client.reset_mock() res = client.delete(f"permissions/1232123", headers=headers) assert res.status_code == 404 gcloud_client.grant_download_access.assert_not_called() gcloud_client.revoke_download_access.assert_not_called() # A mismatched ETag leads to a PreconditionFailed error gcloud_client.reset_mock() res = client.delete(f"permissions/{perm.id}", headers=headers) assert res.status_code == 412 gcloud_client.grant_download_access.assert_not_called() gcloud_client.revoke_download_access.assert_not_called() headers["If-Match"] = perm._etag # A well-formed delete request fails if IAM revoke fails gcloud_client.reset_mock() gcloud_client.revoke_download_access.side_effect = Exception("oops") res = client.delete(f"permissions/{perm.id}", headers=headers) assert "IAM revoke failed" in res.json["_error"]["message"] assert res.status_code == 500 with cidc_api.app_context(): assert Permissions.find_by_id(perm.id) is not None gcloud_client.revoke_download_access.side_effect = None # A matching ETag leads to a successful deletion gcloud_client.reset_mock() res = client.delete(f"permissions/{perm.id}", headers=headers) assert res.status_code == 204 with cidc_api.app_context(): assert Permissions.find_by_id(perm.id) is None gcloud_client.grant_download_access.assert_not_called() gcloud_client.revoke_download_access.assert_called_once()
def test_create_permission(cidc_api, clean_db, monkeypatch): """Check that creating a new permission works as expected.""" gcloud_client = mock_gcloud_client(monkeypatch) current_user_id, other_user_id = setup_permissions(cidc_api, monkeypatch) client = cidc_api.test_client() # Non-admins should be blocked from posting to this endpoint gcloud_client.reset_mocks() res = client.post("permissions") assert res.status_code == 401 assert "not authorized to access this endpoint" in res.json["_error"][ "message"] gcloud_client.grant_download_access.assert_not_called() gcloud_client.revoke_download_access.assert_not_called() make_admin(current_user_id, cidc_api) perm = { "granted_to_user": other_user_id, "trial_id": TRIAL_ID, "upload_type": "ihc", } # When an IAM grant error occurs, the permission db record shouldn't be created gcloud_client.reset_mocks() gcloud_client.grant_download_access.side_effect = Exception("oops") res = client.post("permissions", json=perm) assert "IAM grant failed" in res.json["_error"]["message"] assert res.status_code == 500 with cidc_api.app_context(): assert clean_db.query(Permissions).filter_by(**perm).all() == [] gcloud_client.grant_download_access.side_effect = None # Admins can't create permissions with invalid upload types gcloud_client.reset_mocks() res = client.post("permissions", json={**perm, "upload_type": "foo"}) assert res.status_code == 422 assert "invalid upload type: foo" in res.json["_error"]["message"] # Admins should be able to create new permissions gcloud_client.reset_mocks() res = client.post("permissions", json=perm) assert res.status_code == 201 assert "id" in res.json assert {**res.json, **perm} == res.json with cidc_api.app_context(): assert Permissions.find_by_id(res.json["id"]) gcloud_client.grant_download_access.assert_called_once() gcloud_client.revoke_download_access.assert_not_called() # Re-insertion is not allowed gcloud_client.reset_mocks() res = client.post("permissions", json=perm) assert res.status_code == 400 assert "unique constraint" in res.json["_error"]["message"] gcloud_client.grant_download_access.assert_not_called() gcloud_client.revoke_download_access.assert_not_called() # The permission grantee must exist gcloud_client.reset_mocks() perm["granted_to_user"] = 999999999 # user doesn't exist res = client.post("permissions", json=perm) assert res.status_code == 400 assert "user must exist, but no user found" in res.json["_error"][ "message"] gcloud_client.grant_download_access.assert_not_called() gcloud_client.revoke_download_access.assert_not_called() with cidc_api.app_context(): clean_db.query(Permissions).delete() clean_db.commit() # The permission grantee must have <= GOOGLE_MAX_DOWNLOAD_PERMISSIONS perm["granted_to_user"] = current_user_id inserts_fail_eventually = False upload_types = list(ALL_UPLOAD_TYPES) for i in range(GOOGLE_MAX_DOWNLOAD_PERMISSIONS + 1): gcloud_client.reset_mocks() perm["upload_type"] = upload_types[i] res = client.post("permissions", json=perm) if res.status_code != 201: assert res.status_code == 400 assert ( "greater than or equal to the maximum number of allowed granular permissions" in res.json["_error"]["message"]) gcloud_client.grant_download_access.assert_not_called() gcloud_client.revoke_download_access.assert_not_called() inserts_fail_eventually = True break assert inserts_fail_eventually