diff options
Diffstat (limited to 'gn2/wqflask/oauth2/resources.py')
-rw-r--r-- | gn2/wqflask/oauth2/resources.py | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/gn2/wqflask/oauth2/resources.py b/gn2/wqflask/oauth2/resources.py new file mode 100644 index 00000000..7d20b859 --- /dev/null +++ b/gn2/wqflask/oauth2/resources.py @@ -0,0 +1,294 @@ +import uuid + +from flask import ( + flash, request, jsonify, url_for, redirect, Response, Blueprint) + +from . import client +from .ui import render_ui +from .checks import require_oauth2 +from .client import oauth2_get, oauth2_post +from .request_utils import ( + flash_error, flash_success, request_error, process_error) + +resources = Blueprint("resource", __name__) + +@resources.route("/", methods=["GET"]) +@require_oauth2 +def user_resources(): + """List the resources the user has access to.""" + def __success__(resources): + return render_ui("oauth2/resources.html", resources=resources) + + return oauth2_get("auth/user/resources").either( + request_error, __success__) + +@resources.route("/create", methods=["GET", "POST"]) +@require_oauth2 +def create_resource(): + """Create a new resource.""" + def __render_template__(categories=[], error=None): + return render_ui( + "oauth2/create-resource.html", + resource_categories=categories, + resource_category_error=error, + resource_name=request.args.get("resource_name"), + resource_category=request.args.get("resource_category")) + + if request.method == "GET": + return oauth2_get("auth/resource/categories").either( + lambda error: __render_template__(error=process_error( + error, "Could not retrieve resource categories")), + lambda cats: __render_template__(categories=cats)) + + def __perr__(error): + err = process_error(error) + flash(f"{err['error']}: {err['error_description']}", "alert-danger") + return redirect(url_for( + "oauth2.resource.create_resource", + resource_name=request.form.get("resource_name"), + resource_category=request.form.get("resource_category"))) + def __psuc__(succ): + flash("Resource created successfully", "alert-success") + return redirect(url_for("oauth2.resource.user_resources")) + return oauth2_post( + "auth/resource/create", data=request.form).either( + __perr__, __psuc__) + +def __compute_page__(submit, current_page): + if submit == "next": + return current_page + 1 + return (current_page - 1) or 1 + +@resources.route("/view/<uuid:resource_id>", methods=["GET"]) +@require_oauth2 +def view_resource(resource_id: uuid.UUID): + """View the given resource.""" + page = __compute_page__(request.args.get("submit"), + int(request.args.get("page", "1"), base=10)) + count_per_page = int(request.args.get("count_per_page", "100"), base=10) + def __users_success__( + resource, unlinked_data, users_n_roles, this_user, group_roles, + users): + return render_ui( + "oauth2/view-resource.html", resource=resource, + unlinked_data=unlinked_data, users_n_roles=users_n_roles, + this_user=this_user, group_roles=group_roles, users=users, + page=page, count_per_page=count_per_page) + + def __group_roles_success__( + resource, unlinked_data, users_n_roles, this_user, group_roles): + return oauth2_get("auth/user/list").either( + lambda err: render_ui( + "oauth2/view-resource.html", resource=resource, + unlinked_data=unlinked_data, users_n_roles=users_n_roles, + this_user=this_user, group_roles=group_roles, + users_error=process_error(err)), + lambda users: __users_success__( + resource, unlinked_data, users_n_roles, this_user, group_roles, + users)) + + def __this_user_success__(resource, unlinked_data, users_n_roles, this_user): + return oauth2_get("auth/group/roles").either( + lambda err: render_ui( + "oauth2/view-resources.html", resource=resource, + unlinked_data=unlinked_data, users_n_roles=users_n_roles, + this_user=this_user, group_roles_error=process_error(err)), + lambda groles: __group_roles_success__( + resource, unlinked_data, users_n_roles, this_user, groles)) + + def __users_n_roles_success__(resource, unlinked_data, users_n_roles): + return oauth2_get("auth/user/").either( + lambda err: render_ui( + "oauth2/view-resources.html", + this_user_error=process_error(err)), + lambda usr_dets: __this_user_success__( + resource, unlinked_data, users_n_roles, usr_dets)) + + def __unlinked_success__(resource, unlinked_data): + return oauth2_get(f"auth/resource/{resource_id}/user/list").either( + lambda err: render_ui( + "oauth2/view-resource.html", + resource=resource, + unlinked_data=unlinked_data, + users_n_roles_error=process_error(err), + page=page, + count_per_page=count_per_page), + lambda users_n_roles: __users_n_roles_success__( + resource, unlinked_data, users_n_roles)) + + def __resource_success__(resource): + dataset_type = resource["resource_category"]["resource_category_key"] + return oauth2_get(f"auth/group/{dataset_type}/unlinked-data").either( + lambda err: render_ui( + "oauth2/view-resource.html", resource=resource, + unlinked_error=process_error(err)), + lambda unlinked: __unlinked_success__(resource, unlinked)) + + def __fetch_resource_data__(resource): + """Fetch the resource's data.""" + return client.get( + f"auth/resource/view/{resource['resource_id']}/data?page={page}" + f"&count_per_page={count_per_page}").either( + lambda err: { + **resource, "resource_data_error": process_error(err) + }, + lambda resdata: {**resource, "resource_data": resdata}) + + return oauth2_get(f"auth/resource/view/{resource_id}").map( + __fetch_resource_data__).either( + lambda err: render_ui( + "oauth2/view-resource.html", + resource=None, resource_error=process_error(err)), + __resource_success__) + +@resources.route("/data/link", methods=["POST"]) +@require_oauth2 +def link_data_to_resource(): + """Link group data to a resource""" + form = request.form + try: + assert "resource_id" in form, "Resource ID not provided." + assert "data_link_id" in form, "Data Link ID not provided." + assert "dataset_type" in form, "Dataset type not specified" + assert form["dataset_type"].lower() in ( + "mrna", "genotype", "phenotype"), "Invalid dataset type provided." + resource_id = form["resource_id"] + + def __error__(error): + err = process_error(error) + flash(f"{err['error']}: {err['error_description']}", "alert-danger") + return redirect(url_for( + "oauth2.resource.view_resource", resource_id=resource_id)) + + def __success__(success): + flash(f"Data linked to resource successfully", "alert-success") + return redirect(url_for( + "oauth2.resource.view_resource", resource_id=resource_id)) + return oauth2_post("auth/resource/data/link", data=dict(form)).either( + __error__, + __success__) + except AssertionError as aserr: + flash(aserr.args[0], "alert-danger") + return redirect(url_for( + "oauth2.resource.view_resource", resource_id=form["resource_id"])) + +@resources.route("/data/unlink", methods=["POST"]) +@require_oauth2 +def unlink_data_from_resource(): + """Unlink group data from a resource""" + form = request.form + try: + assert "resource_id" in form, "Resource ID not provided." + assert "data_link_id" in form, "Data Link ID not provided." + resource_id = form["resource_id"] + + def __error__(error): + err = process_error(error) + flash(f"{err['error']}: {err['error_description']}", "alert-danger") + return redirect(url_for( + "oauth2.resource.view_resource", resource_id=resource_id)) + + def __success__(success): + flash(f"Data unlinked from resource successfully", "alert-success") + return redirect(url_for( + "oauth2.resource.view_resource", resource_id=resource_id)) + return oauth2_post( + "auth/resource/data/unlink", data=dict(form)).either( + __error__, __success__) + except AssertionError as aserr: + flash(aserr.args[0], "alert-danger") + return redirect(url_for( + "oauth2.resource.view_resource", resource_id=form["resource_id"])) + +@resources.route("<uuid:resource_id>/user/assign", methods=["POST"]) +@require_oauth2 +def assign_role(resource_id: uuid.UUID) -> Response: + form = request.form + group_role_id = form.get("group_role_id", "") + user_email = form.get("user_email", "") + try: + assert bool(group_role_id), "The role must be provided." + assert bool(user_email), "The user email must be provided." + + def __assign_error__(error): + err = process_error(error) + flash(f"{err['error']}: {err['error_description']}", "alert-danger") + return redirect(url_for( + "oauth2.resource.view_resource", resource_id=resource_id)) + + def __assign_success__(success): + flash(success["description"], "alert-success") + return redirect(url_for( + "oauth2.resource.view_resource", resource_id=resource_id)) + + return oauth2_post( + f"auth/resource/{resource_id}/user/assign", + data={ + "group_role_id": group_role_id, + "user_email": user_email + }).either(__assign_error__, __assign_success__) + except AssertionError as aserr: + flash(aserr.args[0], "alert-danger") + return redirect(url_for("oauth2.resources.view_resource", resource_id=resource_id)) + +@resources.route("<uuid:resource_id>/user/unassign", methods=["POST"]) +@require_oauth2 +def unassign_role(resource_id: uuid.UUID) -> Response: + form = request.form + group_role_id = form.get("group_role_id", "") + user_id = form.get("user_id", "") + try: + assert bool(group_role_id), "The role must be provided." + assert bool(user_id), "The user id must be provided." + + def __unassign_error__(error): + err = process_error(error) + flash(f"{err['error']}: {err['error_description']}", "alert-danger") + return redirect(url_for( + "oauth2.resource.view_resource", resource_id=resource_id)) + + def __unassign_success__(success): + flash(success["description"], "alert-success") + return redirect(url_for( + "oauth2.resource.view_resource", resource_id=resource_id)) + + return oauth2_post( + f"auth/resource/{resource_id}/user/unassign", + data={ + "group_role_id": group_role_id, + "user_id": user_id + }).either(__unassign_error__, __unassign_success__) + except AssertionError as aserr: + flash(aserr.args[0], "alert-danger") + return redirect(url_for("oauth2.resources.view_resource", resource_id=resource_id)) + +@resources.route("/toggle/<uuid:resource_id>", methods=["POST"]) +@require_oauth2 +def toggle_public(resource_id: uuid.UUID): + """Toggle the given resource's public status.""" + def __handle_error__(err): + flash_error(process_error(err)) + return redirect(url_for( + "oauth2.resource.view_resource", resource_id=resource_id)) + + def __handle_success__(success): + flash_success(success) + return redirect(url_for( + "oauth2.resource.view_resource", resource_id=resource_id)) + + return oauth2_post( + f"auth/resource/{resource_id}/toggle-public", data={}).either( + lambda err: __handle_error__(err), + lambda suc: __handle_success__(suc)) + +@resources.route("/edit/<uuid:resource_id>", methods=["GET"]) +@require_oauth2 +def edit_resource(resource_id: uuid.UUID): + """Edit the given resource.""" + return "WOULD Edit THE GIVEN RESOURCE'S DETAILS" + +@resources.route("/delete/<uuid:resource_id>", methods=["GET"]) +@require_oauth2 +def delete_resource(resource_id: uuid.UUID): + """Delete the given resource.""" + return "WOULD DELETE THE GIVEN RESOURCE" |