about summary refs log tree commit diff
path: root/gn_auth/auth/authorisation/resources/views.py
diff options
context:
space:
mode:
Diffstat (limited to 'gn_auth/auth/authorisation/resources/views.py')
-rw-r--r--gn_auth/auth/authorisation/resources/views.py80
1 files changed, 64 insertions, 16 deletions
diff --git a/gn_auth/auth/authorisation/resources/views.py b/gn_auth/auth/authorisation/resources/views.py
index e4401c5..f114476 100644
--- a/gn_auth/auth/authorisation/resources/views.py
+++ b/gn_auth/auth/authorisation/resources/views.py
@@ -1,9 +1,10 @@
 """The views/routes for the resources package"""
-from uuid import UUID, uuid4
+import time
 import json
+import logging
 import operator
 import sqlite3
-import time
+from uuid import UUID, uuid4
 
 from dataclasses import asdict
 from functools import reduce
@@ -13,6 +14,7 @@ from authlib.jose import jwt
 from authlib.integrations.flask_oauth2.errors import _HTTPException
 from flask import (make_response, request, jsonify, Response,
                    Blueprint, current_app as app)
+import gn_libs.privileges.resources
 
 from gn_auth.auth.requests import request_json
 
@@ -39,12 +41,11 @@ from gn_auth.auth.authorisation.roles.models import (
 from gn_auth.auth.authentication.oauth2.resource_server import require_oauth
 from gn_auth.auth.authentication.users import User, user_by_id, user_by_email
 
-from .system.models import system_resource
-
 from .inbredset.views import popbp
 from .genotypes.views import genobp
 from .phenotypes.views import phenobp
 from .errors import MissingGroupError
+from .system.models import system_resource
 from .groups.models import Group, user_group
 from .checks import can_delete, authorised_for
 from .models import (
@@ -52,7 +53,10 @@ from .models import (
     resource_categories, assign_resource_user, link_data_to_resource,
     unassign_resource_user, resource_category_by_id, user_roles_on_resources,
     unlink_data_from_resource, create_resource as _create_resource,
-    get_resource_id, delete_resource as _delete_resource)
+    get_resource_id, delete_resource as _delete_resource,
+    edit_resource as _edit_resource)
+
+logger = logging.getLogger(__name__)
 
 resources = Blueprint("resources", __name__)
 resources.register_blueprint(popbp, url_prefix="/")
@@ -97,8 +101,7 @@ def create_resource() -> Response:
                                       "resources.resource_name"):
                     raise InconsistencyError(
                         "You cannot have duplicate resource names.") from sql3ie
-                app.logger.debug(
-                    f"{type(sql3ie)=}: {sql3ie=}")
+                logger.debug("type(sql3ie)=%s: sql3ie=%s", type(sql3ie), sql3ie)
                 raise
 
 
@@ -116,6 +119,49 @@ def view_resource(resource_id: UUID) -> Response:
                 )
             )
 
+
+@resources.route("/<uuid:resource_id>/edit", methods=["POST"])
+@require_oauth("profile group resource")
+def edit_resource(resource_id: UUID) -> Response:
+    """Update/edit basic details regarding a resource."""
+    db_uri = app.config["AUTH_DB"]
+    with (require_oauth.acquire("profile group resource") as _token,
+          db.connection(db_uri) as conn):
+        def __extract_privileges__(roles: tuple[Role, ...]) -> tuple[str, ...]:
+            return tuple(
+                priv.privilege_id for role in roles
+                for priv in role.privileges)
+
+        _sys_resource = system_resource(conn)
+        _privileges = {
+            ("system_privileges"
+             if _rid == _sys_resource.resource_id
+             else "resource_privileges"): __extract_privileges__(_rroles)
+            for _rid, _rroles in user_roles_on_resources(
+                conn,
+                _token.user,
+                (resource_id, _sys_resource.resource_id)
+            ).items()
+        }
+        if not gn_libs.privileges.resources.can_edit(**_privileges):
+            return make_response(jsonify({
+                "error": "AuthorisationError",
+                "error_description": "You are not allowed to edit this resource."
+            }), 401)
+
+        name = (request_json().get("resource_name") or "").strip()
+        if bool(name):
+            return jsonify({
+                "resource": asdict(_edit_resource(conn, resource_id, name)),
+                "message": "Resource updated successfully",
+                "status": "success"
+            })
+
+        return make_response(jsonify({
+            "error_description": "Expected `resource_name` to be provided.",
+            "error": "InvalidInput"
+        }), 400)
+
 def __safe_get_requests_page__(key: str = "page") -> int:
     """Get the results page if it exists or default to the first page."""
     try:
@@ -234,9 +280,11 @@ def resource_users(resource_id: UUID):
                             **users_n_roles,
                             user_id: {
                                 "user": user,
-                                "user_group": Group(
-                                    UUID(row["group_id"]), row["group_name"],
-                                    json.loads(row["group_metadata"])),
+                                "user_group": (
+                                    Group(UUID(row["group_id"]),
+                                          row["group_name"],
+                                          json.loads(row["group_metadata"]))
+                                    if bool(row["group_id"]) else False) ,
                                 "roles": users_n_roles.get(
                                     user_id, {}).get("roles", tuple()) + (role,)
                             }
@@ -244,7 +292,7 @@ def resource_users(resource_id: UUID):
                     cursor.execute(
                         "SELECT g.*, u.*, r.* "
                         "FROM groups AS g INNER JOIN group_users AS gu "
-                        "ON g.group_id=gu.group_id INNER JOIN users AS u "
+                        "ON g.group_id=gu.group_id RIGHT JOIN users AS u "
                         "ON gu.user_id=u.user_id INNER JOIN user_roles AS ur "
                         "ON u.user_id=ur.user_id INNER JOIN roles AS r "
                         "ON ur.role_id=r.role_id "
@@ -257,7 +305,8 @@ def resource_users(resource_id: UUID):
         results = (
             {
                 "user": asdict(row["user"]),
-                "user_group": asdict(row["user_group"]),
+                "user_group": (
+                    asdict(row["user_group"]) if row["user_group"] else False),
                 "roles": tuple(asdict(role) for role in row["roles"])
             } for row in (
                 user_row for user_id, user_row
@@ -470,7 +519,7 @@ def resources_authorisation():
         })
         resp.status_code = 400
     except Exception as _exc:#pylint: disable=[broad-except]
-        app.logger.debug("Generic exception.", exc_info=True)
+        logger.debug("Generic exception.", exc_info=True)
         resp = jsonify({
             "status": "general-exception",
             "error_description": (
@@ -508,7 +557,6 @@ def get_user_roles_on_resource(name) -> Response:
         response = make_response({
             # Flatten this list
             "roles": roles,
-            "silly": "ausah",
         })
         iat = int(time.time())
         jose_header = {
@@ -707,13 +755,13 @@ def delete_resource():
                 "description": f"Successfully deleted resource with ID '{resource_id}'."
             })
         except ValueError as _verr:
-            app.logger.debug("Error!", exc_info=True)
+            logger.debug("Error!", exc_info=True)
             return jsonify({
                 "error": "ValueError",
                 "error-description": "An invalid identifier was provided"
             }), 400
         except TypeError as _terr:
-            app.logger.debug("Error!", exc_info=True)
+            logger.debug("Error!", exc_info=True)
             return jsonify({
                 "error": "TypeError",
                 "error-description": "An invalid identifier was provided"