diff options
author | Frederick Muriuki Muriithi | 2022-11-24 13:53:59 +0300 |
---|---|---|
committer | Frederick Muriuki Muriithi | 2022-11-24 13:53:59 +0300 |
commit | 9810731b8432624c3817633ea0877dd80d0eea39 (patch) | |
tree | e30a620e9d549c6df19c80e3e27f0ac59cd7cb6e | |
parent | 021b8dfcb99928b363e4546f626e3deb5793e392 (diff) | |
download | genenetwork3-9810731b8432624c3817633ea0877dd80d0eea39.tar.gz |
auth: Check for authentication and fix errors
* gn3/auth/authorisation/groups.py: base `MembershipError` on new
`AuthorisationError` base exception. Use new authentication checking
decorator.
* gn3/auth/authorisation/privileges.py: Change argument to User object rather
than UUID object
* gn3/auth/authorisation/roles.py: Use new authentication checking decorator.
* tests/unit/auth/test_groups.py: use `conftest.TEST_USER`
* tests/unit/auth/test_privileges.py: use `conftest.TEST_USER`
* tests/unit/auth/test_roles.py: use `conftest.TEST_USER`
-rw-r--r-- | gn3/auth/authorisation/groups.py | 5 | ||||
-rw-r--r-- | gn3/auth/authorisation/privileges.py | 5 | ||||
-rw-r--r-- | gn3/auth/authorisation/roles.py | 2 | ||||
-rw-r--r-- | tests/unit/auth/test_groups.py | 48 | ||||
-rw-r--r-- | tests/unit/auth/test_privileges.py | 16 | ||||
-rw-r--r-- | tests/unit/auth/test_roles.py | 19 |
6 files changed, 48 insertions, 47 deletions
diff --git a/gn3/auth/authorisation/groups.py b/gn3/auth/authorisation/groups.py index ac80089..6496e87 100644 --- a/gn3/auth/authorisation/groups.py +++ b/gn3/auth/authorisation/groups.py @@ -12,6 +12,7 @@ from gn3.auth.authentication.checks import authenticated_p from .checks import authorised_p from .privileges import Privilege from .roles import Role, create_role +from .exceptions import AuthorisationError class Group(NamedTuple): """Class representing a group.""" @@ -23,7 +24,7 @@ class GroupRole(NamedTuple): group_role_id: UUID role: Role -class MembershipError(Exception): +class MembershipError(AuthorisationError): """Raised when there is an error with a user's membership to a group.""" def __init__(self, user: User, groups: Sequence[Group]): @@ -46,6 +47,7 @@ def user_membership(conn: db.DbConnection, user: User) -> Sequence[Group]: return groups +@authenticated_p @authorised_p(("create-group",), error_message="Failed to create group.") def create_group(conn: db.DbConnection, group_name: str, group_leader: User) -> Group: @@ -65,6 +67,7 @@ def create_group(conn: db.DbConnection, group_name: str, return group +@authenticated_p @authorised_p(("create-role",), error_message="Could not create the group role") def create_group_role( conn: db.DbConnection, group: Group, role_name: str, diff --git a/gn3/auth/authorisation/privileges.py b/gn3/auth/authorisation/privileges.py index 09439ad..9e66bda 100644 --- a/gn3/auth/authorisation/privileges.py +++ b/gn3/auth/authorisation/privileges.py @@ -3,13 +3,14 @@ from uuid import UUID from typing import Iterable, NamedTuple from gn3.auth import db +from gn3.auth.authentication.users import User class Privilege(NamedTuple): """Class representing a privilege: creates immutable objects.""" privilege_id: UUID privilege_name: str -def user_privileges(conn: db.DbConnection, user_id: UUID) -> Iterable[Privilege]: +def user_privileges(conn: db.DbConnection, user: User) -> Iterable[Privilege]: """Fetch the user's privileges from the database.""" with db.cursor(conn) as cursor: cursor.execute( @@ -18,7 +19,7 @@ def user_privileges(conn: db.DbConnection, user_id: UUID) -> Iterable[Privilege] "INNER JOIN role_privileges AS rp ON ur.role_id=rp.role_id " "INNER JOIN privileges AS p ON rp.privilege_id=p.privilege_id " "WHERE ur.user_id=?"), - (str(user_id),)) + (str(user.user_id),)) results = cursor.fetchall() return (Privilege(UUID(row[0]), row[1]) for row in results) diff --git a/gn3/auth/authorisation/roles.py b/gn3/auth/authorisation/roles.py index 8435c40..397ad80 100644 --- a/gn3/auth/authorisation/roles.py +++ b/gn3/auth/authorisation/roles.py @@ -3,6 +3,7 @@ from uuid import UUID, uuid4 from typing import Iterable, NamedTuple from gn3.auth import db +from gn3.auth.authentication.checks import authenticated_p from .checks import authorised_p from .privileges import Privilege @@ -13,6 +14,7 @@ class Role(NamedTuple): role_name: str privileges: Iterable[Privilege] +@authenticated_p @authorised_p(("create-role",), error_message="Could not create role") def create_role( cursor: db.DbCursor, role_name: str, diff --git a/tests/unit/auth/test_groups.py b/tests/unit/auth/test_groups.py index 225bb59..22d90f4 100644 --- a/tests/unit/auth/test_groups.py +++ b/tests/unit/auth/test_groups.py @@ -10,6 +10,8 @@ from gn3.auth.authorisation.privileges import Privilege from gn3.auth.authorisation.groups import ( Group, GroupRole, create_group, MembershipError, create_group_role) +from tests.unit.auth import conftest + create_group_failure = { "status": "error", "message": "Unauthorised: Failed to create group." @@ -26,15 +28,13 @@ PRIVILEGES = ( @pytest.mark.unit_test @pytest.mark.parametrize( - "user_id,expected", ( - ("ecb52977-3004-469e-9428-2a1856725c7f", Group( - UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_group")), - ("21351b66-8aad-475b-84ac-53ce528451e3", create_group_failure), - ("ae9c6245-0966-41a5-9a5e-20885a96bea7", create_group_failure), - ("9a0c7ce5-2f40-4e78-979e-bf3527a59579", create_group_failure), - ("e614247d-84d2-491d-a048-f80b578216cb", create_group_failure))) + "user,expected", tuple(zip(conftest.TEST_USERS, ( + Group( + UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_group"), + create_group_failure, create_group_failure, create_group_failure, + create_group_failure)))) def test_create_group(# pylint: disable=[too-many-arguments] - test_app, auth_testdb_path, mocker, test_users, user_id, expected):# pylint: disable=[unused-argument] + test_app, auth_testdb_path, mocker, test_users, user, expected):# pylint: disable=[unused-argument] """ GIVEN: an authenticated user WHEN: the user attempts to create a group @@ -43,10 +43,9 @@ def test_create_group(# pylint: disable=[too-many-arguments] """ mocker.patch("gn3.auth.authorisation.groups.uuid4", uuid_fn) with test_app.app_context() as flask_context: - flask_context.g.user_id = UUID(user_id) + flask_context.g.user = user with db.connection(auth_testdb_path) as conn: - assert create_group(conn, "a_test_group", User( - UUID(user_id), "some@email.address", "a_test_user")) == expected + assert create_group(conn, "a_test_group", user) == expected create_role_failure = { "status": "error", @@ -55,16 +54,14 @@ create_role_failure = { @pytest.mark.unit_test @pytest.mark.parametrize( - "user_id,expected", ( - ("ecb52977-3004-469e-9428-2a1856725c7f", GroupRole( - UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), - Role(UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), - "ResourceEditor", PRIVILEGES))), - ("21351b66-8aad-475b-84ac-53ce528451e3", create_role_failure), - ("ae9c6245-0966-41a5-9a5e-20885a96bea7", create_role_failure), - ("9a0c7ce5-2f40-4e78-979e-bf3527a59579", create_role_failure), - ("e614247d-84d2-491d-a048-f80b578216cb", create_role_failure))) -def test_create_group_role(mocker, test_users_in_group, test_app, user_id, expected): + "user,expected", tuple(zip(conftest.TEST_USERS, ( + GroupRole( + UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), + Role(UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), + "ResourceEditor", PRIVILEGES)), + create_role_failure, create_role_failure, create_role_failure, + create_role_failure)))) +def test_create_group_role(mocker, test_users_in_group, test_app, user, expected): """ GIVEN: an authenticated user WHEN: the user attempts to create a role, attached to a group @@ -75,7 +72,7 @@ def test_create_group_role(mocker, test_users_in_group, test_app, user_id, expec mocker.patch("gn3.auth.authorisation.roles.uuid4", uuid_fn) conn, _group, _users = test_users_in_group with test_app.app_context() as flask_context: - flask_context.g.user_id = UUID(user_id) + flask_context.g.user = user assert create_group_role( conn, GROUP, "ResourceEditor", PRIVILEGES) == expected @@ -89,11 +86,12 @@ def test_create_multiple_groups(mocker, test_app, test_users): message """ mocker.patch("gn3.auth.authorisation.groups.uuid4", uuid_fn) - user_id = UUID("ecb52977-3004-469e-9428-2a1856725c7f") + user = User( + UUID("ecb52977-3004-469e-9428-2a1856725c7f"), "group@lead.er", + "Group Leader") conn, _test_users = test_users with test_app.app_context() as flask_context: - flask_context.g.user_id = user_id - user = User(user_id, "some@email.address", "a_test_user") + 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") diff --git a/tests/unit/auth/test_privileges.py b/tests/unit/auth/test_privileges.py index 2514f9d..3586e90 100644 --- a/tests/unit/auth/test_privileges.py +++ b/tests/unit/auth/test_privileges.py @@ -6,6 +6,8 @@ import pytest from gn3.auth import db from gn3.auth.authorisation.privileges import Privilege, user_privileges +from tests.unit.auth import conftest + SORT_KEY = lambda x: x.privilege_name PRIVILEGES = sorted( @@ -33,18 +35,14 @@ PRIVILEGES = sorted( @pytest.mark.unit_test @pytest.mark.parametrize( - "user_id,expected", ( - ("ecb52977-3004-469e-9428-2a1856725c7f", PRIVILEGES), - ("21351b66-8aad-475b-84ac-53ce528451e3", []), - ("ae9c6245-0966-41a5-9a5e-20885a96bea7", []), - ("9a0c7ce5-2f40-4e78-979e-bf3527a59579", []), - ("e614247d-84d2-491d-a048-f80b578216cb", []))) -def test_user_privileges(auth_testdb_path, test_users, user_id, expected):# pylint: disable=[unused-argument] + "user,expected", tuple(zip( + conftest.TEST_USERS, (PRIVILEGES, [], [], [], [])))) +def test_user_privileges(auth_testdb_path, test_users, user, expected):# pylint: disable=[unused-argument] """ - GIVEN: A user_id + GIVEN: A user WHEN: An attempt is made to fetch the user's privileges THEN: Ensure only """ with db.connection(auth_testdb_path) as conn: assert sorted( - user_privileges(conn, UUID(user_id)), key=SORT_KEY) == expected + user_privileges(conn, user), key=SORT_KEY) == expected diff --git a/tests/unit/auth/test_roles.py b/tests/unit/auth/test_roles.py index 70663b3..b6e681d 100644 --- a/tests/unit/auth/test_roles.py +++ b/tests/unit/auth/test_roles.py @@ -7,6 +7,8 @@ from gn3.auth import db from gn3.auth.authorisation.privileges import Privilege from gn3.auth.authorisation.roles import Role, create_role +from tests.unit.auth import conftest + create_role_failure = { "status": "error", "message": "Unauthorised: Could not create role" @@ -22,16 +24,13 @@ PRIVILEGES = ( @pytest.mark.unit_test @pytest.mark.parametrize( - "user_id,expected", ( - ("ecb52977-3004-469e-9428-2a1856725c7f", Role( - uuid.UUID("d32611e3-07fc-4564-b56c-786c6db6de2b"), "a_test_role", - PRIVILEGES)), - ("21351b66-8aad-475b-84ac-53ce528451e3", create_role_failure), - ("ae9c6245-0966-41a5-9a5e-20885a96bea7", create_role_failure), - ("9a0c7ce5-2f40-4e78-979e-bf3527a59579", create_role_failure), - ("e614247d-84d2-491d-a048-f80b578216cb", create_role_failure))) + "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)))) def test_create_role(# pylint: disable=[too-many-arguments] - test_app, auth_testdb_path, mocker, test_users, user_id, expected):# pylint: disable=[unused-argument] + test_app, auth_testdb_path, mocker, test_users, user, expected):# pylint: disable=[unused-argument] """ GIVEN: an authenticated user WHEN: the user attempts to create a role @@ -40,7 +39,7 @@ def test_create_role(# pylint: disable=[too-many-arguments] """ mocker.patch("gn3.auth.authorisation.roles.uuid4", uuid_fn) with test_app.app_context() as flask_context: - flask_context.g.user_id = uuid.UUID(user_id) + flask_context.g.user = user with db.connection(auth_testdb_path) as conn, db.cursor(conn) as cursor: the_role = create_role(cursor, "a_test_role", PRIVILEGES) assert the_role == expected |