Source code for collection

"""Collection requests."""
import flask

import structure
import user
import utils

blueprint = flask.Blueprint("collection", __name__)  # pylint: disable=invalid-name


[docs]@blueprint.route("", methods=["GET"]) def list_collection(): """Provide a simplified list of all available collections.""" results = list( flask.g.db["collections"].find( projection={"title": 1, "_id": 1, "tags": 1, "properties": 1} ) ) return utils.response_json({"collections": results})
[docs]@blueprint.route("/<identifier>", methods=["GET"]) def get_collection(identifier): """ Retrieve the collection with uuid <identifier>. Args: identifier (str): uuid for the wanted collection Returns: flask.Request: json structure for the collection """ entry = utils.req_get_entry("collections", identifier) if not entry: flask.abort(status=404) # only show editors if owner/admin if not flask.g.current_user or ( not utils.req_has_permission("DATA_MANAGEMENT") and flask.g.current_user["_id"] not in entry["editors"] ): flask.current_app.logger.debug( "Not allowed to access editors field %s", flask.g.current_user ) del entry["editors"] else: entry["editors"] = utils.user_uuid_data(entry["editors"], flask.g.db) # return {_id, _title} for datasets entry["datasets"] = [ flask.g.db.datasets.find_one({"_id": dataset}, {"title": 1}) for dataset in entry["datasets"] ] return utils.response_json({"collection": entry})
[docs]@blueprint.route("", methods=["POST"]) @user.login_required def add_collection(): """ Add a collection. Returns: flask.Response: Json structure with the ``_id`` of the collection. """ perm_status = utils.req_check_permissions(["DATA_EDIT"]) if perm_status != 200: flask.abort(status=perm_status) # create new collection collection = structure.collection() jsondata = flask.request.json if not jsondata or "collection" not in jsondata or not isinstance(jsondata["collection"], dict): flask.abort(status=400) indata = jsondata["collection"] # indata validation validation = utils.basic_check_indata(indata, collection, prohibited=["_id"]) if not validation.result: flask.abort(status=validation.status) if not indata.get("editors"): indata["editors"] = [flask.g.current_user["_id"]] # add current user if missing and only DATA_EDIT elif ( not utils.req_has_permission("DATA_MANAGEMENT") and str(flask.g.current_user["_id"]) not in indata["editors"] ): indata["editors"].append(flask.g.current_user["_id"]) # convert all incoming uuids to uuid.UUID indata = utils.prepare_for_db(indata) # convert entries to uuids for field in ("datasets", "editors"): if field in indata: indata[field] = [utils.str_to_uuid(value) for value in indata[field]] collection.update(indata) # add to db result = utils.req_commit_to_db("collections", "add", collection) if not result.log or not result.data: flask.abort(status=500) return utils.response_json({"_id": result.ins_id})
[docs]@blueprint.route("/<identifier>", methods=["DELETE"]) @user.login_required def delete_collection(identifier: str): """ Delete a collection. Can be deleted only by an owner or user with DATA_MANAGEMENT permissions. Args: identifier (str): The collection uuid. """ perm_status = utils.req_check_permissions(["DATA_EDIT"]) if perm_status != 200: flask.abort(status=perm_status) entry = utils.req_get_entry("collections", identifier) if not entry: flask.abort(status=404) # permission check if ( not utils.req_has_permission("DATA_MANAGEMENT") and flask.g.current_user["_id"] not in entry["editors"] ): flask.abort(status=403) result = utils.req_commit_to_db("collections", "delete", {"_id": entry["_id"]}) if not result.log or not result.data: flask.abort(status=500) return flask.Response(status=200)
[docs]@blueprint.route("/<identifier>", methods=["PATCH"]) @user.login_required def update_collection(identifier): """ Update a collection. Args: identifier (str): The collection uuid. Returns: flask.Response: Status code. """ perm_status = utils.req_check_permissions(["DATA_EDIT"]) if perm_status != 200: flask.abort(status=perm_status) collection = utils.req_get_entry("collections", identifier) if not collection: flask.abort(status=404) jsondata = flask.request.json if not jsondata or "collection" not in jsondata or not isinstance(jsondata["collection"], dict): flask.abort(status=400) indata = jsondata["collection"] # permission check if ( not utils.req_has_permission("DATA_MANAGEMENT") and flask.g.current_user["_id"] not in collection["editors"] ): flask.current_app.logger.debug( "Unauthorized update attempt (collection %s, user %s)", collection["_id"], flask.g.current_user["_id"], ) flask.abort(status=403) # indata validation validation = utils.basic_check_indata(indata, collection, prohibited=["_id"]) if not validation.result: flask.abort(status=validation.status) # DATA_EDIT may not delete itself from editors if ( not utils.req_has_permission("DATA_MANAGEMENT") and indata.get("editors") and str(flask.g.current_user["_id"]) not in indata["editors"] ): flask.abort(status=400) # convert all incoming uuids to uuid.UUID indata = utils.prepare_for_db(indata) # convert entries to uuids for field in ("datasets", "editors"): if field in indata: indata[field] = [utils.str_to_uuid(value) for value in indata[field]] is_different = False for field in indata: if indata[field] != collection[field]: is_different = True break if indata and is_different: collection.update(indata) result = utils.req_commit_to_db("collections", "edit", collection) if not result.log or not result.data: flask.abort(status=500) return flask.Response(status=200)
[docs]@blueprint.route("/<identifier>/log", methods=["GET"]) @user.login_required def get_collection_log(identifier: str = None): """ Get change logs for the collection matching ``identifier``. Can be accessed by editors (with DATA_EDIT) and admin (DATA_MANAGEMENT). Deleted entries cannot be accessed. Args: identifier (str): The uuid of the collection. Returns: flask.Response: Logs as json. """ perm_status = utils.req_check_permissions(["DATA_EDIT"]) if perm_status != 200: flask.abort(status=perm_status) collection = utils.req_get_entry("collections", identifier) if not collection: flask.abort(status=404) if ( not utils.req_has_permission("DATA_MANAGEMENT") and flask.g.current_user["_id"] not in collection["editors"] ): flask.abort(403) collection_logs = list( flask.g.db["logs"].find({"data_type": "collection", "data._id": collection["_id"]}) ) for log in collection_logs: del log["data_type"] utils.incremental_logs(collection_logs) return utils.response_json( { "entry_id": collection["_id"], "data_type": "collection", "logs": collection_logs, } )