about summary refs log tree commit diff
path: root/gn_auth
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2024-06-17 15:41:52 -0500
committerFrederick Muriuki Muriithi2024-06-17 15:41:52 -0500
commit529165c1fda8b7f88bcc4fff4f227d95c7bf6ba5 (patch)
tree10cb33d85570a19011c3f75f75be98a3934802b6 /gn_auth
parentb472424eca8ae14e154c41cee2a4ecd9d0810334 (diff)
downloadgn-auth-529165c1fda8b7f88bcc4fff4f227d95c7bf6ba5.tar.gz
Retrieve complete list of a users roles on a particular resource.
Diffstat (limited to 'gn_auth')
-rw-r--r--gn_auth/auth/authorisation/resources/views.py22
-rw-r--r--gn_auth/auth/authorisation/roles/models.py22
2 files changed, 43 insertions, 1 deletions
diff --git a/gn_auth/auth/authorisation/resources/views.py b/gn_auth/auth/authorisation/resources/views.py
index 0849466..07439a0 100644
--- a/gn_auth/auth/authorisation/resources/views.py
+++ b/gn_auth/auth/authorisation/resources/views.py
@@ -18,7 +18,9 @@ from gn_auth.auth.db import sqlite3 as db
 from gn_auth.auth.db.sqlite3 import with_db_connection
 
 from gn_auth.auth.authorisation.roles import Role
-from gn_auth.auth.authorisation.roles.models import create_role
+from gn_auth.auth.authorisation.roles.models import (
+    create_role,
+    user_resource_roles as _user_resource_roles)
 from gn_auth.auth.errors import (
     InvalidData,
     InconsistencyError,
@@ -609,3 +611,21 @@ def create_resource_role(resource_id: UUID):
             })
 
     return jsonify(asdict(role))
+
+@resources.route("/<uuid:resource_id>/users/<uuid:user_id>/roles", methods=["GET"])
+@require_oauth("profile group resource role")
+def user_resource_roles(resource_id: UUID, user_id: UUID):
+    """Get a specific user's roles on a particular resource."""
+    with (require_oauth.acquire("profile group resource") as _token,
+          db.connection(app.config["AUTH_DB"]) as conn,
+          db.cursor(conn) as cursor):
+        if _token.user.user_id != user_id:
+            raise AuthorisationError(
+                "You are not authorised to view the roles this user has.")
+
+        _resource = resource_by_id(conn, _token.user, resource_id)
+        if not bool(_resource):
+            raise BadRequest("No resource was found with the given ID.")
+
+        return jsonify([asdict(role) for role in
+                        _user_resource_roles(conn, _token.user, _resource)])
diff --git a/gn_auth/auth/authorisation/roles/models.py b/gn_auth/auth/authorisation/roles/models.py
index f0e9745..03f88d7 100644
--- a/gn_auth/auth/authorisation/roles/models.py
+++ b/gn_auth/auth/authorisation/roles/models.py
@@ -7,6 +7,7 @@ from typing import Sequence, Iterable, Optional
 from pymonad.either import Left, Right, Either
 
 from gn_auth.auth.errors import NotFoundError, AuthorisationError
+from gn_auth.auth.authorisation.resources.base import Resource
 
 from ...db import sqlite3 as db
 from ...authentication.users import User
@@ -131,6 +132,27 @@ def user_roles(conn: db.DbConnection, user: User) -> Sequence[dict]:
             __organise_privileges__, cursor.fetchall(), {}).values())
     return tuple()
 
+
+def user_resource_roles(
+        conn: db.DbConnection,
+        user: User,
+        resource: Resource
+) -> tuple[Role]:
+    """Retrieve all roles assigned to a user for a particular resource."""
+    with db.cursor(conn) as cursor:
+        cursor.execute(
+            "SELECT ur.resource_id, ur.user_id, r.*, p.* "
+            "FROM user_roles AS ur "
+            "INNER JOIN roles AS r ON ur.role_id=r.role_id "
+            "INNER JOIN role_privileges AS rp ON r.role_id=rp.role_id "
+            "INNER JOIN privileges AS p ON rp.privilege_id=p.privilege_id "
+            "WHERE ur.user_id=? AND ur.resource_id=?",
+            (str(user.user_id), str(resource.resource_id)))
+
+        return db_rows_to_roles(cursor.fetchall())
+    return tuple()
+
+
 def user_role(conn: db.DbConnection, user: User, role_id: UUID) -> Either:
     """Retrieve a specific non-resource role assigned to the user."""
     with db.cursor(conn) as cursor: