diff options
author | Frederick Muriuki Muriithi | 2023-01-23 14:30:20 +0300 |
---|---|---|
committer | Frederick Muriuki Muriithi | 2023-01-23 14:30:20 +0300 |
commit | b9139c2356f75103bc5fd17f074f4ee0e74b64aa (patch) | |
tree | 06803f97ccea91ce5137d42f42e1abe33c38365c /tests | |
parent | e92ceacccb4c8d32f28ed7d2530ddc6912a730d4 (diff) | |
download | genenetwork3-b9139c2356f75103bc5fd17f074f4ee0e74b64aa.tar.gz |
auth: create group: Fix group creation.
* gn3/auth/authorisation/checks.py: Enable passing user to authorisation
checking function. Raise error on authorisation failure for consistent error
handling.
* gn3/auth/authorisation/groups.py: Add user to group, updating the privileges
as appropriate.
* gn3/auth/authorisation/resources.py: Fix resources querying
* gn3/auth/authorisation/roles.py: Assign/revoke roles by name
* gn3/auth/authorisation/views.py: Create group
* migrations/auth/20221108_01_CoxYh-create-the-groups-table.py: Add
group_metadata field
* tests/unit/auth/fixtures/group_fixtures.py: fix tests
* tests/unit/auth/test_groups.py: fix tests
* tests/unit/auth/test_resources.py: fix tests
* tests/unit/auth/test_roles.py: fix tests
Diffstat (limited to 'tests')
-rw-r--r-- | tests/unit/auth/fixtures/group_fixtures.py | 4 | ||||
-rw-r--r-- | tests/unit/auth/test_groups.py | 63 | ||||
-rw-r--r-- | tests/unit/auth/test_resources.py | 49 | ||||
-rw-r--r-- | tests/unit/auth/test_roles.py | 28 |
4 files changed, 113 insertions, 31 deletions
diff --git a/tests/unit/auth/fixtures/group_fixtures.py b/tests/unit/auth/fixtures/group_fixtures.py index 1830374..d7bbc56 100644 --- a/tests/unit/auth/fixtures/group_fixtures.py +++ b/tests/unit/auth/fixtures/group_fixtures.py @@ -10,9 +10,9 @@ from gn3.auth.authorisation.resources import Resource, ResourceCategory from .role_fixtures import RESOURCE_EDITOR_ROLE, RESOURCE_READER_ROLE TEST_GROUP_01 = Group(uuid.UUID("9988c21d-f02f-4d45-8966-22c968ac2fbf"), - "TheTestGroup") + "TheTestGroup", {}) TEST_GROUP_02 = Group(uuid.UUID("e37d59d7-c05e-4d67-b479-81e627d8d634"), - "AnotherTestGroup") + "AnotherTestGroup", {}) TEST_GROUPS = (TEST_GROUP_01, TEST_GROUP_02) TEST_RESOURCES_GROUP_01 = ( diff --git a/tests/unit/auth/test_groups.py b/tests/unit/auth/test_groups.py index 158360e..219b82a 100644 --- a/tests/unit/auth/test_groups.py +++ b/tests/unit/auth/test_groups.py @@ -8,8 +8,10 @@ from gn3.auth import db from gn3.auth.authentication.users import User from gn3.auth.authorisation.roles import Role from gn3.auth.authorisation.privileges import Privilege +from gn3.auth.authorisation.errors import AuthorisationError from gn3.auth.authorisation.groups import ( - Group, GroupRole, user_group, create_group, MembershipError, create_group_role) + Group, GroupRole, user_group, create_group, MembershipError, + create_group_role) from tests.unit.auth import conftest @@ -20,7 +22,8 @@ create_group_failure = { uuid_fn = lambda : UUID("d32611e3-07fc-4564-b56c-786c6db6de2b") -GROUP = Group(UUID("9988c21d-f02f-4d45-8966-22c968ac2fbf"), "TheTestGroup") +GROUP = Group(UUID("9988c21d-f02f-4d45-8966-22c968ac2fbf"), "TheTestGroup", + {"group_description": "The test group"}) PRIVILEGES = ( Privilege( "group:resource:view-resource", @@ -29,9 +32,10 @@ PRIVILEGES = ( @pytest.mark.unit_test @pytest.mark.parametrize( - "user,expected", tuple(zip(conftest.TEST_USERS, ( + "user,expected", tuple(zip(conftest.TEST_USERS[0:1], ( Group( - UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_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] @@ -46,7 +50,24 @@ def test_create_group(# pylint: disable=[too-many-arguments] with fxtr_app.app_context() as flask_context: flask_context.g.user = user with db.connection(auth_testdb_path) as conn: - assert create_group(conn, "a_test_group", user) == expected + assert create_group( + conn, "a_test_group", user, "A test group") == expected + +@pytest.mark.unit_test +@pytest.mark.parametrize("user", conftest.TEST_USERS[1:]) +def test_create_group_raises_exception_with_non_privileged_user(# pylint: disable=[too-many-arguments] + fxtr_app, auth_testdb_path, mocker, fxtr_users, user):# pylint: disable=[unused-argument] + """ + GIVEN: an authenticated user, without appropriate privileges + WHEN: the user attempts to create a group + THEN: verify the system raises an exception + """ + mocker.patch("gn3.auth.authorisation.groups.uuid4", uuid_fn) + with fxtr_app.app_context() as flask_context: + flask_context.g.user = user + with db.connection(auth_testdb_path) as conn: + with pytest.raises(AuthorisationError): + assert create_group(conn, "a_test_group", user, "A test group") create_role_failure = { "status": "error", @@ -55,14 +76,12 @@ create_role_failure = { @pytest.mark.unit_test @pytest.mark.parametrize( - "user,expected", tuple(zip(conftest.TEST_USERS, ( + "user,expected", tuple(zip(conftest.TEST_USERS[0:1], ( GroupRole( UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), GROUP, Role(UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), - "ResourceEditor", PRIVILEGES)), - create_role_failure, create_role_failure, create_role_failure, - create_role_failure)))) + "ResourceEditor", PRIVILEGES)),)))) def test_create_group_role(mocker, fxtr_users_in_group, fxtr_app, user, expected): """ GIVEN: an authenticated user @@ -84,6 +103,27 @@ def test_create_group_role(mocker, fxtr_users_in_group, fxtr_app, user, expected (str(uuid_fn()), str(GROUP.group_id), str(uuid_fn()))) @pytest.mark.unit_test +@pytest.mark.parametrize( + "user,expected", tuple(zip(conftest.TEST_USERS[1:], ( + create_role_failure, create_role_failure, create_role_failure)))) +def test_create_group_role_raises_exception_with_unauthorised_users( + mocker, fxtr_users_in_group, fxtr_app, user, expected): + """ + GIVEN: an authenticated user + WHEN: the user attempts to create a role, attached to a group + THEN: verify they are only able to create the role if they have the + appropriate privileges and that the role is attached to the given group + """ + mocker.patch("gn3.auth.authorisation.groups.uuid4", uuid_fn) + mocker.patch("gn3.auth.authorisation.roles.uuid4", uuid_fn) + conn, _group, _users = fxtr_users_in_group + with fxtr_app.app_context() as flask_context: + flask_context.g.user = user + with pytest.raises(AuthorisationError): + assert create_group_role( + conn, GROUP, "ResourceEditor", PRIVILEGES) == expected + +@pytest.mark.unit_test def test_create_multiple_groups(mocker, fxtr_app, fxtr_users): """ GIVEN: An authenticated user with appropriate authorisation @@ -101,7 +141,8 @@ def test_create_multiple_groups(mocker, fxtr_app, fxtr_users): flask_context.g.user = user # First time, successfully creates the group assert create_group(conn, "a_test_group", user) == Group( - UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_group") + UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_group", + {}) # subsequent attempts should fail with pytest.raises(MembershipError): create_group(conn, "another_test_group", user) @@ -111,7 +152,7 @@ def test_create_multiple_groups(mocker, fxtr_app, fxtr_users): "user,expected", tuple(zip( conftest.TEST_USERS, - (([Group(UUID("9988c21d-f02f-4d45-8966-22c968ac2fbf"), "TheTestGroup")] * 3) + (([Group(UUID("9988c21d-f02f-4d45-8966-22c968ac2fbf"), "TheTestGroup", {})] * 3) + [Nothing])))) def test_user_group(fxtr_users_in_group, user, expected): """ diff --git a/tests/unit/auth/test_resources.py b/tests/unit/auth/test_resources.py index e6ebeb9..a0236c4 100644 --- a/tests/unit/auth/test_resources.py +++ b/tests/unit/auth/test_resources.py @@ -5,13 +5,15 @@ import pytest from gn3.auth import db from gn3.auth.authorisation.groups import Group +from gn3.auth.authorisation.errors import AuthorisationError from gn3.auth.authorisation.resources import ( Resource, user_resources, create_resource, ResourceCategory, public_resources) from tests.unit.auth import conftest -group = Group(uuid.UUID("9988c21d-f02f-4d45-8966-22c968ac2fbf"), "TheTestGroup") +group = Group(uuid.UUID("9988c21d-f02f-4d45-8966-22c968ac2fbf"), "TheTestGroup", + {}) resource_category = ResourceCategory( uuid.UUID("fad071a3-2fc8-40b8-992b-cdefe7dcac79"), "mrna", "mRNA Dataset") create_resource_failure = { @@ -24,14 +26,10 @@ uuid_fn = lambda : uuid.UUID("d32611e3-07fc-4564-b56c-786c6db6de2b") @pytest.mark.parametrize( "user,expected", tuple(zip( - conftest.TEST_USERS, + conftest.TEST_USERS[0:1], (Resource( group, uuid.UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), - "test_resource", resource_category, False), - create_resource_failure, - create_resource_failure, - create_resource_failure, - create_resource_failure)))) + "test_resource", resource_category, False),)))) def test_create_resource(mocker, fxtr_app, fxtr_users_in_group, user, expected): """Test that resource creation works as expected.""" mocker.patch("gn3.auth.authorisation.resources.uuid4", uuid_fn) @@ -44,6 +42,24 @@ def test_create_resource(mocker, fxtr_app, fxtr_users_in_group, user, expected): cursor.execute( "DELETE FROM resources WHERE resource_id=?", (str(uuid_fn()),)) +@pytest.mark.unit_test +@pytest.mark.parametrize( + "user,expected", + tuple(zip( + conftest.TEST_USERS[1:], + (create_resource_failure, create_resource_failure, + create_resource_failure)))) +def test_create_resource_raises_for_unauthorised_users( + mocker, fxtr_app, fxtr_users_in_group, user, expected): + """Test that resource creation works as expected.""" + mocker.patch("gn3.auth.authorisation.resources.uuid4", uuid_fn) + conn, _group, _users = fxtr_users_in_group + with fxtr_app.app_context() as flask_context: + flask_context.g.user = user + with pytest.raises(AuthorisationError): + assert create_resource( + conn, "test_resource", resource_category) == expected + SORTKEY = lambda resource: resource.resource_id @pytest.mark.unit_test @@ -57,7 +73,9 @@ def test_public_resources(fxtr_resources): assert sorted(public_resources(conn), key=SORTKEY) == sorted(tuple( res for res in conftest.TEST_RESOURCES if res.public), key=SORTKEY) -PUBLIC_RESOURCES = sorted(conftest.TEST_RESOURCES_PUBLIC, key=SORTKEY) +PUBLIC_RESOURCES = sorted( + {res.resource_id: res for res in conftest.TEST_RESOURCES_PUBLIC}.values(), + key=SORTKEY) @pytest.mark.unit_test @pytest.mark.parametrize( @@ -65,12 +83,15 @@ PUBLIC_RESOURCES = sorted(conftest.TEST_RESOURCES_PUBLIC, key=SORTKEY) tuple(zip( conftest.TEST_USERS, (sorted( - set(conftest.TEST_RESOURCES_GROUP_01).union( - conftest.TEST_RESOURCES_PUBLIC), + {res.resource_id: res for res in + (conftest.TEST_RESOURCES_GROUP_01 + + conftest.TEST_RESOURCES_PUBLIC)}.values(), key=SORTKEY), sorted( - set([conftest.TEST_RESOURCES_GROUP_01[1]]).union( - conftest.TEST_RESOURCES_PUBLIC), + {res.resource_id: res for res in + ((conftest.TEST_RESOURCES_GROUP_01[1],) + + conftest.TEST_RESOURCES_PUBLIC)}.values() + , key=SORTKEY), PUBLIC_RESOURCES, PUBLIC_RESOURCES)))) def test_user_resources(fxtr_group_user_roles, user, expected): @@ -80,4 +101,6 @@ def test_user_resources(fxtr_group_user_roles, user, expected): THEN: list only the resources for which the user can access """ conn, *_others = fxtr_group_user_roles - assert sorted(user_resources(conn, user), key=SORTKEY) == expected + assert sorted( + {res.resource_id: res for res in user_resources(conn, user) + }.values(), key=SORTKEY) == expected diff --git a/tests/unit/auth/test_roles.py b/tests/unit/auth/test_roles.py index 7252bfe..78ff8a6 100644 --- a/tests/unit/auth/test_roles.py +++ b/tests/unit/auth/test_roles.py @@ -5,6 +5,7 @@ import pytest from gn3.auth import db from gn3.auth.authorisation.privileges import Privilege +from gn3.auth.authorisation.errors import AuthorisationError from gn3.auth.authorisation.roles import Role, user_roles, create_role from tests.unit.auth import conftest @@ -24,11 +25,9 @@ PRIVILEGES = ( @pytest.mark.unit_test @pytest.mark.parametrize( - "user,expected", tuple(zip(conftest.TEST_USERS, ( - Role( - uuid.UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_role", - PRIVILEGES), create_role_failure, create_role_failure, - create_role_failure, create_role_failure)))) + "user,expected", tuple(zip(conftest.TEST_USERS[0:1], ( + Role(uuid.UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_role", + PRIVILEGES),)))) def test_create_role(# pylint: disable=[too-many-arguments] fxtr_app, auth_testdb_path, mocker, fxtr_users, user, expected):# pylint: disable=[unused-argument] """ @@ -46,6 +45,25 @@ def test_create_role(# pylint: disable=[too-many-arguments] @pytest.mark.unit_test @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, user, expected):# pylint: disable=[unused-argument] + """ + GIVEN: an authenticated user + WHEN: the user attempts to create a role + THEN: verify they are only able to create the role if they have the + appropriate privileges + """ + mocker.patch("gn3.auth.authorisation.roles.uuid4", uuid_fn) + with fxtr_app.app_context() as flask_context: + flask_context.g.user = user + with db.connection(auth_testdb_path) as conn, db.cursor(conn) as cursor: + with pytest.raises(AuthorisationError): + create_role(cursor, "a_test_role", PRIVILEGES) + +@pytest.mark.unit_test +@pytest.mark.parametrize( "user,expected", (zip(TEST_USERS, ((Role( |