diff options
author | Frederick Muriuki Muriithi | 2023-03-06 14:57:53 +0300 |
---|---|---|
committer | Frederick Muriuki Muriithi | 2023-03-06 14:57:53 +0300 |
commit | 98e93be1b8e5353656e18f1452026db6f2902e6c (patch) | |
tree | 2547ab9284e1a1718b35faf92d8aa68e9d42b283 /gn3/auth/authorisation/resources | |
parent | 4fc72af7e851f12a9f4edc98b0a55c66c9bf1b13 (diff) | |
download | genenetwork3-98e93be1b8e5353656e18f1452026db6f2902e6c.tar.gz |
auth: resources: Enable assigning a user roles on resources
Diffstat (limited to 'gn3/auth/authorisation/resources')
-rw-r--r-- | gn3/auth/authorisation/resources/models.py | 30 | ||||
-rw-r--r-- | gn3/auth/authorisation/resources/views.py | 38 |
2 files changed, 60 insertions, 8 deletions
diff --git a/gn3/auth/authorisation/resources/models.py b/gn3/auth/authorisation/resources/models.py index be1bc17..0a5b1ec 100644 --- a/gn3/auth/authorisation/resources/models.py +++ b/gn3/auth/authorisation/resources/models.py @@ -14,7 +14,8 @@ from .checks import authorised_for from ..checks import authorised_p from ..errors import NotFoundError, AuthorisationError -from ..groups.models import Group, user_group, group_by_id, is_group_leader +from ..groups.models import ( + Group, GroupRole, user_group, group_by_id, is_group_leader) class MissingGroupError(AuthorisationError): """Raised for any resource operation without a group.""" @@ -477,3 +478,30 @@ def attach_resources_data( cursor, rscs) for category, rscs in organised.items()) for resource in categories) + +@authorised_p( + ("group:user:assign-role",), + "You cannot assign roles to users for this group.", + oauth2_scope="profile group role resource") +def assign_resource_user( + conn: db.DbConnection, resource: Resource, user: User, + role: GroupRole) -> dict: + """Assign `role` to `user` for the specific `resource`.""" + with db.cursor(conn) as cursor: + cursor.execute( + "INSERT INTO " + "group_user_roles_on_resources(group_id, user_id, role_id, " + "resource_id) " + "VALUES (?, ?, ?, ?) " + "ON CONFLICT (group_id, user_id, role_id, resource_id) " + "DO NOTHING", + (str(resource.group.group_id), str(user.user_id), + str(role.role.role_id), str(resource.resource_id))) + return { + "resource": dictify(resource), + "user": dictify(user), + "role": dictify(role), + "description": ( + f"The user '{user.name}'({user.email}) was assigned the " + f"'{role.role.role_name}' role on resource with ID " + f"'{resource.resource_id}'.")} diff --git a/gn3/auth/authorisation/resources/views.py b/gn3/auth/authorisation/resources/views.py index e1386ab..6d4098a 100644 --- a/gn3/auth/authorisation/resources/views.py +++ b/gn3/auth/authorisation/resources/views.py @@ -9,17 +9,17 @@ from gn3.auth.db_utils import with_db_connection from .checks import authorised_for from .models import ( - resource_by_id, resource_categories, link_data_to_resource, - resource_category_by_id, unlink_data_from_resource, + resource_by_id, resource_categories, assign_resource_user, + link_data_to_resource, resource_category_by_id, unlink_data_from_resource, create_resource as _create_resource) from ..roles import Role -from ..groups.models import Group, GroupRole from ..errors import InvalidData, AuthorisationError +from ..groups.models import Group, GroupRole, group_role_by_id from ... import db from ...dictify import dictify -from ...authentication.users import User +from ...authentication.users import User, user_by_email from ...authentication.oauth2.resource_server import require_oauth resources = Blueprint("resources", __name__) @@ -101,7 +101,7 @@ def unlink_data(): except AssertionError as aserr: raise InvalidData(aserr.args[0]) from aserr -@resources.route("<uuid:resource_id>/users", methods=["GET"]) +@resources.route("<uuid:resource_id>/user/list", methods=["GET"]) @require_oauth("profile group resource") def resource_users(resource_id: uuid.UUID): """Retrieve all users with access to the given resource.""" @@ -115,8 +115,8 @@ def resource_users(resource_id: uuid.UUID): with db.cursor(conn) as cursor: def __organise_users_n_roles__(users_n_roles, row): user_id = uuid.UUID(row["user_id"]) - user = users_n_roles.get( - user_id, User(user_id, row["email"], row["name"])) + user = users_n_roles.get(user_id, {}).get( + "user", User(user_id, row["email"], row["name"])) role = GroupRole( uuid.UUID(row["group_role_id"]), resource.group, @@ -157,3 +157,27 @@ def resource_users(resource_id: uuid.UUID): user_row for user_id, user_row in with_db_connection(__the_users__).items())) return jsonify(tuple(results)) + +@resources.route("<uuid:resource_id>/user/assign", methods=["POST"]) +@require_oauth("profile group resource role") +def assign_role_to_user(resource_id: uuid.UUID) -> Response: + """Assign a role on the specified resource to a user.""" + with require_oauth.acquire("profile group resource role") as the_token: + try: + form = request.form + group_role_id = form.get("group_role_id", "") + user_email = form.get("user_email", "") + assert bool(group_role_id), "The role must be provided." + assert bool(user_email), "The user email must be provided." + + def __assign__(conn: db.DbConnection) -> dict: + resource = resource_by_id(conn, the_token.user, resource_id) + user = user_by_email(conn, user_email) + return assign_resource_user( + conn, resource, user, + group_role_by_id(conn, resource.group, + uuid.UUID(group_role_id))) + except AssertionError as aserr: + raise AuthorisationError(aserr.args[0]) from aserr + + return jsonify(with_db_connection(__assign__)) |