diff options
Diffstat (limited to 'gn_auth/auth/authorisation/resources/models.py')
-rw-r--r-- | gn_auth/auth/authorisation/resources/models.py | 119 |
1 files changed, 68 insertions, 51 deletions
diff --git a/gn_auth/auth/authorisation/resources/models.py b/gn_auth/auth/authorisation/resources/models.py index 2855c70..31371fd 100644 --- a/gn_auth/auth/authorisation/resources/models.py +++ b/gn_auth/auth/authorisation/resources/models.py @@ -4,8 +4,6 @@ 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 @@ -15,10 +13,12 @@ from gn_auth.auth.authorisation.privileges import Privilege from gn_auth.auth.authorisation.checks import authorised_p from gn_auth.auth.errors import NotFoundError, AuthorisationError -from .checks import authorised_for -from .base import Resource, ResourceCategory -from .common import assign_resource_owner_role +from .system.models import system_resource +from .checks import authorised_for, authorised_for_spec +from .base import Resource, ResourceCategory, resource_from_dbrow +from .common import assign_resource_owner_role, grant_access_to_sysadmins from .groups.models import Group, is_group_leader +from .inbredset.models import resource_data as inbredset_resource_data from .mrna import ( resource_data as mrna_resource_data, attach_resources_data as mrna_attach_resources_data, @@ -29,29 +29,18 @@ from .genotypes.models import ( attach_resources_data as genotype_attach_resources_data, link_data_to_resource as genotype_link_data_to_resource, unlink_data_from_resource as genotype_unlink_data_from_resource) -from .phenotype import ( +from .phenotypes.models import ( resource_data as phenotype_resource_data, attach_resources_data as phenotype_attach_resources_data, link_data_to_resource as phenotype_link_data_to_resource, unlink_data_from_resource as phenotype_unlink_data_from_resource) -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") -def create_resource(# pylint: disable=[too-many-arguments] - cursor: sqlite3.Cursor, +def create_resource(# pylint: disable=[too-many-arguments, too-many-positional-arguments] + conn: db.DbConnection, resource_name: str, resource_category: ResourceCategory, user: User, @@ -59,29 +48,48 @@ def create_resource(# pylint: disable=[too-many-arguments] public: bool ) -> Resource: """Create a resource item.""" - resource = Resource(uuid4(), resource_name, resource_category, public) - cursor.execute( - "INSERT INTO resources VALUES (?, ?, ?, ?)", - (str(resource.resource_id), - resource_name, - str(resource.resource_category.resource_category_id), - 1 if resource.public else 0)) - # TODO: @fredmanglis,@rookie101 - # 1. Move the actions below into a (the?) hooks system - # 2. Do more checks: A resource can have varying hooks depending on type - # e.g. if mRNA, pheno or geno resource, assign: - # - "resource-owner" - # if inbredset-group, assign: - # - "resource-owner", - # - "inbredset-group-owner" etc. - # if resource is of type "group", assign: - # - group-leader - cursor.execute("INSERT INTO resource_ownership (group_id, resource_id) " - "VALUES (?, ?)", - (str(group.group_id), str(resource.resource_id))) - assign_resource_owner_role(cursor, resource.resource_id, user.user_id) - - return resource + with db.cursor(conn) as cursor: + resource = Resource(uuid4(), resource_name, resource_category, public) + cursor.execute( + "INSERT INTO resources VALUES (?, ?, ?, ?)", + (str(resource.resource_id), + resource_name, + str(resource.resource_category.resource_category_id), + 1 if resource.public else 0)) + # TODO: @fredmanglis,@rookie101 + # 1. Move the actions below into a (the?) hooks system + # 2. Do more checks: A resource can have varying hooks depending on type + # e.g. if mRNA, pheno or geno resource, assign: + # - "resource-owner" + # if inbredset-group, assign: + # - "resource-owner", + # - "inbredset-group-owner" etc. + # if resource is of type "group", assign: + # - group-leader + cursor.execute("INSERT INTO resource_ownership (group_id, resource_id) " + "VALUES (?, ?)", + (str(group.group_id), str(resource.resource_id))) + assign_resource_owner_role(cursor, resource.resource_id, user.user_id) + grant_access_to_sysadmins( + cursor, resource.resource_id, system_resource(conn).resource_id) + + return resource + + +def delete_resource(conn: db.DbConnection, resource_id: UUID): + """Delete a resource.""" + with db.cursor(conn) as cursor: + cursor.execute("DELETE FROM user_roles WHERE resource_id=?", + (str(resource_id),)) + cursor.execute("DELETE FROM resource_roles WHERE resource_id=?", + (str(resource_id),)) + cursor.execute("DELETE FROM group_resources WHERE resource_id=?", + (str(resource_id),)) + cursor.execute("DELETE FROM resource_ownership WHERE resource_id=?", + (str(resource_id),)) + cursor.execute("DELETE FROM resources WHERE resource_id=?", + (str(resource_id),)) + def resource_category_by_id( conn: db.DbConnection, category_id: UUID) -> ResourceCategory: @@ -144,8 +152,10 @@ def user_resources(conn: db.DbConnection, user: User) -> Sequence[Resource]: """List the resources available to the user""" with db.cursor(conn) as cursor: cursor.execute( - ("SELECT r.*, rc.resource_category_key, " - "rc.resource_category_description FROM user_roles AS ur " + ("SELECT DISTINCT(r.resource_id), r.resource_name, " + "r.resource_category_id, r.public, 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 " @@ -168,7 +178,8 @@ def resource_data(conn, resource, offset: int = 0, limit: Optional[int] = None) "genotype-metadata": lambda *args: tuple(), "mrna-metadata": lambda *args: tuple(), "system": lambda *args: tuple(), - "group": lambda *args: tuple() + "group": lambda *args: tuple(), + "inbredset-group": inbredset_resource_data, } with db.cursor(conn) as cursor: return tuple( @@ -196,9 +207,11 @@ def attach_resource_data(cursor: db.DbCursor, resource: Resource) -> Resource: def resource_by_id( conn: db.DbConnection, user: User, resource_id: UUID) -> Resource: """Retrieve a resource by its ID.""" - if not authorised_for( - conn, user, ("group:resource:view-resource",), - (resource_id,))[resource_id]: + if not authorised_for_spec( + conn, + user.user_id, + resource_id, + "(OR group:resource:view-resource system:resource:view)"): raise AuthorisationError( "You are not authorised to access resource with id " f"'{resource_id}'.") @@ -216,8 +229,12 @@ def resource_by_id( raise NotFoundError(f"Could not find a resource with id '{resource_id}'") def link_data_to_resource( - conn: db.DbConnection, user: User, resource_id: UUID, dataset_type: str, - data_link_id: UUID) -> dict: + conn: db.DbConnection, + user: User, + resource_id: UUID, + dataset_type: str, + data_link_ids: tuple[UUID, ...] +) -> tuple[dict, ...]: """Link data to resource.""" if not authorised_for( conn, user, ("group:resource:edit-resource",), @@ -232,7 +249,7 @@ def link_data_to_resource( "mrna": mrna_link_data_to_resource, "genotype": genotype_link_data_to_resource, "phenotype": phenotype_link_data_to_resource, - }[dataset_type.lower()](conn, resource, data_link_id) + }[dataset_type.lower()](conn, resource, data_link_ids) def unlink_data_from_resource( conn: db.DbConnection, user: User, resource_id: UUID, data_link_id: UUID): |