From 5f42365bb856a8272a27a127e9cd7e6e28971b42 Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Wed, 13 Sep 2023 08:07:18 +0300 Subject: Add `resource_group` function to retrieve the owning group Some resources are "owned" by specific user groups. This commit adds a way to retrieve those "owners" where relevant. --- gn_auth/auth/authorisation/resources/models.py | 21 +++++++++++++++++++-- gn_auth/auth/authorisation/resources/views.py | 20 ++++++++++++-------- 2 files changed, 31 insertions(+), 10 deletions(-) (limited to 'gn_auth/auth/authorisation') diff --git a/gn_auth/auth/authorisation/resources/models.py b/gn_auth/auth/authorisation/resources/models.py index b5a6cd5..93a1aff 100644 --- a/gn_auth/auth/authorisation/resources/models.py +++ b/gn_auth/auth/authorisation/resources/models.py @@ -4,13 +4,13 @@ from uuid import UUID, uuid4 from functools import reduce, partial from typing import Dict, Sequence, Optional +from pymonad.maybe import Just, Maybe, Nothing + from ...db import sqlite3 as db from ...dictify import dictify from ...authentication.users import User from ...db.sqlite3 import with_db_connection -from .checks import authorised_for - from ..checks import authorised_p from ..errors import NotFoundError, AuthorisationError from ..groups.models import ( @@ -383,3 +383,20 @@ def save_resource( raise AuthorisationError( "You do not have the appropriate privileges to edit this resource.") + +def resource_group(conn: db.DbConnection, resource: Resource) -> Maybe[Group]: + """Return the group that owns the resource.""" + with db.cursor(conn) as cursor: + cursor.execute( + "SELECT g.* FROM resource_ownership AS ro " + "INNER JOIN groups AS g ON ro.group_id=g.group_id " + "WHERE ro.resource_id=?", + (str(resource.resource_id),)) + row = cursor.fetchone() + if row: + return Just(Group( + UUID(row["group_id"]), + row["group_name"], + json.loads(row["group_metadata"]))) + + return Nothing diff --git a/gn_auth/auth/authorisation/resources/views.py b/gn_auth/auth/authorisation/resources/views.py index bf7e6f5..3a733c6 100644 --- a/gn_auth/auth/authorisation/resources/views.py +++ b/gn_auth/auth/authorisation/resources/views.py @@ -11,9 +11,9 @@ from ...db.sqlite3 import with_db_connection from .checks import authorised_for from .models import ( - Resource, save_resource, resource_data, resource_by_id, resource_categories, - assign_resource_user, link_data_to_resource, unassign_resource_user, - resource_category_by_id, unlink_data_from_resource, + Resource, save_resource, resource_data, resource_group, resource_by_id, + resource_categories, assign_resource_user, link_data_to_resource, + unassign_resource_user, resource_category_by_id, unlink_data_from_resource, create_resource as _create_resource) from ..roles import Role @@ -154,6 +154,7 @@ def resource_users(resource_id: uuid.UUID): with require_oauth.acquire("profile group resource") as the_token: def __the_users__(conn: db.DbConnection): resource = resource_by_id(conn, the_token.user, resource_id) + rgroup = resource_group(conn, resource).maybe(None, lambda grp: grp) authorised = authorised_for( conn, the_token.user, ("group:resource:edit-resource",), (resource_id,)) @@ -165,7 +166,7 @@ def resource_users(resource_id: uuid.UUID): "user", User(user_id, row["email"], row["name"])) role = GroupRole( uuid.UUID(row["group_role_id"]), - resource.group, + rgroup, Role(uuid.UUID(row["role_id"]), row["role_name"], bool(int(row["user_editable"])), tuple())) return { @@ -218,11 +219,12 @@ def assign_role_to_user(resource_id: uuid.UUID) -> Response: def __assign__(conn: db.DbConnection) -> dict: resource = resource_by_id(conn, the_token.user, resource_id) + rgroup = resource_group(conn, resource).maybe( + None, lambda grp: grp) user = user_by_email(conn, user_email) return assign_resource_user( conn, resource, user, - group_role_by_id(conn, resource.group, - uuid.UUID(group_role_id))) + group_role_by_id(conn, rgroup, uuid.UUID(group_role_id))) except AssertionError as aserr: raise AuthorisationError(aserr.args[0]) from aserr @@ -242,9 +244,11 @@ def unassign_role_to_user(resource_id: uuid.UUID) -> Response: def __assign__(conn: db.DbConnection) -> dict: resource = resource_by_id(conn, the_token.user, resource_id) + rgroup = resource_group(conn, resource).maybe( + None, lambda grp: grp) return unassign_resource_user( conn, resource, user_by_id(conn, uuid.UUID(user_id)), - group_role_by_id(conn, resource.group, + group_role_by_id(conn, rgroup, uuid.UUID(group_role_id))) except AssertionError as aserr: raise AuthorisationError(aserr.args[0]) from aserr @@ -260,7 +264,7 @@ def toggle_public(resource_id: uuid.UUID) -> Response: old_rsc = resource_by_id(conn, the_token.user, resource_id) return save_resource( conn, the_token.user, Resource( - old_rsc.group, old_rsc.resource_id, old_rsc.resource_name, + old_rsc.resource_id, old_rsc.resource_name, old_rsc.resource_category, not old_rsc.public, old_rsc.resource_data)) -- cgit v1.2.3