about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gn3/auth/authorisation/groups/models.py42
-rw-r--r--gn3/auth/authorisation/groups/views.py20
2 files changed, 60 insertions, 2 deletions
diff --git a/gn3/auth/authorisation/groups/models.py b/gn3/auth/authorisation/groups/models.py
index 2a6f840..777e2d0 100644
--- a/gn3/auth/authorisation/groups/models.py
+++ b/gn3/auth/authorisation/groups/models.py
@@ -1,6 +1,7 @@
 """Handle the management of resource/user groups."""
 import json
 from uuid import UUID, uuid4
+from functools import reduce
 from typing import Any, Sequence, Iterable, Optional, NamedTuple
 
 from flask import g
@@ -301,3 +302,44 @@ def accept_reject_join_request(
             raise AuthorisationError(
                 "You cannot act on other groups join requests")
         raise NotFoundError(f"Could not find request with ID '{request_id}'")
+
+def __organise_privileges__(acc, row):
+    role_id = UUID(row["role_id"])
+    role = acc.get(role_id, False)
+    if role:
+        return {
+            **acc,
+            role_id: Role(role.role_id, role.role_name, role.privileges + (
+                Privilege(row["privilege_id"], row["privilege_description"]),))
+        }
+    return {
+        **acc,
+        role_id: Role(UUID(row["role_id"]), row["role_name"], (
+            Privilege(row["privilege_id"], row["privilege_description"]),))
+    }
+
+# @authorised_p(("group:role:view",),
+#               "Insufficient privileges to view role",
+#               oauth2_scope="profile group role")
+def group_role_by_id(
+        conn: db.DbConnection, group: Group, group_role_id: UUID) -> GroupRole:
+    """Retrieve GroupRole from id by its `group_role_id`."""
+    ## TODO: do privileges check before running actual query
+    ##       the check commented out above doesn't work correctly
+    with db.cursor(conn) as cursor:
+        cursor.execute(
+            "SELECT gr.group_role_id, r.*, p.* "
+            "FROM group_roles AS gr "
+            "INNER JOIN roles AS r ON gr.role_id=r.role_id "
+            "INNER JOIN role_privileges AS rp ON rp.role_id=r.role_id "
+            "INNER JOIN privileges AS p ON p.privilege_id=rp.privilege_id "
+            "WHERE gr.group_role_id=? AND gr.group_id=?",
+            (str(group_role_id), str(group.group_id)))
+        rows = cursor.fetchall()
+        if rows:
+            roles: tuple[Role,...] = tuple(reduce(
+                __organise_privileges__, rows, {}).values())
+            assert len(roles) == 1
+            return GroupRole(group_role_id, group, roles[0])
+        raise NotFoundError(
+            f"Group role with ID '{group_role_id}' does not exist.")
diff --git a/gn3/auth/authorisation/groups/views.py b/gn3/auth/authorisation/groups/views.py
index 4da6781..8b7adef 100644
--- a/gn3/auth/authorisation/groups/views.py
+++ b/gn3/auth/authorisation/groups/views.py
@@ -15,8 +15,9 @@ from gn3.auth.db_utils import with_db_connection
 from .data import link_data_to_group, retrieve_ungrouped_data
 from .models import (
     user_group, all_groups, DUMMY_GROUP, GroupRole, group_by_id, join_requests,
-    GroupCreationError, accept_reject_join_request, group_users as _group_users,
-    create_group as _create_group, create_group_role as _create_group_role)
+    group_role_by_id, GroupCreationError, accept_reject_join_request,
+    group_users as _group_users, create_group as _create_group,
+    create_group_role as _create_group_role)
 
 from ..roles.models import Role
 from ..checks import authorised_p
@@ -302,3 +303,18 @@ def create_group_role():
             return _create_group_role(conn, group, role_name, privileges)
 
         return jsonify(with_db_connection(__create__))
+
+@groups.route("/role/<uuid:group_role_id>", methods=["GET"])
+def view_group_role(group_role_id: uuid.UUID):
+    """Return the details of the given role."""
+    with require_oauth.acquire("profile group role") as the_token:
+        def __group_role__(conn: db.DbConnection) -> GroupRole:
+            with db.cursor(conn) as cursor:
+                group = user_group(cursor, the_token.user).maybe(#type: ignore[misc]
+                    DUMMY_GROUP, lambda grp: grp)
+
+            if group == DUMMY_GROUP:
+                raise AuthorisationError(
+                    "A user without a group cannot view group roles.")
+            return group_role_by_id(conn, group, group_role_id)
+        return jsonify(dictify(with_db_connection(__group_role__)))