From 529165c1fda8b7f88bcc4fff4f227d95c7bf6ba5 Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Mon, 17 Jun 2024 15:41:52 -0500 Subject: Retrieve complete list of a users roles on a particular resource. --- gn_auth/auth/authorisation/resources/views.py | 22 +++++++++++++++++++++- gn_auth/auth/authorisation/roles/models.py | 22 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) (limited to 'gn_auth/auth/authorisation') 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("//users//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: -- cgit v1.2.3