about summary refs log tree commit diff
path: root/migrations/auth
diff options
context:
space:
mode:
Diffstat (limited to 'migrations/auth')
-rw-r--r--migrations/auth/20250328_01_72EFk-add-admin-ui-privilege-to-system-administrator-role.py42
-rw-r--r--migrations/auth/20250609_01_LB60X-add-batch-edit-privileges.py49
-rw-r--r--migrations/auth/20250609_01_bj9Pl-add-new-group-data-link-to-group-privilege.py19
-rw-r--r--migrations/auth/20250609_02_9UBPl-assign-group-data-link-to-group-privilege-to-group-leader.py23
-rw-r--r--migrations/auth/20250703_01_aDVwP-add-role-management-privileges-to-group-leader-role.py27
-rw-r--r--migrations/auth/20250722_01_7Gro7-create-new-system-user-edit-privilege.py18
-rw-r--r--migrations/auth/20250722_02_M8TXv-add-system-user-edit-privilege-to-system-admin-role.py36
-rw-r--r--migrations/auth/20250729_01_CNn2p-create-initial-system-wide-resources-access-privileges.py31
-rw-r--r--migrations/auth/20250729_02_7ycSm-assign-initial-system-wide-resources-access-privileges-to-sys-admins.py53
-rw-r--r--migrations/auth/20250729_03_oCvvq-grant-role-to-all-resources-to-sys-admin-users.py75
-rw-r--r--migrations/auth/20250731_01_Ke1us-add-sysadmin-privileges-for-acting-on-groups-members.py70
11 files changed, 443 insertions, 0 deletions
diff --git a/migrations/auth/20250328_01_72EFk-add-admin-ui-privilege-to-system-administrator-role.py b/migrations/auth/20250328_01_72EFk-add-admin-ui-privilege-to-system-administrator-role.py
new file mode 100644
index 0000000..d22ad01
--- /dev/null
+++ b/migrations/auth/20250328_01_72EFk-add-admin-ui-privilege-to-system-administrator-role.py
@@ -0,0 +1,42 @@
+"""
+add admin ui privilege to system-administrator role
+"""
+import contextlib
+
+from yoyo import step
+
+__depends__ = {'20240924_01_thbvh-hooks-for-edu-domains'}
+
+def get_system_admin_id(cursor):
+    cursor.execute(
+        "SELECT role_id FROM roles WHERE role_name='system-administrator'")
+    return cursor.fetchone()[0]
+
+def add_admin_ui_privilege(conn):
+    with contextlib.closing(conn.cursor()) as cursor:
+        # Create admin-ui privilege
+        cursor.execute(
+            "INSERT INTO privileges (privilege_id, privilege_description) "
+            "VALUES(?, ?)",
+            ("system:user:admin-ui", "View UI elements that should only be visible to system administrators"))
+
+        # Add UI privilege to system-administrator role
+        cursor.execute(
+            "INSERT INTO role_privileges (role_id, privilege_id) "
+            "VALUES(?, ?)",
+            (get_system_admin_id(cursor), "system:user:admin-ui")
+        )
+
+def remove_admin_ui_privilege(conn):
+    with contextlib.closing(conn.cursor()) as cursor:
+        # Remove UI privilege from system-administrator role
+        cursor.execute(
+            "DELETE FROM role_privileges WHERE privilege_id='system:user:admin-ui'")
+        
+        # Remove UI privilege from privileges table
+        cursor.execute(
+            "DELETE FROM privileges WHERE privilege_id='system:user:admin-ui'")
+
+steps = [
+    step(add_admin_ui_privilege, remove_admin_ui_privilege)
+]
diff --git a/migrations/auth/20250609_01_LB60X-add-batch-edit-privileges.py b/migrations/auth/20250609_01_LB60X-add-batch-edit-privileges.py
new file mode 100644
index 0000000..73a4880
--- /dev/null
+++ b/migrations/auth/20250609_01_LB60X-add-batch-edit-privileges.py
@@ -0,0 +1,49 @@
+"""
+Add Batch Edit privileges
+"""
+
+import contextlib
+
+from yoyo import step
+
+__depends__ = {'20250328_01_72EFk-add-admin-ui-privilege-to-system-administrator-role'}
+
+def add_batch_edit_privilege_and_role(conn):
+    with contextlib.closing(conn.cursor()) as cursor:
+        # Create batch edit privilege
+        cursor.execute(
+            "INSERT INTO privileges (privilege_id, privilege_description) "
+            "VALUES(?, ?)",
+            ("system:data:batch-edit", "Batch Edit"))
+
+        # Create batch editor role
+        cursor.execute(
+            "INSERT INTO roles (role_id, role_name, user_editable) "
+            "VALUES(?, ?, ?)",
+            ("0f391910-5225-476a-bb8d-9c0adc9d81cc", "Batch Editors", 0))
+
+        # Link role/privilege
+        cursor.execute(
+            "INSERT INTO role_privileges (role_id, privilege_id) "
+            "VALUES(?, ?)",
+            ("0f391910-5225-476a-bb8d-9c0adc9d81cc", "system:data:batch-edit")
+        )
+
+def remove_batch_edit_privilege_and_role(conn):
+    with contextlib.closing(conn.cursor()) as cursor:
+        # Remove batch edit role/privilege link
+        cursor.execute(
+            "DELETE FROM role_privileges WHERE privilege_id='system:data:batch-edit'")
+        
+        # Remove Batch Editor role
+        cursor.execute(
+            "DELETE FROM roles WHERE role_id='0f391910-5225-476a-bb8d-9c0adc9d81cc'")
+
+        # Remove Batch Edit privilege
+        cursor.execute(
+            "DELETE FROM privileges WHERE privilege_id='system:data:batch-edit'")
+
+
+steps = [
+    step(add_batch_edit_privilege_and_role, remove_batch_edit_privilege_and_role)
+]
diff --git a/migrations/auth/20250609_01_bj9Pl-add-new-group-data-link-to-group-privilege.py b/migrations/auth/20250609_01_bj9Pl-add-new-group-data-link-to-group-privilege.py
new file mode 100644
index 0000000..3b9e928
--- /dev/null
+++ b/migrations/auth/20250609_01_bj9Pl-add-new-group-data-link-to-group-privilege.py
@@ -0,0 +1,19 @@
+"""
+Add new 'group:data:link-to-group' privilege.
+"""
+
+from yoyo import step
+
+__depends__ = {'20240924_01_thbvh-hooks-for-edu-domains'}
+
+steps = [
+    step(
+        """
+    INSERT INTO privileges(privilege_id, privilege_description)
+    VALUES(
+      'group:data:link-to-group',
+      'Allow linking data to only one specific group.'
+    )
+    """,
+        "DELETE FROM privileges WHERE privilege_id='group:data:link-to-group'")
+]
diff --git a/migrations/auth/20250609_02_9UBPl-assign-group-data-link-to-group-privilege-to-group-leader.py b/migrations/auth/20250609_02_9UBPl-assign-group-data-link-to-group-privilege-to-group-leader.py
new file mode 100644
index 0000000..5d9c306
--- /dev/null
+++ b/migrations/auth/20250609_02_9UBPl-assign-group-data-link-to-group-privilege-to-group-leader.py
@@ -0,0 +1,23 @@
+"""
+Assign 'group:data:link-to-group' privilege to group leader.
+"""
+
+from yoyo import step
+
+__depends__ = {'20250609_01_bj9Pl-add-new-group-data-link-to-group-privilege'}
+
+steps = [
+    step(
+        """
+        INSERT INTO role_privileges(role_id, privilege_id)
+        VALUES(
+          'a0e67630-d502-4b9f-b23f-6805d0f30e30',
+          'group:data:link-to-group'
+        )
+        """,
+        """
+        DELETE FROM role_privileges
+        WHERE role_id='a0e67630-d502-4b9f-b23f-6805d0f30e30'
+        AND privilege_id='group:data:link-to-group'
+        """)
+]
diff --git a/migrations/auth/20250703_01_aDVwP-add-role-management-privileges-to-group-leader-role.py b/migrations/auth/20250703_01_aDVwP-add-role-management-privileges-to-group-leader-role.py
new file mode 100644
index 0000000..6335152
--- /dev/null
+++ b/migrations/auth/20250703_01_aDVwP-add-role-management-privileges-to-group-leader-role.py
@@ -0,0 +1,27 @@
+"""
+Add role management privileges to group-leader role
+"""
+
+from yoyo import step
+
+__depends__ = {'20250609_01_LB60X-add-batch-edit-privileges', '20250609_02_9UBPl-assign-group-data-link-to-group-privilege-to-group-leader'}
+
+steps = [
+    step(
+        """
+        INSERT INTO role_privileges(role_id, privilege_id)
+        VALUES
+          ('a0e67630-d502-4b9f-b23f-6805d0f30e30', 'resource:role:create-role'),
+          ('a0e67630-d502-4b9f-b23f-6805d0f30e30', 'resource:role:delete-role'),
+          ('a0e67630-d502-4b9f-b23f-6805d0f30e30', 'resource:role:edit-role')
+        """,
+        """
+        DELETE FROM role_privileges
+        WHERE role_id='a0e67630-d502-4b9f-b23f-6805d0f30e30'
+        AND privilege_id IN (
+          'resource:role:create-role',
+          'resource:role:delete-role',
+          'resource:role:edit-role'
+        )
+        """)
+]
diff --git a/migrations/auth/20250722_01_7Gro7-create-new-system-user-edit-privilege.py b/migrations/auth/20250722_01_7Gro7-create-new-system-user-edit-privilege.py
new file mode 100644
index 0000000..f00ab11
--- /dev/null
+++ b/migrations/auth/20250722_01_7Gro7-create-new-system-user-edit-privilege.py
@@ -0,0 +1,18 @@
+"""
+Create new 'system:user:edit' privilege.
+"""
+
+from yoyo import step
+
+__depends__ = {'20250703_01_aDVwP-add-role-management-privileges-to-group-leader-role'}
+
+steps = [
+    step(
+        """
+        INSERT INTO privileges(privilege_id, privilege_description)
+        VALUES(
+          'system:user:edit',
+          'Allow general user-information edit.')
+        """,
+        "DELETE FROM privileges WHERE privilege_id='system:user:edit'")
+]
diff --git a/migrations/auth/20250722_02_M8TXv-add-system-user-edit-privilege-to-system-admin-role.py b/migrations/auth/20250722_02_M8TXv-add-system-user-edit-privilege-to-system-admin-role.py
new file mode 100644
index 0000000..b956bef
--- /dev/null
+++ b/migrations/auth/20250722_02_M8TXv-add-system-user-edit-privilege-to-system-admin-role.py
@@ -0,0 +1,36 @@
+"""
+Add 'system:user:edit' privilege to 'system-admin' role.
+"""
+import contextlib
+
+from yoyo import step
+
+__depends__ = {'20250722_01_7Gro7-create-new-system-user-edit-privilege'}
+
+
+def system_administrator_role_id(cursor):
+    """Fetch ID for role 'system-administrator'."""
+    cursor.execute(
+        "SELECT role_id FROM roles WHERE role_name='system-administrator'")
+    return cursor.fetchone()[0]
+
+
+def add_system_user_edit_privilege(conn):
+    """Add the 'system:user:edit' to the 'system-administrator' role."""
+    with contextlib.closing(conn.cursor()) as cursor:
+        cursor.execute(
+            "INSERT INTO role_privileges(role_id, privilege_id) "
+            "VALUES(?, ?)",
+            (system_administrator_role_id(cursor), 'system:user:edit'))
+
+
+def remove_system_user_edit_privilege(conn):
+    """Remove the 'system:user:edit' from the 'system-administrator' role."""
+    with contextlib.closing(conn.cursor()) as cursor:
+        cursor.execute(
+            "DELETE FROM role_privileges WHERE role_id=? AND privilege_id=?",
+            (system_administrator_role_id(cursor), 'system:user:edit'))
+
+steps = [
+    step(add_system_user_edit_privilege, remove_system_user_edit_privilege)
+]
diff --git a/migrations/auth/20250729_01_CNn2p-create-initial-system-wide-resources-access-privileges.py b/migrations/auth/20250729_01_CNn2p-create-initial-system-wide-resources-access-privileges.py
new file mode 100644
index 0000000..be0d022
--- /dev/null
+++ b/migrations/auth/20250729_01_CNn2p-create-initial-system-wide-resources-access-privileges.py
@@ -0,0 +1,31 @@
+"""
+Create initial system-wide resources access privileges
+"""
+
+from yoyo import step
+
+__depends__ = {'20250722_02_M8TXv-add-system-user-edit-privilege-to-system-admin-role'}
+
+steps = [
+    step(
+        """
+        INSERT INTO privileges(privilege_id, privilege_description)
+        VALUES
+          ("system:resource:view",
+           "View the wrapper resource object (not attached data). This is mostly for administration purposes."),
+          ("system:resource:edit",
+           "Edit/update the wrapper resource object (not attached data). This is mostly for administration purposes."),
+          ("system:resource:delete",
+           "Delete the wrapper resource object (not attached data). This is mostly for administration purposes."),
+          ("system:resource:reassign-group",
+           "Reassign the resource, and its data, to a different user group."),
+          ("system:resource:assign-owner",
+           "Assign ownership of any resource to any user.")
+        """,
+        """
+        DELETE FROM privileges WHERE privilege_id IN
+          ("system:resource:view", "system:resource:edit",
+           "system:resource:delete", "system:resource:reassign-group",
+           "system:resource:assign-owner")
+        """)
+]
diff --git a/migrations/auth/20250729_02_7ycSm-assign-initial-system-wide-resources-access-privileges-to-sys-admins.py b/migrations/auth/20250729_02_7ycSm-assign-initial-system-wide-resources-access-privileges-to-sys-admins.py
new file mode 100644
index 0000000..e79ab1c
--- /dev/null
+++ b/migrations/auth/20250729_02_7ycSm-assign-initial-system-wide-resources-access-privileges-to-sys-admins.py
@@ -0,0 +1,53 @@
+"""
+Assign initial system-wide resources-access privileges to sys-admins.
+"""
+import contextlib
+
+from yoyo import step
+
+def system_administrator_role_id(cursor):
+    """Fetch ID for role 'system-administrator'."""
+    cursor.execute(
+        "SELECT role_id FROM roles WHERE role_name='system-administrator'")
+    return cursor.fetchone()[0]
+
+
+def assign_system_wide_resource_access_to_sysadmin(conn):
+    """
+    Assign initial system-wide resources-access privileges to
+    `system-administrator` role.
+    """
+    with contextlib.closing(conn.cursor()) as cursor:
+        sysadmin_role_id = system_administrator_role_id(cursor)
+        cursor.executemany(
+            "INSERT INTO role_privileges(role_id, privilege_id) "
+            "VALUES(?, ?)",
+            ((sysadmin_role_id, "system:resource:view"),
+             (sysadmin_role_id, "system:resource:edit"),
+             (sysadmin_role_id, "system:resource:delete"),
+             (sysadmin_role_id, "system:resource:reassign-group"),
+             (sysadmin_role_id, "system:resource:assign-owner")))
+
+
+def revoke_system_wide_resource_access_from_sysadmin(conn):
+    """
+    Revoke initial system-wide resources-access privileges from
+    `system-administrator` role.
+    """
+    with contextlib.closing(conn.cursor()) as cursor:
+        sysadmin_role_id = system_administrator_role_id(cursor)
+        cursor.executemany(
+            "DELETE FROM role_privileges "
+            "WHERE role_id=? AND privilege_id=?",
+            ((sysadmin_role_id, "system:resource:view"),
+             (sysadmin_role_id, "system:resource:edit"),
+             (sysadmin_role_id, "system:resource:delete"),
+             (sysadmin_role_id, "system:resource:reassign-group"),
+             (sysadmin_role_id, "system:resource:assign-owner")))
+
+__depends__ = {'20250729_01_CNn2p-create-initial-system-wide-resources-access-privileges'}
+
+steps = [
+    step(assign_system_wide_resource_access_to_sysadmin,
+         revoke_system_wide_resource_access_from_sysadmin)
+]
diff --git a/migrations/auth/20250729_03_oCvvq-grant-role-to-all-resources-to-sys-admin-users.py b/migrations/auth/20250729_03_oCvvq-grant-role-to-all-resources-to-sys-admin-users.py
new file mode 100644
index 0000000..e3bdc8f
--- /dev/null
+++ b/migrations/auth/20250729_03_oCvvq-grant-role-to-all-resources-to-sys-admin-users.py
@@ -0,0 +1,75 @@
+"""
+Grant  role to ALL resources to sys-admin users.
+"""
+import itertools
+import contextlib
+
+from yoyo import step
+
+__depends__ = {'20250729_02_7ycSm-assign-initial-system-wide-resources-access-privileges-to-sys-admins'}
+
+
+def system_administrator_role_id(cursor):
+    """Fetch ID for role 'system-administrator'."""
+    cursor.execute(
+        "SELECT role_id FROM roles WHERE role_name='system-administrator'")
+    return cursor.fetchone()[0]
+
+
+def system_resource_id(cursor):
+    cursor.execute(
+        "SELECT resources.resource_id FROM resource_categories "
+        "INNER JOIN resources ON resource_categories.resource_category_id=resources.resource_category_id "
+        "WHERE resource_category_key = 'system'")
+    return cursor.fetchone()[0]
+
+
+def fetch_ids_for_sysadmin_users(cursor):
+    """Fetch all sysadmin users' IDs."""
+    cursor.execute(
+        "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=?",
+        (system_resource_id(cursor),))
+    return tuple(row[0] for row in cursor.fetchall())
+
+
+def fetch_non_system_resources(cursor):
+    """Fetch IDs for all resources that are not of the 'system' category."""
+    cursor.execute(
+        "SELECT resources.resource_id FROM resource_categories "
+        "INNER JOIN resources "
+        "ON resource_categories.resource_category_id=resources.resource_category_id "
+        "WHERE resource_category_key != 'system'")
+    return tuple(row[0] for row in cursor.fetchall())
+
+
+def assign_sysadmin_role_on_non_system_resources(conn):
+    """Assign sysadmins the sysadmin role on all non-system resources."""
+    with contextlib.closing(conn.cursor()) as cursor:
+        sysadminroleid = system_administrator_role_id(cursor)
+        cursor.executemany(
+            "INSERT INTO user_roles(user_id, resource_id, role_id) "
+            "VALUES (?, ?, ?)",
+            tuple(item + (sysadminroleid,)
+                  for item in itertools.product(
+                          fetch_ids_for_sysadmin_users(cursor),
+                          fetch_non_system_resources(cursor))))
+
+
+def revoke_sysadmin_role_on_non_system_resources(conn):
+    """Revoke sysadmins the sysadmin role on all non-system resources."""
+    with contextlib.closing(conn.cursor()) as cursor:
+        sysadminroleid = system_administrator_role_id(cursor)
+        cursor.executemany(
+            "DELETE FROM user_roles "
+            "WHERE user_id=? AND resource_id=? AND role_id=?",
+            tuple(item + (sysadminroleid,)
+                  for item in itertools.product(
+                          fetch_ids_for_sysadmin_users(cursor),
+                          fetch_non_system_resources(cursor))))
+
+steps = [
+    step(assign_sysadmin_role_on_non_system_resources,
+         revoke_sysadmin_role_on_non_system_resources)
+]
diff --git a/migrations/auth/20250731_01_Ke1us-add-sysadmin-privileges-for-acting-on-groups-members.py b/migrations/auth/20250731_01_Ke1us-add-sysadmin-privileges-for-acting-on-groups-members.py
new file mode 100644
index 0000000..95a6fbb
--- /dev/null
+++ b/migrations/auth/20250731_01_Ke1us-add-sysadmin-privileges-for-acting-on-groups-members.py
@@ -0,0 +1,70 @@
+"""
+Add sysadmin privileges for acting on groups: mostly handling user management.
+"""
+import itertools
+import contextlib
+
+from yoyo import step
+
+__depends__ = {'20250729_03_oCvvq-grant-role-to-all-resources-to-sys-admin-users'}
+
+
+def system_administrator_role_id(cursor):
+    """Fetch ID for role 'system-administrator'."""
+    cursor.execute(
+        "SELECT role_id FROM roles WHERE role_name='system-administrator'")
+    return cursor.fetchone()[0]
+
+
+def add_group_privileges_to_sysadmin_role(conn):
+    """Add group-management privileges to sysadmin role."""
+    with contextlib.closing(conn.cursor()) as cursor:
+        sysadminroleid = system_administrator_role_id(cursor)
+        cursor.executemany(
+            "INSERT INTO role_privileges(role_id, privilege_id) VALUES (?, ?)",
+            tuple(itertools.product(
+                (sysadminroleid,),
+                ('system:group:add-group-member',
+                 'system:group:remove-group-member',
+                 'system:group:assign-group-leader',
+                 'system:group:revoke-group-leader'))))
+
+
+def remove_group_privileges_to_sysadmin_role(conn):
+    """Remove group-management privileges from sysadmin role."""
+    with contextlib.closing(conn.cursor()) as cursor:
+        sysadminroleid = system_administrator_role_id(cursor)
+        cursor.executemany(
+            "DELETE FROM role_privileges WHERE role_id=? AND privilege_id=?",
+            tuple(itertools.product(
+                (sysadminroleid,),
+                ('system:group:add-group-member',
+                 'system:group:remove-group-member',
+                 'system:group:assign-group-leader',
+                 'system:group:revoke-group-leader'))))
+
+
+steps = [
+    step(
+        """
+        INSERT INTO privileges(privilege_id, privilege_description)
+        VALUES
+          ('system:group:add-group-member',
+           'Make an existing user a member of a group.'),
+          ('system:group:remove-group-member',
+           'Remove a member user from a group.'),
+          ('system:group:assign-group-leader',
+           'Assign an existing group member the group-leader role'),
+          ('system:group:revoke-group-leader',
+           'Revoke the group-leader role from a group member with the role.')
+        """,
+        """
+        DELETE FROM privileges WHERE privilege_id IN
+        ('system:group:add-group-member',
+         'system:group:remove-group-member',
+         'system:group:assign-group-leader',
+         'system:group:revoke-group-leader')
+        """),
+    step(add_group_privileges_to_sysadmin_role,
+         remove_group_privileges_to_sysadmin_role)
+]