about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2025-07-29 13:20:24 -0500
committerFrederick Muriuki Muriithi2025-07-29 13:21:56 -0500
commit4346b93c3f0b86860383e91a3df0e440e0f3066b (patch)
tree874da7685cbe4da5dc28ce7e6c98b8b4f0b9237a
parentbfd8cefaa3e68f77c84eaf577b206377bf7fc4d5 (diff)
downloadgn-auth-4346b93c3f0b86860383e91a3df0e440e0f3066b.tar.gz
Grant sysadmins access to the resource when created.
-rw-r--r--gn_auth/auth/authorisation/resources/common.py23
-rw-r--r--gn_auth/auth/authorisation/resources/models.py54
-rw-r--r--gn_auth/auth/authorisation/resources/views.py3
3 files changed, 53 insertions, 27 deletions
diff --git a/gn_auth/auth/authorisation/resources/common.py b/gn_auth/auth/authorisation/resources/common.py
index 5d2b72b..1842982 100644
--- a/gn_auth/auth/authorisation/resources/common.py
+++ b/gn_auth/auth/authorisation/resources/common.py
@@ -22,3 +22,26 @@ def assign_resource_owner_role(
         "ON CONFLICT (user_id, role_id, resource_id) DO NOTHING",
         params)
     return params
+
+
+def grant_access_to_sysadmins(
+        cursor: Cursor,
+        resource_id: uuid.UUID,
+        system_resource_id: uuid.UUID
+):
+    """Grant sysadmins access to resource identified by `resource_id`."""
+    cursor.execute(
+        "SELECT role_id FROM roles WHERE role_name='system-administrator'")
+    sysadminroleid = cursor.fetchone()[0]
+
+    cursor.execute(# Fetch sysadmin IDs.
+        "SELECT user_roles.user_id FROM roles INNER JOIN user_roles "
+        "ON roles.role_id=user_roles.role_id "
+        "WHERE role_name='system-administrator' AND resource_id=?",
+        (str(system_resource_id),))
+
+    cursor.executemany(
+        "INSERT INTO user_roles(user_id, role_id, resource_id) "
+        "VALUES (?, ?, ?)",
+        tuple((row["user_id"], sysadminroleid, str(resource_id))
+              for row in cursor.fetchall()))
diff --git a/gn_auth/auth/authorisation/resources/models.py b/gn_auth/auth/authorisation/resources/models.py
index 5feb916..16f0359 100644
--- a/gn_auth/auth/authorisation/resources/models.py
+++ b/gn_auth/auth/authorisation/resources/models.py
@@ -15,9 +15,10 @@ from gn_auth.auth.authorisation.privileges import Privilege
 from gn_auth.auth.authorisation.checks import authorised_p
 from gn_auth.auth.errors import NotFoundError, AuthorisationError
 
+from .system.models import system_resource
 from .checks import authorised_for, authorised_for_spec
 from .base import Resource, ResourceCategory, resource_from_dbrow
-from .common import assign_resource_owner_role
+from .common import assign_resource_owner_role, grant_access_to_sysadmins
 from .groups.models import Group, is_group_leader
 from .mrna import (
     resource_data as mrna_resource_data,
@@ -40,7 +41,7 @@ from .phenotypes.models import (
               error_description="Insufficient privileges to create a resource",
               oauth2_scope="profile resource")
 def create_resource(# pylint: disable=[too-many-arguments, too-many-positional-arguments]
-        cursor: sqlite3.Cursor,
+        conn: db.DbConnection,
         resource_name: str,
         resource_category: ResourceCategory,
         user: User,
@@ -48,29 +49,32 @@ def create_resource(# pylint: disable=[too-many-arguments, too-many-positional-a
         public: bool
 ) -> Resource:
     """Create a resource item."""
-    resource = Resource(uuid4(), resource_name, resource_category, public)
-    cursor.execute(
-        "INSERT INTO resources VALUES (?, ?, ?, ?)",
-        (str(resource.resource_id),
-         resource_name,
-         str(resource.resource_category.resource_category_id),
-         1 if resource.public else 0))
-    # TODO: @fredmanglis,@rookie101
-    # 1. Move the actions below into a (the?) hooks system
-    # 2. Do more checks: A resource can have varying hooks depending on type
-    #    e.g. if mRNA, pheno or geno resource, assign:
-    #           - "resource-owner"
-    #         if inbredset-group, assign:
-    #           - "resource-owner",
-    #           - "inbredset-group-owner" etc.
-    #         if resource is of type "group", assign:
-    #           - group-leader
-    cursor.execute("INSERT INTO resource_ownership (group_id, resource_id) "
-                   "VALUES (?, ?)",
-                   (str(group.group_id), str(resource.resource_id)))
-    assign_resource_owner_role(cursor, resource.resource_id, user.user_id)
-
-    return resource
+    with db.cursor(conn) as cursor:
+        resource = Resource(uuid4(), resource_name, resource_category, public)
+        cursor.execute(
+            "INSERT INTO resources VALUES (?, ?, ?, ?)",
+            (str(resource.resource_id),
+             resource_name,
+             str(resource.resource_category.resource_category_id),
+             1 if resource.public else 0))
+        # TODO: @fredmanglis,@rookie101
+        # 1. Move the actions below into a (the?) hooks system
+        # 2. Do more checks: A resource can have varying hooks depending on type
+        #    e.g. if mRNA, pheno or geno resource, assign:
+        #           - "resource-owner"
+        #         if inbredset-group, assign:
+        #           - "resource-owner",
+        #           - "inbredset-group-owner" etc.
+        #         if resource is of type "group", assign:
+        #           - group-leader
+        cursor.execute("INSERT INTO resource_ownership (group_id, resource_id) "
+                       "VALUES (?, ?)",
+                       (str(group.group_id), str(resource.resource_id)))
+        assign_resource_owner_role(cursor, resource.resource_id, user.user_id)
+        grant_access_to_sysadmins(
+            cursor, resource.resource_id, system_resource(conn).resource_id)
+
+        return resource
 
 
 def delete_resource(conn: db.DbConnection, resource_id: UUID):
diff --git a/gn_auth/auth/authorisation/resources/views.py b/gn_auth/auth/authorisation/resources/views.py
index 02d2b76..cee3d6c 100644
--- a/gn_auth/auth/authorisation/resources/views.py
+++ b/gn_auth/auth/authorisation/resources/views.py
@@ -84,7 +84,7 @@ def create_resource() -> Response:
                     raise MissingGroupError(# Not all resources require an owner group
                         "User with no group cannot create a resource.")
                 resource = _create_resource(
-                    cursor,
+                    conn,
                     resource_name,
                     resource_category_by_id(conn, resource_category_id),
                     the_token.user,
@@ -686,7 +686,6 @@ def delete_resource() -> Response:
         form = request_json()
         try:
             resource_id = UUID(form.get("resource_id"))
-            # TODO Update resource creation to grant privileges (system:resource:*) to admin users
             # TODO Update user-levels promotion/demotion to grant/revoke (system:resource:*) to/from admin users
             if not authorised_for_spec(
                     conn,