def test_delete_call_not_successful(app, public_bucket_indexd_client): """ Test fence.blueprints.data.indexd.IndexedFile delete_files fails """ class MockResponse: """ Mock Response from requests lib """ def __init__(self, data, status_code=200): """ Setup Mock Response """ self.data = data self.status_code = status_code def json(self): """ Mock json() call """ return self.data with patch("fence.blueprints.data.indexd.flask.current_app", return_value=app): with patch( "fence.resources.user.user_session.UserSession.create_initial_token" ): with patch( "fence.blueprints.data.indexd.requests.delete", return_value=MockResponse(data=None, status_code=503), ): indexed_file = IndexedFile(file_id="some id") assert indexed_file.delete()
def delete_data_file(file_id): """ Delete all the locations for a data file which was uploaded to bucket storage from indexd. If the data file is still at the first stage where it belongs to just the uploader (and isn't linked to a project), then the deleting user should match the uploader field on the record in indexd. Otherwise, the user must have delete permissions in the project. Args: file_id (str): GUID of file to delete """ record = IndexedFile(file_id) # check auth: user must have uploaded the file (so `uploader` field on the record is # this user) uploader = record.index_document.get("uploader") if not uploader: raise Forbidden("deleting submitted records is not supported") if current_token["context"]["user"]["name"] != uploader: raise Forbidden("user is not uploader for file {}".format(file_id)) logger.info("deleting record and files for {}".format(file_id)) record.delete_files(delete_all=True) return record.delete()
def delete_data_file(file_id): """ Delete all the locations for a data file which was uploaded to bucket storage from indexd. If the data file has authz matching the user's permissions, delete it. If the data file has no authz, then the deleting user should match the uploader field on the record in indexd. Args: file_id (str): GUID of file to delete """ record = IndexedFile(file_id) authz = record.index_document.get("authz") has_correct_authz = None if authz: logger.debug( "Trying to ask arborist if user can delete in fence for {}".format(authz) ) has_correct_authz = flask.current_app.arborist.auth_request( jwt=get_jwt(), service="fence", methods="delete", resources=authz ) # If authz is not empty, use *only* arborist to check if user can delete # Don't fall back on uploader -- this prevents users from escalating from edit to # delete permissions by changing the uploader field to their own username # (b/c users only have edit access through arborist/authz) if has_correct_authz: logger.info("Deleting record and files for {}".format(file_id)) message, status_code = record.delete_files(delete_all=True) if str(status_code)[0] != "2": return flask.jsonify({"message": message}), status_code try: return record.delete() except Exception as e: logger.error(e) return ( flask.jsonify( {"message": "There was an error deleting this index record."} ), 500, ) else: return ( flask.jsonify( { "message": "You do not have arborist permissions to delete this file." } ), 403, ) # If authz is empty: use uploader == user to see if user can delete. uploader_mismatch_error_message = "You cannot delete this file because the uploader field indicates it does not belong to you." uploader = record.index_document.get("uploader") if not uploader: return ( flask.jsonify({"message": uploader_mismatch_error_message}), 403, ) if current_token["context"]["user"]["name"] != uploader: return ( flask.jsonify({"message": uploader_mismatch_error_message}), 403, ) logger.info("deleting record and files for {}".format(file_id)) message, status_code = record.delete_files(delete_all=True) if str(status_code)[0] != "2": return flask.jsonify({"message": message}), status_code try: return record.delete() except Exception as e: logger.error(e) return ( flask.jsonify( {"message": "There was an error deleting this index record."} ), 500, )