diff options
-rw-r--r-- | gn_auth/auth/authorisation/resources/groups/models.py | 2 | ||||
-rw-r--r-- | gn_auth/auth/authorisation/resources/models.py | 50 | ||||
-rw-r--r-- | tests/unit/auth/fixtures/group_fixtures.py | 112 | ||||
-rw-r--r-- | tests/unit/auth/fixtures/resource_fixtures.py | 109 | ||||
-rw-r--r-- | tests/unit/auth/fixtures/role_fixtures.py | 169 | ||||
-rw-r--r-- | tests/unit/auth/fixtures/user_fixtures.py | 25 | ||||
-rw-r--r-- | tests/unit/auth/test_groups.py | 82 | ||||
-rw-r--r-- | tests/unit/auth/test_privileges.py | 5 | ||||
-rw-r--r-- | tests/unit/auth/test_resources.py | 13 | ||||
-rw-r--r-- | tests/unit/auth/test_roles.py | 300 |
10 files changed, 598 insertions, 269 deletions
diff --git a/gn_auth/auth/authorisation/resources/groups/models.py b/gn_auth/auth/authorisation/resources/groups/models.py index 03a93b6..ee77654 100644 --- a/gn_auth/auth/authorisation/resources/groups/models.py +++ b/gn_auth/auth/authorisation/resources/groups/models.py @@ -72,7 +72,7 @@ def user_membership(conn: db.DbConnection, user: User) -> Sequence[Group]: "WHERE group_users.user_id=?") with db.cursor(conn) as cursor: cursor.execute(query, (str(user.user_id),)) - groups = tuple(Group(row[0], row[1], json.loads(row[2])) + groups = tuple(Group(row[0], row[1], json.loads(row[2] or "{}")) for row in cursor.fetchall()) return groups diff --git a/gn_auth/auth/authorisation/resources/models.py b/gn_auth/auth/authorisation/resources/models.py index c6c2e9e..94e817d 100644 --- a/gn_auth/auth/authorisation/resources/models.py +++ b/gn_auth/auth/authorisation/resources/models.py @@ -4,6 +4,8 @@ from uuid import UUID, uuid4 from functools import reduce, partial from typing import Dict, Sequence, Optional +import sqlite3 + from gn_auth.auth.db import sqlite3 as db from gn_auth.auth.authentication.users import User from gn_auth.auth.db.sqlite3 import with_db_connection @@ -48,6 +50,19 @@ def __assign_resource_owner_role__(cursor, resource, user): "resource_id": str(resource.resource_id) }) + +def resource_from_dbrow(row: sqlite3.Row): + """Convert an SQLite3 resultset row into a resource.""" + return Resource( + resource_id=UUID(row["resource_id"]), + resource_name=row["resource_name"], + resource_category=ResourceCategory( + UUID(row["resource_category_id"]), + row["resource_category_key"], + row["resource_category_description"]), + public=bool(int(row["public"]))) + + @authorised_p(("group:resource:create-resource",), error_description="Insufficient privileges to create a resource", oauth2_scope="profile resource") @@ -135,32 +150,19 @@ def group_leader_resources( def user_resources(conn: db.DbConnection, user: User) -> Sequence[Resource]: """List the resources available to the user""" - categories = { # Repeated in `public_resources` function - cat.resource_category_id: cat for cat in resource_categories(conn) - } with db.cursor(conn) as cursor: - def __all_resources__(group) -> Sequence[Resource]: - gl_resources = group_leader_resources(conn, user, group, categories) + cursor.execute( + ("SELECT r.*, rc.resource_category_key, " + "rc.resource_category_description FROM user_roles AS ur " + "INNER JOIN resources AS r ON ur.resource_id=r.resource_id " + "INNER JOIN resource_categories AS rc " + "ON r.resource_category_id=rc.resource_category_id " + "WHERE ur.user_id=?"), + (str(user.user_id),)) + rows = cursor.fetchall() or [] + + return tuple(resource_from_dbrow(row) for row in rows) - cursor.execute( - ("SELECT resources.* FROM user_roles LEFT JOIN resources " - "ON user_roles.resource_id=resources.resource_id " - "WHERE user_roles.user_id=?"), - (str(user.user_id),)) - rows = cursor.fetchall() - private_res = tuple( - Resource(UUID(row[0]), row[1], categories[UUID(row[2])], - bool(row[3])) - for row in rows) - return tuple({ - res.resource_id: res - for res in - (private_res + gl_resources + public_resources(conn))# type: ignore[operator] - }.values()) - - # Fix the typing here - return user_group(conn, user).map(__all_resources__).maybe(# type: ignore[arg-type,misc] - public_resources(conn), lambda res: res)# type: ignore[arg-type,return-value] def resource_data(conn, resource, offset: int = 0, limit: Optional[int] = None) -> tuple[dict, ...]: """ diff --git a/tests/unit/auth/fixtures/group_fixtures.py b/tests/unit/auth/fixtures/group_fixtures.py index 8ddcf50..2e8cd9a 100644 --- a/tests/unit/auth/fixtures/group_fixtures.py +++ b/tests/unit/auth/fixtures/group_fixtures.py @@ -7,7 +7,7 @@ from gn_auth.auth.db import sqlite3 as db from gn_auth.auth.authorisation.resources.groups import Group from gn_auth.auth.authorisation.resources import Resource, ResourceCategory -from .role_fixtures import RESOURCE_EDITOR_ROLE +from .resource_fixtures import TEST_RESOURCES TEST_GROUP_01 = Group(uuid.UUID("9988c21d-f02f-4d45-8966-22c968ac2fbf"), "TheTestGroup", {}) @@ -15,16 +15,6 @@ TEST_GROUP_02 = Group(uuid.UUID("e37d59d7-c05e-4d67-b479-81e627d8d634"), "AnotherTestGroup", {}) TEST_GROUPS = (TEST_GROUP_01, TEST_GROUP_02) -SYSTEM_CATEGORY = ResourceCategory( - uuid.UUID("aa3d787f-af6a-44fa-9b0b-c82d40e54ad2"), - "system", - "The overall system.") -SYSTEM_RESOURCE = Resource( - uuid.UUID("0248b289-b277-4eaa-8c94-88a434d14b6e"), - "GeneNetwork System", - SYSTEM_CATEGORY, - True) - GROUP_CATEGORY = ResourceCategory( uuid.UUID("1e0f70ee-add5-4358-8c6c-43de77fa4cce"), "group", @@ -46,38 +36,11 @@ GROUP_RESOURCES = tuple( False) for row in GROUPS_AS_RESOURCES) -TEST_RESOURCES_GROUP_01 = ( - Resource(uuid.UUID("26ad1668-29f5-439d-b905-84d551f85955"), - "ResourceG01R01", - ResourceCategory(uuid.UUID("48056f84-a2a6-41ac-8319-0e1e212cba2a"), - "genotype", "Genotype Dataset"), - True), - Resource(uuid.UUID("2130aec0-fefd-434d-92fd-9ca342348b2d"), - "ResourceG01R02", - ResourceCategory(uuid.UUID("548d684b-d4d1-46fb-a6d3-51a56b7da1b3"), - "phenotype", "Phenotype (Publish) Dataset"), - False), - Resource(uuid.UUID("e9a1184a-e8b4-49fb-b713-8d9cbeea5b83"), - "ResourceG01R03", - ResourceCategory(uuid.UUID("fad071a3-2fc8-40b8-992b-cdefe7dcac79"), - "mrna", "mRNA Dataset"), - False)) - -TEST_RESOURCES_GROUP_02 = ( - Resource(uuid.UUID("14496a1c-c234-49a2-978c-8859ea274054"), - "ResourceG02R01", - ResourceCategory(uuid.UUID("48056f84-a2a6-41ac-8319-0e1e212cba2a"), - "genotype", "Genotype Dataset"), - False), - Resource(uuid.UUID("04ad9e09-94ea-4390-8a02-11f92999806b"), - "ResourceG02R02", - ResourceCategory(uuid.UUID("fad071a3-2fc8-40b8-992b-cdefe7dcac79"), - "mrna", "mRNA Dataset"), - True)) - -TEST_RESOURCES = TEST_RESOURCES_GROUP_01 + TEST_RESOURCES_GROUP_02 -TEST_RESOURCES_PUBLIC = ( - SYSTEM_RESOURCE, TEST_RESOURCES_GROUP_01[0], TEST_RESOURCES_GROUP_02[1]) + +TEST_RESOURCES_GROUP_01 = TEST_RESOURCES[0:3] +TEST_RESOURCES_GROUP_02 = TEST_RESOURCES[3:5] + + def __gtuple__(cursor): return tuple(dict(row) for row in cursor.fetchall()) @@ -115,6 +78,37 @@ def fxtr_group(conn_after_auth_migrations):# pylint: disable=[redefined-outer-na "DELETE FROM groups WHERE group_id=?", ((str(group.group_id),) for group in TEST_GROUPS)) + +@pytest.fixture(scope="function") +def fxtr_resource_ownership(# pylint: disable=[redefined-outer-name] + fxtr_resources, fxtr_group +): + """fixture: Set up group ownership of resources.""" + _conn, resources = fxtr_resources + conn, groups = fxtr_group + ownership = tuple({ + "group_id": str(TEST_GROUP_01.group_id), + "resource_id": str(res.resource_id) + } for res in TEST_RESOURCES_GROUP_01) + tuple({ + "group_id": str(TEST_GROUP_02.group_id), + "resource_id": str(res.resource_id) + } for res in TEST_RESOURCES_GROUP_02) + + with db.cursor(conn) as cursor: + cursor.executemany( + "INSERT INTO resource_ownership(group_id, resource_id) " + "VALUES (:group_id, :resource_id)", + ownership) + + yield conn, resources, groups, ownership + + with db.cursor(conn) as cursor: + cursor.executemany( + "DELETE FROM resource_ownership " + "WHERE group_id=:group_id AND resource_id=:resource_id", + ownership) + + @pytest.fixture(scope="function") def fxtr_users_in_group(fxtr_group, fxtr_users):# pylint: disable=[redefined-outer-name, unused-argument] """Link the users to the groups.""" @@ -134,35 +128,3 @@ def fxtr_users_in_group(fxtr_group, fxtr_users):# pylint: disable=[redefined-out cursor.executemany( "DELETE FROM group_users WHERE group_id=? AND user_id=?", query_params) - - -@pytest.fixture(scope="function") -def fxtr_group_user_roles(fxtr_users_in_group, fxtr_resources, fxtr_resource_roles):#pylint: disable=[redefined-outer-name,unused-argument] - """Assign roles to users.""" - _conn, _group, group_users = fxtr_users_in_group - _conn, group_resources = fxtr_resources - conn, _groups, resource_roles = fxtr_resource_roles - users = tuple(user for user in group_users if user.email - not in ("unaff@iliated.user", "group@lead.er")) - users_roles_resources = ( - (user, RESOURCE_EDITOR_ROLE, TEST_RESOURCES_GROUP_01[1]) - for user in users if user.email == "group@mem.ber01") - with db.cursor(conn) as cursor: - params = tuple({ - "user_id": str(user.user_id), - "role_id": str(role.role_id), - "resource_id": str(resource.resource_id) - } for user, role, resource in users_roles_resources) - cursor.executemany( - ("INSERT INTO user_roles " - "VALUES (:user_id, :role_id, :resource_id)"), - params) - - yield conn, group_users, resource_roles, group_resources - - with db.cursor(conn) as cursor: - cursor.executemany( - ("DELETE FROM user_roles WHERE " - "user_id=:user_id AND role_id=:role_id AND " - "resource_id=:resource_id"), - params) diff --git a/tests/unit/auth/fixtures/resource_fixtures.py b/tests/unit/auth/fixtures/resource_fixtures.py index 37397d2..e06f64e 100644 --- a/tests/unit/auth/fixtures/resource_fixtures.py +++ b/tests/unit/auth/fixtures/resource_fixtures.py @@ -1,76 +1,65 @@ """Fixtures and utilities for resource-related tests""" +import uuid + import pytest from gn_auth.auth.db import sqlite3 as db +from gn_auth.auth.authorisation.resources import Resource, ResourceCategory -from .role_fixtures import RESOURCE_EDITOR_ROLE, RESOURCE_READER_ROLE -from .group_fixtures import ( - TEST_RESOURCES, - TEST_GROUP_01, - TEST_GROUP_02, - TEST_RESOURCES_GROUP_01, - TEST_RESOURCES_GROUP_02) -@pytest.fixture(scope="function") -def fxtr_resources(fxtr_group):# pylint: disable=[redefined-outer-name] - """fixture: setup test resources in the database""" - conn, _group = fxtr_group - ownership = tuple({ - "group_id": str(TEST_GROUP_01.group_id), - "resource_id": str(res.resource_id) - } for res in TEST_RESOURCES_GROUP_01) + tuple({ - "group_id": str(TEST_GROUP_02.group_id), - "resource_id": str(res.resource_id) - } for res in TEST_RESOURCES_GROUP_02) +SYSTEM_CATEGORY = ResourceCategory( + uuid.UUID("aa3d787f-af6a-44fa-9b0b-c82d40e54ad2"), + "system", + "The overall system.") +SYSTEM_RESOURCE = Resource( + uuid.UUID("0248b289-b277-4eaa-8c94-88a434d14b6e"), + "GeneNetwork System", + SYSTEM_CATEGORY, + True) - with db.cursor(conn) as cursor: - cursor.executemany( - "INSERT INTO resources VALUES (?,?,?,?)", - ((str(res.resource_id), res.resource_name, - str(res.resource_category.resource_category_id), - 1 if res.public else 0) for res in TEST_RESOURCES)) - cursor.executemany( - "INSERT INTO resource_ownership(group_id, resource_id) " - "VALUES (:group_id, :resource_id)", - ownership) +TEST_RESOURCES = ( + Resource(uuid.UUID("26ad1668-29f5-439d-b905-84d551f85955"), + "ResourceG01R01", + ResourceCategory(uuid.UUID("48056f84-a2a6-41ac-8319-0e1e212cba2a"), + "genotype", "Genotype Dataset"), + True), + Resource(uuid.UUID("2130aec0-fefd-434d-92fd-9ca342348b2d"), + "ResourceG01R02", + ResourceCategory(uuid.UUID("548d684b-d4d1-46fb-a6d3-51a56b7da1b3"), + "phenotype", "Phenotype (Publish) Dataset"), + False), + Resource(uuid.UUID("e9a1184a-e8b4-49fb-b713-8d9cbeea5b83"), + "ResourceG01R03", + ResourceCategory(uuid.UUID("fad071a3-2fc8-40b8-992b-cdefe7dcac79"), + "mrna", "mRNA Dataset"), + False), + Resource(uuid.UUID("14496a1c-c234-49a2-978c-8859ea274054"), + "ResourceG02R01", + ResourceCategory(uuid.UUID("48056f84-a2a6-41ac-8319-0e1e212cba2a"), + "genotype", "Genotype Dataset"), + False), + Resource(uuid.UUID("04ad9e09-94ea-4390-8a02-11f92999806b"), + "ResourceG02R02", + ResourceCategory(uuid.UUID("fad071a3-2fc8-40b8-992b-cdefe7dcac79"), + "mrna", "mRNA Dataset"), + True)) - yield (conn, TEST_RESOURCES) - - with db.cursor(conn) as cursor: - cursor.executemany( - "DELETE FROM resource_ownership " - "WHERE group_id=:group_id AND resource_id=:resource_id", - ownership) - cursor.executemany("DELETE FROM resources WHERE resource_id=?", - ((str(res.resource_id),) - for res in TEST_RESOURCES)) +TEST_RESOURCES_PUBLIC = (SYSTEM_RESOURCE, TEST_RESOURCES[0], TEST_RESOURCES[4]) @pytest.fixture(scope="function") -def fxtr_resource_roles(fxtr_group, fxtr_resources, fxtr_roles):# pylint: disable=[redefined-outer-name,unused-argument] - """Link roles to resources.""" - resource_roles = ({ - "resource_id": str(TEST_RESOURCES_GROUP_01[0].resource_id), - "role_created_by": "ecb52977-3004-469e-9428-2a1856725c7f", - "role_id": str(RESOURCE_EDITOR_ROLE.role_id) - },{ - "resource_id": str(TEST_RESOURCES_GROUP_01[0].resource_id), - "role_created_by": "ecb52977-3004-469e-9428-2a1856725c7f", - "role_id": str(RESOURCE_READER_ROLE.role_id) - }) - conn, groups = fxtr_group +def fxtr_resources(conn_after_auth_migrations): + """fixture: setup test resources in the database""" + conn = conn_after_auth_migrations with db.cursor(conn) as cursor: cursor.executemany( - "INSERT INTO resource_roles(resource_id, role_created_by, role_id) " - "VALUES (:resource_id, :role_created_by, :role_id)", - resource_roles) + "INSERT INTO resources VALUES (?,?,?,?)", + ((str(res.resource_id), res.resource_name, + str(res.resource_category.resource_category_id), + 1 if res.public else 0) for res in TEST_RESOURCES)) - yield conn, groups, resource_roles + yield (conn, TEST_RESOURCES) with db.cursor(conn) as cursor: - cursor.executemany( - ("DELETE FROM resource_roles " - "WHERE resource_id=:resource_id " - "AND role_created_by=:role_created_by " - "AND role_id=:role_id"), - resource_roles) + cursor.executemany("DELETE FROM resources WHERE resource_id=?", + ((str(res.resource_id),) for res in TEST_RESOURCES)) diff --git a/tests/unit/auth/fixtures/role_fixtures.py b/tests/unit/auth/fixtures/role_fixtures.py index ddcbba5..1858712 100644 --- a/tests/unit/auth/fixtures/role_fixtures.py +++ b/tests/unit/auth/fixtures/role_fixtures.py @@ -7,18 +7,41 @@ from gn_auth.auth.db import sqlite3 as db from gn_auth.auth.authorisation.roles import Role from gn_auth.auth.authorisation.privileges import Privilege +from .user_fixtures import TEST_USERS +from .resource_fixtures import SYSTEM_RESOURCE, TEST_RESOURCES_PUBLIC +from .group_fixtures import ( + TEST_GROUP_01, + TEST_RESOURCES_GROUP_01, + TEST_RESOURCES_GROUP_02) + +PUBLIC_VIEW_ROLE = Role( + uuid.UUID("fd88bfed-d869-4969-87f2-67c4e8446ecb"), + "public-view", + False, + (Privilege("group:resource:view-resource", + "view a resource and use it in computations"),)) + RESOURCE_READER_ROLE = Role( - uuid.UUID("c3ca2507-ee24-4835-9b31-8c21e1c072d3"), "resource_reader", True, + uuid.UUID("c3ca2507-ee24-4835-9b31-8c21e1c072d3"), "resource_reader", + True, (Privilege("group:resource:view-resource", "view a resource and use it in computations"),)) RESOURCE_EDITOR_ROLE = Role( - uuid.UUID("89819f84-6346-488b-8955-86062e9eedb7"), "resource_editor", True, + uuid.UUID("89819f84-6346-488b-8955-86062e9eedb7"), + "resource_editor", + True, ( Privilege("group:resource:view-resource", "view a resource and use it in computations"), Privilege("group:resource:edit-resource", "edit/update a resource"))) +CREATE_GROUP_ROLE = Role( + uuid.UUID("ade7e6b0-ba9c-4b51-87d0-2af7fe39a347"), + "group-creator", + False, + (Privilege("system:group:create-group", "Create a group"),)) + TEST_ROLES = (RESOURCE_READER_ROLE, RESOURCE_EDITOR_ROLE) @pytest.fixture(scope="function") @@ -43,3 +66,145 @@ def fxtr_roles(conn_after_auth_migrations): cursor.executemany( ("DELETE FROM roles WHERE role_id=?"), ((str(role.role_id),) for role in TEST_ROLES)) + + +@pytest.fixture(scope="function") +def fxtr_resource_roles(fxtr_resources, fxtr_roles):# pylint: disable=[redefined-outer-name,unused-argument] + """Link roles to resources.""" + resource_roles = ({ + "resource_id": str(TEST_RESOURCES_GROUP_01[0].resource_id), + "role_created_by": "ecb52977-3004-469e-9428-2a1856725c7f", + "role_id": str(RESOURCE_EDITOR_ROLE.role_id) + },{ + "resource_id": str(TEST_RESOURCES_GROUP_01[0].resource_id), + "role_created_by": "ecb52977-3004-469e-9428-2a1856725c7f", + "role_id": str(RESOURCE_READER_ROLE.role_id) + }, { + "resource_id": str(TEST_RESOURCES_GROUP_02[1].resource_id), + "role_created_by": "ecb52977-3004-469e-9428-2a1856725c7f", + "role_id": str(RESOURCE_EDITOR_ROLE.role_id) + },{ + "resource_id": str(TEST_RESOURCES_GROUP_02[1].resource_id), + "role_created_by": "ecb52977-3004-469e-9428-2a1856725c7f", + "role_id": str(RESOURCE_READER_ROLE.role_id) + }) + + conn, resources = fxtr_resources + with db.cursor(conn) as cursor: + cursor.executemany( + "INSERT INTO resource_roles(resource_id, role_created_by, role_id) " + "VALUES (:resource_id, :role_created_by, :role_id)", + resource_roles) + + yield conn, resources, resource_roles + + with db.cursor(conn) as cursor: + cursor.executemany( + ("DELETE FROM resource_roles " + "WHERE resource_id=:resource_id " + "AND role_created_by=:role_created_by " + "AND role_id=:role_id"), + resource_roles) + + +@pytest.fixture(scope="function") +def fxtr_setup_group_leaders(fxtr_users): + """Define what roles users have that target resources of type 'Group'.""" + conn, users = fxtr_users + with db.cursor(conn) as cursor: + cursor.execute("SELECT * FROM group_resources") + g01res_id = { + row["group_id"]: row["resource_id"] + for row in cursor.fetchall() + }[str(TEST_GROUP_01.group_id)] + test_user_roles = ({ + "user_id": "ecb52977-3004-469e-9428-2a1856725c7f", + "role_id": "a0e67630-d502-4b9f-b23f-6805d0f30e30",# group-leader + "resource_id": g01res_id + },) + cursor.executemany( + "INSERT INTO user_roles(user_id, role_id, resource_id) " + "VALUES (:user_id, :role_id, :resource_id)", + test_user_roles) + + yield conn, users + + with db.cursor(conn) as cursor: + cursor.executemany( + "DELETE FROM user_roles WHERE user_id=:user_id " + "AND role_id=:role_id AND resource_id=:resource_id", + test_user_roles) + + +@pytest.fixture(scope="function") +def fxtr_system_roles(fxtr_users): + """Define what roles users have that target resources of type 'Group'.""" + conn, users = fxtr_users + with db.cursor(conn) as cursor: + cursor.execute("SELECT * FROM resources WHERE resource_name='GeneNetwork System'") + sysres_id = cursor.fetchone()["resource_id"] + test_user_roles = tuple({ + "user_id": str(user.user_id), + "role_id": str(PUBLIC_VIEW_ROLE.role_id), + "resource_id": sysres_id + } for user in TEST_USERS) + cursor.executemany( + "INSERT INTO user_roles(user_id, role_id, resource_id) " + "VALUES (:user_id, :role_id, :resource_id)", + test_user_roles) + + yield conn, users + + with db.cursor(conn) as cursor: + cursor.executemany( + "DELETE FROM user_roles WHERE user_id=:user_id " + "AND role_id=:role_id AND resource_id=:resource_id", + test_user_roles) + + +@pytest.fixture(scope="function") +def fxtr_resource_user_roles(# pylint: disable=[too-many-arguments, too-many-locals] + fxtr_resources, + fxtr_users_in_group, + fxtr_resource_ownership, + fxtr_resource_roles, + fxtr_setup_group_leaders, + fxtr_system_roles +):#pylint: disable=[redefined-outer-name,unused-argument] + """Assign roles to users.""" + _conn, group_resources = fxtr_resources + _conn, _resources, _groups, group_resources = fxtr_resource_ownership + _conn, _group, group_users = fxtr_users_in_group + conn, _groups, resource_roles = fxtr_resource_roles + + users_roles_resources = ( + # Give access to group leader to all resources in their group + tuple((TEST_USERS[0], RESOURCE_EDITOR_ROLE, resource) + for resource in TEST_RESOURCES_GROUP_01) + # Set group member as resource editor + + ((TEST_USERS[1], RESOURCE_EDITOR_ROLE, TEST_RESOURCES_GROUP_01[1]),) + # Set group-creator role on the unaffiliated user + + ((TEST_USERS[3], CREATE_GROUP_ROLE, SYSTEM_RESOURCE),) + # Set roles for public resources + + tuple( + (user, PUBLIC_VIEW_ROLE, resource) + for user in TEST_USERS for resource in TEST_RESOURCES_PUBLIC[1:])) + with db.cursor(conn) as cursor: + params = tuple({ + "user_id": str(user.user_id), + "role_id": str(role.role_id), + "resource_id": str(resource.resource_id) + } for user, role, resource in users_roles_resources) + cursor.executemany( + ("INSERT INTO user_roles " + "VALUES (:user_id, :role_id, :resource_id)"), + params) + + yield conn, group_users, resource_roles, group_resources + + with db.cursor(conn) as cursor: + cursor.executemany( + ("DELETE FROM user_roles WHERE " + "user_id=:user_id AND role_id=:role_id AND " + "resource_id=:resource_id"), + params) diff --git a/tests/unit/auth/fixtures/user_fixtures.py b/tests/unit/auth/fixtures/user_fixtures.py index b88d78a..1cf0e20 100644 --- a/tests/unit/auth/fixtures/user_fixtures.py +++ b/tests/unit/auth/fixtures/user_fixtures.py @@ -6,8 +6,6 @@ import pytest from gn_auth.auth.db import sqlite3 as db from gn_auth.auth.authentication.users import User, hash_password -from .group_fixtures import TEST_GROUP_01 - TEST_USERS = ( User(uuid.UUID("ecb52977-3004-469e-9428-2a1856725c7f"), "group@lead.er", "Group Leader"), @@ -25,29 +23,6 @@ def fxtr_users(conn_after_auth_migrations, fxtr_group):# pylint: disable=[redefi with db.cursor(conn_after_auth_migrations) as cursor: cursor.executemany(query, ( (str(user.user_id), user.email, user.name) for user in TEST_USERS)) - # setup user roles - cursor.execute("SELECT * FROM group_resources") - g01res_id = { - row["group_id"]: row["resource_id"] - for row in cursor.fetchall() - }[str(TEST_GROUP_01.group_id)] - cursor.execute("SELECT * FROM resources WHERE resource_name='GeneNetwork System'") - sysres_id = cursor.fetchone()["resource_id"] - test_user_roles = ( - { - "user_id": "ecb52977-3004-469e-9428-2a1856725c7f", - "role_id": "a0e67630-d502-4b9f-b23f-6805d0f30e30",# group-leader - "resource_id": g01res_id - }, - { - "user_id": "ecb52977-3004-469e-9428-2a1856725c7f", - "role_id": "ade7e6b0-ba9c-4b51-87d0-2af7fe39a347",# group-creator - "resource_id": sysres_id - }) - cursor.executemany( - "INSERT INTO user_roles(user_id, role_id, resource_id) " - "VALUES (:user_id, :role_id, :resource_id)", - test_user_roles) yield (conn_after_auth_migrations, TEST_USERS) diff --git a/tests/unit/auth/test_groups.py b/tests/unit/auth/test_groups.py index 2960fe1..f22a8cf 100644 --- a/tests/unit/auth/test_groups.py +++ b/tests/unit/auth/test_groups.py @@ -6,7 +6,6 @@ from pymonad.maybe import Nothing from gn_auth.auth.db import sqlite3 as db from gn_auth.auth.errors import AuthorisationError -from gn_auth.auth.authentication.users import User from gn_auth.auth.authorisation.roles import Role from gn_auth.auth.authorisation.privileges import Privilege from gn_auth.auth.authorisation.resources.groups.models import ( @@ -28,15 +27,60 @@ PRIVILEGES = ( Privilege("group:resource:edit-resource", "edit/update a resource")) @pytest.mark.unit_test +@pytest.mark.parametrize("user", tuple(conftest.TEST_USERS[0:3])) +def test_create_group_fails(# pylint: disable=[too-many-arguments] + fxtr_app, auth_testdb_path, mocker, fxtr_resource_user_roles, fxtr_oauth2_clients, user):# pylint: disable=[unused-argument] + """ + GIVEN: an authenticated user + WHEN: the user attempts to create a group + THEN: verify they are only able to create the group if they have the + appropriate privileges + """ + _conn, clients = fxtr_oauth2_clients + mocker.patch("gn_auth.auth.authorisation.resources.groups.models.uuid4", conftest.uuid_fn) + mocker.patch( + "gn_auth.auth.authorisation.checks.require_oauth.acquire", + conftest.get_tokeniser( + user, + tuple(client for client in clients if client.user == user)[0])) + with db.connection(auth_testdb_path) as conn: + with pytest.raises(AuthorisationError): + create_group(conn, "a_test_group", user, "A test group") + + +def __cleanup_create_group__(conn, user, group): + """Cleanup creating a group...""" + # cleanup: This should probably go into a 'delete_group(…) function' + with db.cursor(conn) as cursor: + cursor.execute("DELETE FROM group_users WHERE group_id=? AND user_id=?", + (str(group.group_id), str(user.user_id))) + cursor.execute("SELECT * FROM group_resources WHERE group_id=?", + (str(group.group_id),)) + grp_rsc = cursor.fetchone() + cursor.execute( + "DELETE FROM user_roles WHERE user_id=? AND resource_id=?", + (str(user.user_id), str(grp_rsc["resource_id"]))) + cursor.execute("DELETE FROM group_resources WHERE group_id=?", + (str(group.group_id),)) + cursor.execute("DELETE FROM groups WHERE group_id=?", + (str(group.group_id),)) + + +@pytest.mark.unit_test @pytest.mark.parametrize( - "user,expected", tuple(zip(conftest.TEST_USERS[0:1], ( - Group( - UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_group", - {"group_description": "A test group"}), - create_group_failure, create_group_failure, create_group_failure, - create_group_failure)))) -def test_create_group(# pylint: disable=[too-many-arguments] - fxtr_app, auth_testdb_path, mocker, fxtr_users, fxtr_oauth2_clients, user, expected):# pylint: disable=[unused-argument] + "user,expected", + ((conftest.TEST_USERS[3], Group( + UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_group", + {"group_description": "A test group"})),)) +def test_create_group_succeeds(# pylint: disable=[too-many-arguments, unused-argument] + fxtr_app, + auth_testdb_path, + mocker, + fxtr_resource_user_roles, + fxtr_oauth2_clients, + user, + expected +): """ GIVEN: an authenticated user WHEN: the user attempts to create a group @@ -51,8 +95,11 @@ def test_create_group(# pylint: disable=[too-many-arguments] user, tuple(client for client in clients if client.user == user)[0])) with db.connection(auth_testdb_path) as conn: - assert create_group( - conn, "a_test_group", user, "A test group") == expected + created_group = create_group( + conn, "a_test_group", user, "A test group") + assert created_group == expected + __cleanup_create_group__(conn, user, created_group) + @pytest.mark.unit_test @pytest.mark.parametrize("user", conftest.TEST_USERS[1:]) @@ -140,7 +187,7 @@ def test_create_group_role_raises_exception_with_unauthorised_users( conn, GROUP, "ResourceEditor", PRIVILEGES) == expected @pytest.mark.unit_test -def test_create_multiple_groups(mocker, fxtr_users, fxtr_oauth2_clients): +def test_create_multiple_groups(mocker, fxtr_resource_user_roles, fxtr_oauth2_clients): """ GIVEN: An authenticated user with appropriate authorisation WHEN: The user attempts to create a new group, while being a member of an @@ -150,23 +197,24 @@ def test_create_multiple_groups(mocker, fxtr_users, fxtr_oauth2_clients): """ _conn, clients = fxtr_oauth2_clients mocker.patch("gn_auth.auth.authorisation.resources.groups.models.uuid4", conftest.uuid_fn) - user = User( - UUID("ecb52977-3004-469e-9428-2a1856725c7f"), "group@lead.er", - "Group Leader") + user = conftest.TEST_USERS[3] mocker.patch( "gn_auth.auth.authorisation.checks.require_oauth.acquire", conftest.get_tokeniser( user, tuple(client for client in clients if client.user == user)[0])) - conn, _test_users = fxtr_users + conn, *_test_users = fxtr_resource_user_roles # First time, successfully creates the group - assert create_group(conn, "a_test_group", user) == Group( + created_group = create_group(conn, "a_test_group", user) + assert created_group == Group( UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_group", {}) # subsequent attempts should fail with pytest.raises(AuthorisationError): create_group(conn, "another_test_group", user) + __cleanup_create_group__(conn, user, created_group) + @pytest.mark.unit_test @pytest.mark.parametrize( "user,expected", diff --git a/tests/unit/auth/test_privileges.py b/tests/unit/auth/test_privileges.py index a225369..619ccc1 100644 --- a/tests/unit/auth/test_privileges.py +++ b/tests/unit/auth/test_privileges.py @@ -11,8 +11,7 @@ def sort_key_privileges(priv): return priv.privilege_id PRIVILEGES = sorted( - (Privilege("system:group:create-group", "Create a group"), - Privilege("system:group:view-group", "View the details of a group"), + (Privilege("system:group:view-group", "View the details of a group"), Privilege("system:group:edit-group", "Edit the details of a group"), Privilege("system:user:list", "List users in the system"), Privilege("system:group:delete-group", "Delete a group"), @@ -32,7 +31,7 @@ PRIVILEGES = sorted( @pytest.mark.parametrize( "user,expected", tuple(zip( conftest.TEST_USERS, (PRIVILEGES, [], [], [], [])))) -def test_user_privileges(auth_testdb_path, fxtr_users, user, expected):# pylint: disable=[unused-argument] +def test_user_privileges(auth_testdb_path, fxtr_setup_group_leaders, user, expected):# pylint: disable=[unused-argument] """ GIVEN: A user WHEN: An attempt is made to fetch the user's privileges diff --git a/tests/unit/auth/test_resources.py b/tests/unit/auth/test_resources.py index b842490..9b45b68 100644 --- a/tests/unit/auth/test_resources.py +++ b/tests/unit/auth/test_resources.py @@ -30,7 +30,14 @@ create_resource_failure = { (Resource( uuid.UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "test_resource", resource_category, False),)))) -def test_create_resource(mocker, fxtr_users_in_group, fxtr_oauth2_clients, user, expected): +def test_create_resource(# pylint: disable=[too-many-arguments, unused-argument] + mocker, + fxtr_users_in_group, + fxtr_resource_user_roles, + fxtr_oauth2_clients, + user, + expected +): """Test that resource creation works as expected.""" mocker.patch("gn_auth.auth.authorisation.resources.models.uuid4", conftest.uuid_fn) _conn, clients = fxtr_oauth2_clients @@ -114,13 +121,13 @@ def test_public_resources(fxtr_resources): , key=sort_key_resources), PUBLIC_RESOURCES, PUBLIC_RESOURCES)))) -def test_user_resources(fxtr_group_user_roles, user, expected): +def test_user_resources(fxtr_resource_user_roles, user, expected): """ GIVEN: some resources in the database WHEN: a particular user's resources are requested THEN: list only the resources for which the user can access """ - conn, *_others = fxtr_group_user_roles + conn, *_others = fxtr_resource_user_roles assert sorted( {res.resource_id: res for res in user_resources(conn, user) }.values(), key=sort_key_resources) == expected diff --git a/tests/unit/auth/test_roles.py b/tests/unit/auth/test_roles.py index e07ee98..b9d1183 100644 --- a/tests/unit/auth/test_roles.py +++ b/tests/unit/auth/test_roles.py @@ -1,5 +1,5 @@ """Test functions dealing with group management.""" -import uuid +from uuid import UUID import pytest @@ -22,14 +22,22 @@ PRIVILEGES = ( Privilege("group:resource:edit-resource", "edit/update a resource")) -@pytest.mark.skip("This still needs some work to actually tests for resource roles.") +@pytest.mark.skip( + "This needs to be replaced by tests for creation of resource roles.") @pytest.mark.unit_test @pytest.mark.parametrize( "user,expected", tuple(zip(conftest.TEST_USERS[0:1], ( - Role(uuid.UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_role", + Role(UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_role", True, PRIVILEGES),)))) -def test_create_role(# pylint: disable=[too-many-arguments] - fxtr_app, auth_testdb_path, mocker, fxtr_users, fxtr_oauth2_clients, user, expected):# pylint: disable=[unused-argument] +def test_create_role(# pylint: disable=[too-many-arguments, unused-argument] + fxtr_app, + auth_testdb_path, + mocker, + fxtr_users, + fxtr_oauth2_clients, + user, + expected +): """ GIVEN: an authenticated user WHEN: the user attempts to create a role @@ -52,8 +60,15 @@ def test_create_role(# pylint: disable=[too-many-arguments] @pytest.mark.parametrize( "user,expected", tuple(zip(conftest.TEST_USERS[1:], ( create_role_failure, create_role_failure, create_role_failure)))) -def test_create_role_raises_exception_for_unauthorised_users(# pylint: disable=[too-many-arguments] - fxtr_app, auth_testdb_path, mocker, fxtr_users, fxtr_oauth2_clients, user, expected):# pylint: disable=[unused-argument] +def test_create_role_raises_exception_for_unauthorised_users(# pylint: disable=[too-many-arguments, unused-argument] + fxtr_app, + auth_testdb_path, + mocker, + fxtr_users, + fxtr_oauth2_clients, + user, + expected +): """ GIVEN: an authenticated user WHEN: the user attempts to create a role @@ -77,80 +92,247 @@ def test_create_role_raises_exception_for_unauthorised_users(# pylint: disable=[ @pytest.mark.parametrize( "user,expected", (zip(TEST_USERS, - (({"resource_id": uuid.UUID("38d1807d-105f-44a7-8327-7e2d973b6d8d"), - "user_id": uuid.UUID("ecb52977-3004-469e-9428-2a1856725c7f"), + (({"resource_id": UUID("2130aec0-fefd-434d-92fd-9ca342348b2d"), + "user_id": UUID("ecb52977-3004-469e-9428-2a1856725c7f"), "roles": (Role( - role_id=uuid.UUID('a0e67630-d502-4b9f-b23f-6805d0f30e30'), - role_name='group-leader', user_editable=False, + role_id=UUID("89819f84-6346-488b-8955-86062e9eedb7"), + role_name="resource_editor", + user_editable=True, privileges=( Privilege( - privilege_id='group:resource:create-resource', - privilege_description='Create a resource object'), + privilege_id="group:resource:edit-resource", + privilege_description="edit/update a resource"), Privilege( - privilege_id='group:resource:delete-resource', - privilege_description='Delete a resource'), + privilege_id="group:resource:view-resource", + privilege_description="view a resource and use it in computations"))),)}, + {"resource_id": UUID("26ad1668-29f5-439d-b905-84d551f85955"), + "user_id": UUID("ecb52977-3004-469e-9428-2a1856725c7f"), + "roles": ( + Role( + role_id=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"))), + Role( + role_id=UUID("fd88bfed-d869-4969-87f2-67c4e8446ecb"), + role_name="public-view", + user_editable=False, + privileges=( + Privilege( + privilege_id="group:resource:view-resource", + privilege_description=( + "view a resource and use it in computations")),)))}, + {"resource_id": UUID("e9a1184a-e8b4-49fb-b713-8d9cbeea5b83"), + "user_id": UUID("ecb52977-3004-469e-9428-2a1856725c7f"), + "roles": (Role( + role_id=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_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_id="group:resource:view-resource", + privilege_description="view a resource and use it in computations"))),)}, + {"resource_id": UUID("38d1807d-105f-44a7-8327-7e2d973b6d8d"), + "user_id": UUID("ecb52977-3004-469e-9428-2a1856725c7f"), + "roles": (Role( + role_id=UUID("a0e67630-d502-4b9f-b23f-6805d0f30e30"), + role_name="group-leader", + user_editable=False, + privileges=( Privilege( - privilege_id='group:user:add-group-member', - privilege_description='Add a user to a group'), + privilege_id="group:resource:create-resource", + privilege_description="Create a resource object"), Privilege( - privilege_id='group:user:remove-group-member', - privilege_description='Remove a user from a group'), + privilege_id="group:resource:delete-resource", + privilege_description="Delete a resource"), Privilege( - privilege_id='system:group:delete-group', - privilege_description='Delete a group'), + privilege_id="group:resource:edit-resource", + privilege_description="edit/update a resource"), Privilege( - privilege_id='system:group:edit-group', - privilege_description='Edit the details of a group'), + privilege_id="group:resource:view-resource", + privilege_description="view a resource and use it in computations"), Privilege( - privilege_id='system:group:transfer-group-leader', + privilege_id="group:user:add-group-member", + privilege_description="Add a user to a group"), + 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')), + "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_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"), + privilege_id="system:user:list", + privilege_description="List users in the system"))),)}, + {"resource_id": UUID("0248b289-b277-4eaa-8c94-88a434d14b6e"), + "user_id": UUID("ecb52977-3004-469e-9428-2a1856725c7f"), "roles": (Role( - role_id=uuid.UUID('89819f84-6346-488b-8955-86062e9eedb7'), - role_name='resource_editor', + role_id=UUID("fd88bfed-d869-4969-87f2-67c4e8446ecb"), + role_name="public-view", + user_editable=False, + privileges=( + Privilege( + privilege_id="group:resource:view-resource", + privilege_description="view a resource and use it in computations"),)),)}, + {"resource_id": UUID("04ad9e09-94ea-4390-8a02-11f92999806b"), + "user_id": UUID("ecb52977-3004-469e-9428-2a1856725c7f"), + "roles": (Role( + role_id=UUID("fd88bfed-d869-4969-87f2-67c4e8446ecb"), + role_name="public-view", + user_editable=False, + privileges=( + Privilege( + privilege_id="group:resource:view-resource", + privilege_description="view a resource and use it in computations"),)),)}), + ({"resource_id": UUID("2130aec0-fefd-434d-92fd-9ca342348b2d"), + "user_id": UUID("21351b66-8aad-475b-84ac-53ce528451e3"), + "roles": (Role( + role_id=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_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"))),) + }, + {"resource_id": UUID("0248b289-b277-4eaa-8c94-88a434d14b6e"), + "user_id": UUID("21351b66-8aad-475b-84ac-53ce528451e3"), + "roles": (Role( + role_id=UUID("fd88bfed-d869-4969-87f2-67c4e8446ecb"), + role_name="public-view", + user_editable=False, + privileges=( + Privilege( + privilege_id="group:resource:view-resource", + privilege_description="view a resource and use it in computations"),)),) + }, + {"resource_id": UUID("04ad9e09-94ea-4390-8a02-11f92999806b"), + "user_id": UUID("21351b66-8aad-475b-84ac-53ce528451e3"), + "roles": (Role( + role_id=UUID("fd88bfed-d869-4969-87f2-67c4e8446ecb"), + role_name="public-view", + user_editable=False, + privileges=( + Privilege( + privilege_id="group:resource:view-resource", + privilege_description="view a resource and use it in computations"),)),) + }, + {"resource_id": UUID("26ad1668-29f5-439d-b905-84d551f85955"), + "user_id": UUID("21351b66-8aad-475b-84ac-53ce528451e3"), + "roles": (Role( + role_id=UUID("fd88bfed-d869-4969-87f2-67c4e8446ecb"), + role_name="public-view", + user_editable=False, + privileges=( 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): + privilege_id="group:resource:view-resource", + privilege_description="view a resource and use it in computations"),)),) + }), + ({"resource_id": UUID("0248b289-b277-4eaa-8c94-88a434d14b6e"), + "user_id": UUID("ae9c6245-0966-41a5-9a5e-20885a96bea7"), + "roles": (Role( + role_id=UUID("fd88bfed-d869-4969-87f2-67c4e8446ecb"), + role_name="public-view", + user_editable=False, + privileges=( + Privilege( + privilege_id="group:resource:view-resource", + privilege_description="view a resource and use it in computations"),)),) + }, + {"resource_id": UUID("04ad9e09-94ea-4390-8a02-11f92999806b"), + "user_id": UUID("ae9c6245-0966-41a5-9a5e-20885a96bea7"), + "roles": (Role( + role_id=UUID("fd88bfed-d869-4969-87f2-67c4e8446ecb"), + role_name="public-view", + user_editable=False, + privileges=( + Privilege( + privilege_id="group:resource:view-resource", + privilege_description="view a resource and use it in computations"),)),) + }, + {"resource_id": UUID("26ad1668-29f5-439d-b905-84d551f85955"), + "user_id": UUID("ae9c6245-0966-41a5-9a5e-20885a96bea7"), + "roles": (Role( + role_id=UUID("fd88bfed-d869-4969-87f2-67c4e8446ecb"), + role_name="public-view", + user_editable=False, + privileges=( + Privilege( + privilege_id="group:resource:view-resource", + privilege_description="view a resource and use it in computations"),)),) + }), + ({"resource_id": UUID("0248b289-b277-4eaa-8c94-88a434d14b6e"), + "user_id": UUID("9a0c7ce5-2f40-4e78-979e-bf3527a59579"), + "roles": ( + Role( + role_id=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"),)), + Role( + role_id=UUID("fd88bfed-d869-4969-87f2-67c4e8446ecb"), + role_name="public-view", + user_editable=False, + privileges=( + Privilege( + privilege_id="group:resource:view-resource", + privilege_description="view a resource and use it in computations"),))) + }, + {"resource_id": UUID("04ad9e09-94ea-4390-8a02-11f92999806b"), + "user_id": UUID("9a0c7ce5-2f40-4e78-979e-bf3527a59579"), + "roles": (Role( + role_id=UUID("fd88bfed-d869-4969-87f2-67c4e8446ecb"), + role_name="public-view", + user_editable=False, + privileges=( + Privilege( + privilege_id="group:resource:view-resource", + privilege_description="view a resource and use it in computations"),)),) + }, + {"resource_id": UUID("26ad1668-29f5-439d-b905-84d551f85955"), + "user_id": UUID("9a0c7ce5-2f40-4e78-979e-bf3527a59579"), + "roles": (Role( + role_id=UUID("fd88bfed-d869-4969-87f2-67c4e8446ecb"), + role_name="public-view", + user_editable=False, + privileges=( + Privilege( + privilege_id="group:resource:view-resource", + privilege_description=( + "view a resource and use it in computations")),)),)}))))) +def test_user_roles( + fxtr_resource_user_roles, + user, + expected +): """ GIVEN: an authenticated user WHEN: we request the user's privileges THEN: return **ALL** the privileges attached to the user """ - conn, *_others = fxtr_group_user_roles + conn, *_others = fxtr_resource_user_roles assert user_roles(conn, user) == expected |