aboutsummaryrefslogtreecommitdiff
path: root/gn3/auth
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2023-04-24 11:45:45 +0300
committerFrederick Muriuki Muriithi2023-04-24 11:45:45 +0300
commit3e2198e39bc229553d118f367fbd2f9932a9a76b (patch)
tree8c388b14df38240a159358475ecf35f85b6d4d9c /gn3/auth
parent993420e616e143684deb1c11565b6a8286cde37f (diff)
downloadgenenetwork3-3e2198e39bc229553d118f367fbd2f9932a9a76b.tar.gz
auth: Return the actual privileges for the user
Previously, the `oauth2/data/authorisation` endpoint was returning hard-coded values for the privileges assigned to the user for each resource. In this change, we rework to return the actual privileges for the user.
Diffstat (limited to 'gn3/auth')
-rw-r--r--gn3/auth/authorisation/data/views.py38
-rw-r--r--gn3/auth/authorisation/resources/models.py21
-rw-r--r--gn3/auth/authorisation/users/models.py47
3 files changed, 84 insertions, 22 deletions
diff --git a/gn3/auth/authorisation/data/views.py b/gn3/auth/authorisation/data/views.py
index 81b3e2f..d2bdbf3 100644
--- a/gn3/auth/authorisation/data/views.py
+++ b/gn3/auth/authorisation/data/views.py
@@ -22,6 +22,8 @@ from gn3.auth.authorisation.errors import InvalidData, NotFoundError
from gn3.auth.authorisation.groups.models import group_by_id
+from gn3.auth.authorisation.users.models import user_resource_roles
+
from gn3.auth.authorisation.resources.checks import authorised_for
from gn3.auth.authorisation.resources.models import (
user_resources, public_resources, attach_resources_data)
@@ -53,14 +55,17 @@ def authorisation() -> Response:
with require_oauth.acquire("profile group resource") as the_token:
resources = attach_resources_data(
auth_conn, user_resources(auth_conn, the_token.user))
+ resources_roles = user_resource_roles(auth_conn, the_token.user)
privileges = {
- resource_id: ("group:resource:view-resource",)
+ resource_id: tuple(
+ privilege.privilege_id
+ for roles in resources_roles[resource_id]
+ for privilege in roles.privileges)#("group:resource:view-resource",)
for resource_id, is_authorised
in authorised_for(
auth_conn, the_token.user,
("group:resource:view-resource",), tuple(
- resource.resource_id for resource in resources
- if not resource.public)).items()
+ resource.resource_id for resource in resources)).items()
if is_authorised
}
except _HTTPException as exc:
@@ -76,18 +81,26 @@ def authorisation() -> Response:
# -H "Content-Type: application/json" \
# -d '{"traits": ["HC_M2_0606_P::1442370_at", "BXDGeno::01.001.695",
# "BXDPublish::10001"]}'
+ def __gen_key__(resource, data_item):
+ if resource.resource_category.resource_category_key.lower() == "phenotype":
+ return (
+ f"{resource.resource_category.resource_category_key.lower()}::"
+ f"{data_item['dataset_name']}::{data_item['PublishXRefId']}")
+ return (
+ f"{resource.resource_category.resource_category_key.lower()}::"
+ f"{data_item['dataset_name']}")
+
data_to_resource_map = {
- (f"{data_item['dataset_type'].lower()}::"
- f"{data_item['dataset_name']}"): resource.resource_id
+ __gen_key__(resource, data_item): resource.resource_id
for resource in resources
for data_item in resource.resource_data
}
privileges = {
- **privileges,
**{
resource.resource_id: ("system:resource:public-read",)
for resource in resources if resource.public
- }}
+ },
+ **privileges}
args = request.get_json()
traits_names = args["traits"] # type: ignore[index]
@@ -97,6 +110,14 @@ def authorisation() -> Response:
"Geno": "Genotype",
"Publish": "Phenotype"
}[val]
+
+ def __trait_key__(trait):
+ dataset_type = __translate__(trait['db']['dataset_type']).lower()
+ dataset_name = trait["db"]["dataset_name"]
+ if dataset_type == "phenotype":
+ return f"{dataset_type}::{dataset_name}::{trait['trait_name']}"
+ return f"{dataset_type}::{dataset_name}"
+
return jsonify(tuple(
{
**{key:trait[key] for key in ("trait_fullname", "trait_name")},
@@ -104,8 +125,7 @@ def authorisation() -> Response:
"dataset_type": __translate__(trait["db"]["dataset_type"]),
"privileges": privileges.get(
data_to_resource_map.get(
- f"{__translate__(trait['db']['dataset_type']).lower()}"
- f"::{trait['db']['dataset_name']}",
+ __trait_key__(trait),
uuid.UUID("4afa415e-94cb-4189-b2c6-f9ce2b6a878d")),
tuple())
} for trait in
diff --git a/gn3/auth/authorisation/resources/models.py b/gn3/auth/authorisation/resources/models.py
index bc88691..e54ec48 100644
--- a/gn3/auth/authorisation/resources/models.py
+++ b/gn3/auth/authorisation/resources/models.py
@@ -423,9 +423,8 @@ def attach_mrna_resources_data(
"""Attach linked data to mRNA Assay resources"""
placeholders = ", ".join(["?"] * len(resources))
cursor.execute(
- "SELECT * FROM mrna_resources AS mr INNER JOIN linked_group_data AS lgd"
- " ON (mr.dataset_id=lgd.dataset_or_trait_id "
- "AND mr.dataset_type=lgd.dataset_type) "
+ "SELECT * FROM mrna_resources AS mr INNER JOIN linked_mrna_data AS lmd"
+ " ON mr.data_link_id=lmd.data_link_id "
f"WHERE mr.resource_id IN ({placeholders})",
tuple(str(resource.resource_id) for resource in resources))
return __attach_data__(cursor.fetchall(), resources)
@@ -436,10 +435,9 @@ def attach_genotype_resources_data(
placeholders = ", ".join(["?"] * len(resources))
cursor.execute(
"SELECT * FROM genotype_resources AS gr "
- "INNER JOIN linked_group_data AS lgd "
- "ON (gr.trait_id=lgd.dataset_or_trait_id "
- "AND gr.dataset_type=lgd.dataset_type) "
- f"WHERE gr.resource_id IN {placeholders}",
+ "INNER JOIN linked_genotype_data AS lgd "
+ "ON gr.data_link_id=lgd.data_link_id "
+ f"WHERE gr.resource_id IN ({placeholders})",
tuple(str(resource.resource_id) for resource in resources))
return __attach_data__(cursor.fetchall(), resources)
@@ -449,10 +447,9 @@ def attach_phenotype_resources_data(
placeholders = ", ".join(["?"] * len(resources))
cursor.execute(
"SELECT * FROM phenotype_resources AS pr "
- "INNER JOIN linked_group_data AS lgd "
- "ON (pr.trait_id=lgd.dataset_or_trait_id "
- "AND pr.dataset_type=lgd.dataset_type) "
- f"WHERE pr.resource_id IN {placeholders}",
+ "INNER JOIN linked_phenotype_data AS lpd "
+ "ON pr.data_link_id=lpd.data_link_id "
+ f"WHERE pr.resource_id IN ({placeholders})",
tuple(str(resource.resource_id) for resource in resources))
return __attach_data__(cursor.fetchall(), resources)
@@ -532,8 +529,6 @@ def save_resource(
conn, user, ("group:resource:edit-resource",), (resource_id,))
if authorised[resource_id]:
with db.cursor(conn) as cursor:
- params = {**dictify(resource), "public": 1 if resource.public else 0}
- print(f"THE PARAMS: {params}")
cursor.execute(
"UPDATE resources SET "
"resource_name=:resource_name, "
diff --git a/gn3/auth/authorisation/users/models.py b/gn3/auth/authorisation/users/models.py
index 844a8a9..8cfc1af 100644
--- a/gn3/auth/authorisation/users/models.py
+++ b/gn3/auth/authorisation/users/models.py
@@ -1,8 +1,11 @@
"""Functions for acting on users."""
import uuid
+from functools import reduce
from gn3.auth import db
+from gn3.auth.authorisation.roles.models import Role
from gn3.auth.authorisation.checks import authorised_p
+from gn3.auth.authorisation.privileges import Privilege
from gn3.auth.authentication.users import User
@@ -17,3 +20,47 @@ def list_users(conn: db.DbConnection) -> tuple[User, ...]:
return tuple(
User(uuid.UUID(row["user_id"]), row["email"], row["name"])
for row in cursor.fetchall())
+
+def __build_resource_roles__(rows):
+ def __build_roles__(roles, row):
+ role_id = uuid.UUID(row["role_id"])
+ priv = Privilege(row["privilege_id"], row["privilege_description"])
+ role = roles.get(role_id, Role(
+ role_id, row["role_name"], tuple()))
+ return {
+ **roles,
+ role_id: Role(role_id, role.role_name, role.privileges + (priv,))
+ }
+ def __build__(acc, row):
+ resource_id = uuid.UUID(row["resource_id"])
+ return {
+ **acc,
+ resource_id: __build_roles__(acc.get(resource_id, {}), row)
+ }
+ return {
+ resource_id: tuple(roles.values())
+ for resource_id, roles in reduce(__build__, rows, {}).items()
+ }
+
+# @authorised_p(
+# ("",),
+# ("You do not have the appropriate privileges to view a user's roles on "
+# "resources."))
+def user_resource_roles(conn: db.DbConnection, user: User) -> dict[uuid.UUID, tuple[Role, ...]]:
+ """Fetch all the user's roles on resources."""
+ with db.cursor(conn) as cursor:
+ cursor.execute(
+ "SELECT res.*, rls.*, p.*"
+ "FROM resources AS res INNER JOIN "
+ "group_user_roles_on_resources AS guror "
+ "ON res.resource_id=guror.resource_id "
+ "LEFT JOIN roles AS rls "
+ "ON guror.role_id=rls.role_id "
+ "LEFT JOIN role_privileges AS rp "
+ "ON rls.role_id=rp.role_id "
+ "LEFT JOIN privileges AS p "
+ "ON rp.privilege_id=p.privilege_id "
+ "WHERE guror.user_id = ?",
+ (str(user.user_id),))
+ return __build_resource_roles__(
+ (dict(row) for row in cursor.fetchall()))