From 53371fb668d1d18ba4696b3e4739f26edd677d8d Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Wed, 11 Jan 2023 11:20:36 +0300 Subject: auth: assign default role. separate group creation from group admin A newly registered user will have the ability to create a group. Once a user is a member of a group, either by creating a new group, or being added to a group, they should not be able to create any more groups, i.e. they lose the 'create-group' (and/or equivalent) privileges. This means that the group-administration privileges should be separated from the group-creation privilege. * gn3/auth/authorisation/roles.py: assign default roles to user on registration * gn3/auth/authorisation/views.py: assign default roles to user on registration * migrations/auth/20230111_01_Wd6IZ-remove-create-group-privilege-from-group-leader.py: separate group-creation role from group-administration role. * tests/unit/auth/fixtures/user_fixtures.py: Add group-creation role to test user * tests/unit/auth/test_roles.py: Add the group-creation role explicitly in the expected results for the test --- gn3/auth/authorisation/roles.py | 13 +++++++ gn3/auth/authorisation/views.py | 5 +-- ...ove-create-group-privilege-from-group-leader.py | 40 ++++++++++++++++++++++ tests/unit/auth/fixtures/user_fixtures.py | 4 ++- tests/unit/auth/test_roles.py | 12 ++++--- 5 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 migrations/auth/20230111_01_Wd6IZ-remove-create-group-privilege-from-group-leader.py diff --git a/gn3/auth/authorisation/roles.py b/gn3/auth/authorisation/roles.py index 562d3bc..6602c9f 100644 --- a/gn3/auth/authorisation/roles.py +++ b/gn3/auth/authorisation/roles.py @@ -83,3 +83,16 @@ def user_roles(conn: db.DbConnection, user: User): return tuple( reduce(__organise_privileges__, results, {}).values()) return tuple() + +def assign_default_roles(cursor: db.DbCursor, user: User): + """Assign `user` some default roles.""" + cursor.execute( + 'SELECT role_id FROM roles WHERE role_name IN ' + '("group-creator")') + role_ids = cursor.fetchall() + str_user_id = str(user.user_id) + params = ( + {"user_id": str_user_id, "role_id": role_id} for role_id in role_ids) + cursor.executemany( + ("INSERT INTO user_roles VALUES (:user_id, :role_id)"), + params) diff --git a/gn3/auth/authorisation/views.py b/gn3/auth/authorisation/views.py index 6ac3be0..2c47bd9 100644 --- a/gn3/auth/authorisation/views.py +++ b/gn3/auth/authorisation/views.py @@ -7,10 +7,10 @@ from gn3.auth.blueprint import oauth2 from .groups import user_group from .errors import UserRegistrationError -from .roles import user_roles as _user_roles +from .roles import assign_default_roles, user_roles as _user_roles from ..authentication.oauth2.resource_server import require_oauth -from ..authentication.users import User, save_user, set_user_password +from ..authentication.users import save_user, set_user_password from ..authentication.oauth2.models.oauth2token import token_by_access_token @oauth2.route("/user", methods=["GET"]) @@ -95,6 +95,7 @@ def register_user(): with db.cursor(conn) as cursor: user, _hashed_password = set_user_password( cursor, save_user(cursor, email, user_name), password) + assign_default_roles(cursor, user) return jsonify( { "user_id": user.user_id, diff --git a/migrations/auth/20230111_01_Wd6IZ-remove-create-group-privilege-from-group-leader.py b/migrations/auth/20230111_01_Wd6IZ-remove-create-group-privilege-from-group-leader.py new file mode 100644 index 0000000..7e7fda2 --- /dev/null +++ b/migrations/auth/20230111_01_Wd6IZ-remove-create-group-privilege-from-group-leader.py @@ -0,0 +1,40 @@ +""" +remove 'create-group' privilege from group-leader. +""" + +from yoyo import step + +__depends__ = {'20221219_03_PcTrb-create-authorisation-code-table'} + +steps = [ + step( + """ + DELETE FROM role_privileges + WHERE role_id='a0e67630-d502-4b9f-b23f-6805d0f30e30' + AND privilege_id='4842e2aa-38b9-4349-805e-0a99a9cf8bff' + """, + """ + INSERT INTO role_privileges VALUES + ('a0e67630-d502-4b9f-b23f-6805d0f30e30', + '4842e2aa-38b9-4349-805e-0a99a9cf8bff') + """), + step( + """ + INSERT INTO roles(role_id, role_name, user_editable) VALUES + ('ade7e6b0-ba9c-4b51-87d0-2af7fe39a347', 'group-creator', '0') + """, + """ + DELETE FROM roles WHERE role_id='ade7e6b0-ba9c-4b51-87d0-2af7fe39a347' + """), + step( + """ + INSERT INTO role_privileges VALUES + ('ade7e6b0-ba9c-4b51-87d0-2af7fe39a347', + '4842e2aa-38b9-4349-805e-0a99a9cf8bff') + """, + """ + DELETE FROM role_privileges + WHERE role_id='ade7e6b0-ba9c-4b51-87d0-2af7fe39a347' + AND privilege_id='4842e2aa-38b9-4349-805e-0a99a9cf8bff' + """) +] diff --git a/tests/unit/auth/fixtures/user_fixtures.py b/tests/unit/auth/fixtures/user_fixtures.py index 89b7e62..4e42abe 100644 --- a/tests/unit/auth/fixtures/user_fixtures.py +++ b/tests/unit/auth/fixtures/user_fixtures.py @@ -24,7 +24,9 @@ def fxtr_users(conn_after_auth_migrations):# pylint: disable=[redefined-outer-na query_user_roles = "INSERT INTO user_roles(user_id, role_id) VALUES (?, ?)" test_user_roles = ( ("ecb52977-3004-469e-9428-2a1856725c7f", - "a0e67630-d502-4b9f-b23f-6805d0f30e30"),) + "a0e67630-d502-4b9f-b23f-6805d0f30e30"), + ("ecb52977-3004-469e-9428-2a1856725c7f", + "ade7e6b0-ba9c-4b51-87d0-2af7fe39a347")) 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)) diff --git a/tests/unit/auth/test_roles.py b/tests/unit/auth/test_roles.py index 3fc146a..21d8e86 100644 --- a/tests/unit/auth/test_roles.py +++ b/tests/unit/auth/test_roles.py @@ -68,9 +68,6 @@ def test_create_role(# pylint: disable=[too-many-arguments] Privilege( privilege_id=uuid.UUID('3ebfe79c-d159-4629-8b38-772cf4bc2261'), privilege_name='view-group'), - Privilege( - privilege_id=uuid.UUID('4842e2aa-38b9-4349-805e-0a99a9cf8bff'), - privilege_name='create-group'), Privilege( privilege_id=uuid.UUID('5103cc68-96f8-4ebb-83a4-a31692402c9b'), privilege_name='assign-role'), @@ -97,7 +94,14 @@ def test_create_role(# pylint: disable=[too-many-arguments] privilege_name='transfer-group-leadership'), Privilege( privilege_id=uuid.UUID('f1bd3f42-567e-4965-9643-6d1a52ddee64'), - privilege_name='remove-group-member'))),), + privilege_name='remove-group-member'))), + Role( + role_id=uuid.UUID("ade7e6b0-ba9c-4b51-87d0-2af7fe39a347"), + role_name="group-creator", + privileges=( + Privilege( + privilege_id=uuid.UUID('4842e2aa-38b9-4349-805e-0a99a9cf8bff'), + privilege_name='create-group'),))), tuple(), tuple(), tuple())))) def test_user_roles(fxtr_group_user_roles, user, expected): """ -- cgit v1.2.3