From f6566c76d97cb44d47cc491f13e1342f0c2555cf Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Fri, 15 Sep 2023 08:38:47 +0300 Subject: Update `user_roles`: Return roles for user by resource. --- gn_auth/auth/authorisation/roles/models.py | 68 +++++++------ tests/unit/auth/fixtures/group_fixtures.py | 7 +- tests/unit/auth/fixtures/migration_fixtures.py | 5 + tests/unit/auth/test_roles.py | 129 ++++++++++++++++--------- 4 files changed, 130 insertions(+), 79 deletions(-) diff --git a/gn_auth/auth/authorisation/roles/models.py b/gn_auth/auth/authorisation/roles/models.py index 579c9dc..206b05e 100644 --- a/gn_auth/auth/authorisation/roles/models.py +++ b/gn_auth/auth/authorisation/roles/models.py @@ -64,43 +64,51 @@ def create_role( return role -def __organise_privileges__(roles_dict, privilege_row): - """Organise the privileges into their roles.""" - role_id_str = privilege_row["role_id"] - if role_id_str in roles_dict: - return { - **roles_dict, - role_id_str: Role( - UUID(role_id_str), - privilege_row["role_name"], - bool(int(privilege_row["user_editable"])), - roles_dict[role_id_str].privileges + ( - Privilege(privilege_row["privilege_id"], - privilege_row["privilege_description"]),)) - } - +def __organise_privileges__(resources, row) -> dict: + resource_id = UUID(row["resource_id"]) + role_id = UUID(row["role_id"]) + roles = resources.get(resource_id, {}).get("roles", {}) + role = roles.get(role_id, Role( + role_id, + row["role_name"], + bool(int(row["user_editable"])), + tuple())) return { - **roles_dict, - role_id_str: Role( - UUID(role_id_str), - privilege_row["role_name"], - bool(int(privilege_row["user_editable"])), - (Privilege(privilege_row["privilege_id"], - privilege_row["privilege_description"]),)) + **resources, + resource_id: { + "resource_id": resource_id, + "user_id": UUID(row["user_id"]), + "roles": { + **roles, + role_id: Role( + role.role_id, + role.role_name, + role.user_editable, + role.privileges + (Privilege( + row["privilege_id"], + row["privilege_description"]),) + ) + } + } } -def user_roles(conn: db.DbConnection, user: User) -> Sequence[Role]: - """Retrieve non-resource roles assigned to the user.""" +def user_roles(conn: db.DbConnection, user: User) -> Sequence[dict]: + """Retrieve all roles (organised by resource) assigned to the user.""" with db.cursor(conn) as cursor: + cursor.execute("SELECT * FROM user_roles") cursor.execute( - "SELECT 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=?", + "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=?", (str(user.user_id),)) - return tuple( - reduce(__organise_privileges__, cursor.fetchall(), {}).values()) + return tuple({ + **row, "roles": tuple(row["roles"].values()) + } for row in reduce( + __organise_privileges__, cursor.fetchall(), {}).values()) return tuple() def user_role(conn: db.DbConnection, user: User, role_id: UUID) -> Either: diff --git a/tests/unit/auth/fixtures/group_fixtures.py b/tests/unit/auth/fixtures/group_fixtures.py index 66edf5e..93133d2 100644 --- a/tests/unit/auth/fixtures/group_fixtures.py +++ b/tests/unit/auth/fixtures/group_fixtures.py @@ -21,11 +21,14 @@ GROUP_CATEGORY = ResourceCategory( "A group resource.") GROUPS_AS_RESOURCES = tuple({ "group_id": str(group.group_id), - "resource_id": str(uuid.uuid4()), + "resource_id": res_id, "resource_name": group.group_name, "category_id": str(GROUP_CATEGORY.resource_category_id), "public": "1" -} for group in TEST_GROUPS) +} for res_id, group in zip( + ("38d1807d-105f-44a7-8327-7e2d973b6d8d", + "89458ef6-e090-4b53-8c2c-59eaf2785f11"), + TEST_GROUPS)) TEST_RESOURCES_GROUP_01 = ( Resource(uuid.UUID("26ad1668-29f5-439d-b905-84d551f85955"), diff --git a/tests/unit/auth/fixtures/migration_fixtures.py b/tests/unit/auth/fixtures/migration_fixtures.py index 16a31cd..954b5a9 100644 --- a/tests/unit/auth/fixtures/migration_fixtures.py +++ b/tests/unit/auth/fixtures/migration_fixtures.py @@ -40,6 +40,11 @@ def conn_after_auth_migrations(backend, auth_testdb_path, all_migrations): # pyl """Run all migrations and return a connection to the database after""" apply_migrations(backend, all_migrations) with db.connection(auth_testdb_path) as conn: + with db.cursor(conn) as cursor: + cursor.execute( + "UPDATE resources " + "SET resource_id='0248b289-b277-4eaa-8c94-88a434d14b6e' " + "WHERE resource_name='GeneNetwork System'") yield conn rollback_migrations(backend, all_migrations) diff --git a/tests/unit/auth/test_roles.py b/tests/unit/auth/test_roles.py index 227cb9e..6c8dbae 100644 --- a/tests/unit/auth/test_roles.py +++ b/tests/unit/auth/test_roles.py @@ -64,53 +64,88 @@ def test_create_role_raises_exception_for_unauthorised_users(# pylint: disable=[ @pytest.mark.parametrize( "user,expected", (zip(TEST_USERS, - ((Role( - role_id=uuid.UUID('a0e67630-d502-4b9f-b23f-6805d0f30e30'), - role_name='group-leader', user_editable=False, - privileges=( - Privilege(privilege_id='group:resource:create-resource', - privilege_description='Create a resource object'), - Privilege(privilege_id='group:resource:delete-resource', - privilege_description='Delete a resource'), - Privilege(privilege_id='group:resource:edit-resource', - privilege_description='edit/update a resource'), - Privilege( - privilege_id='group:resource:view-resource', - privilege_description=( - 'view a resource and use it in computations')), - Privilege(privilege_id='group:role:create-role', - privilege_description='Create a new role'), - Privilege(privilege_id='group:role:delete-role', - privilege_description='Delete an existing role'), - Privilege(privilege_id='group:role:edit-role', - privilege_description='edit/update an existing role'), - Privilege(privilege_id='group:user:add-group-member', - privilege_description='Add a user to a group'), - Privilege(privilege_id='group:user:assign-role', - privilege_description=( - 'Assign a role to an existing user')), - Privilege(privilege_id='group:user:remove-group-member', - privilege_description='Remove a user from a group'), - Privilege(privilege_id='system:group:delete-group', - privilege_description='Delete a group'), - Privilege(privilege_id='system:group:edit-group', - privilege_description='Edit the details of a group'), - Privilege( - privilege_id='system:group:transfer-group-leader', - privilege_description=( - 'Transfer leadership of the group to some other ' - 'member')), - Privilege(privilege_id='system:group:view-group', - privilege_description='View the details of a group'), - Privilege(privilege_id='system:user:list', - privilege_description='List users in the system'))), - Role( - role_id=uuid.UUID("ade7e6b0-ba9c-4b51-87d0-2af7fe39a347"), - role_name="group-creator", user_editable=False, - privileges=( - Privilege(privilege_id='system:group:create-group', - privilege_description = "Create a group"),))), - tuple(), tuple(), tuple())))) + (({"resource_id": uuid.UUID("38d1807d-105f-44a7-8327-7e2d973b6d8d"), + "user_id": uuid.UUID("ecb52977-3004-469e-9428-2a1856725c7f"), + "roles": (Role( + role_id=uuid.UUID('a0e67630-d502-4b9f-b23f-6805d0f30e30'), + role_name='group-leader', user_editable=False, + privileges=( + Privilege( + privilege_id='group:resource:create-resource', + privilege_description='Create a resource object'), + Privilege( + privilege_id='group:resource:delete-resource', + privilege_description='Delete a resource'), + Privilege( + privilege_id='group:resource:edit-resource', + privilege_description='edit/update a resource'), + Privilege( + privilege_id='group:resource:view-resource', + privilege_description=( + 'view a resource and use it in computations')), + Privilege( + privilege_id='group:role:create-role', + privilege_description='Create a new role'), + Privilege( + privilege_id='group:role:delete-role', + privilege_description='Delete an existing role'), + Privilege( + privilege_id='group:role:edit-role', + privilege_description='edit/update an existing role'), + Privilege( + privilege_id='group:user:add-group-member', + privilege_description='Add a user to a group'), + Privilege( + privilege_id='group:user:assign-role', + privilege_description=( + 'Assign a role to an existing user')), + Privilege( + privilege_id='group:user:remove-group-member', + privilege_description='Remove a user from a group'), + Privilege( + privilege_id='system:group:delete-group', + privilege_description='Delete a group'), + Privilege( + privilege_id='system:group:edit-group', + privilege_description='Edit the details of a group'), + Privilege( + privilege_id='system:group:transfer-group-leader', + privilege_description=( + 'Transfer leadership of the group to some other ' + 'member')), + Privilege( + privilege_id='system:group:view-group', + privilege_description='View the details of a group'), + Privilege( + privilege_id='system:user:list', + privilege_description='List users in the system'))),) + }, + { + "resource_id": uuid.UUID("0248b289-b277-4eaa-8c94-88a434d14b6e"), + "user_id": uuid.UUID("ecb52977-3004-469e-9428-2a1856725c7f"), + "roles": (Role( + role_id=uuid.UUID("ade7e6b0-ba9c-4b51-87d0-2af7fe39a347"), + role_name="group-creator", + user_editable=False, + privileges=( + Privilege( + privilege_id="system:group:create-group", + privilege_description="Create a group"),)),)}), + ({"resource_id": uuid.UUID("2130aec0-fefd-434d-92fd-9ca342348b2d"), + "user_id": uuid.UUID("21351b66-8aad-475b-84ac-53ce528451e3"), + "roles": (Role( + role_id=uuid.UUID('89819f84-6346-488b-8955-86062e9eedb7'), + role_name='resource_editor', + user_editable=True, + privileges=( + Privilege( + privilege_id='group:resource:edit-resource', + privilege_description='edit/update a resource'), + Privilege( + privilege_id='group:resource:view-resource', + privilege_description='view a resource and use it in computations'))),)},), + tuple(), + tuple())))) def test_user_roles(fxtr_group_user_roles, user, expected): """ GIVEN: an authenticated user -- cgit v1.2.3