about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gn_auth/auth/authorisation/resources/groups/models.py2
-rw-r--r--gn_auth/auth/authorisation/resources/models.py50
-rw-r--r--tests/unit/auth/fixtures/group_fixtures.py112
-rw-r--r--tests/unit/auth/fixtures/resource_fixtures.py109
-rw-r--r--tests/unit/auth/fixtures/role_fixtures.py169
-rw-r--r--tests/unit/auth/fixtures/user_fixtures.py25
-rw-r--r--tests/unit/auth/test_groups.py82
-rw-r--r--tests/unit/auth/test_privileges.py5
-rw-r--r--tests/unit/auth/test_resources.py13
-rw-r--r--tests/unit/auth/test_roles.py300
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