From e66e0d24f76458aade54056e18de7d4e0762d06c Mon Sep 17 00:00:00 2001
From: Frederick Muriuki Muriithi
Date: Tue, 28 Feb 2023 12:45:57 +0300
Subject: auth: Unlink data from resources

Enable the data editor to unlink data from a particular resource.
---
 gn3/auth/authorisation/data/views.py | 62 +++++++++++++++++++++++-------------
 1 file changed, 40 insertions(+), 22 deletions(-)

(limited to 'gn3/auth/authorisation/data')

diff --git a/gn3/auth/authorisation/data/views.py b/gn3/auth/authorisation/data/views.py
index 76f4158..08032db 100644
--- a/gn3/auth/authorisation/data/views.py
+++ b/gn3/auth/authorisation/data/views.py
@@ -1,16 +1,15 @@
 """Handle data endpoints."""
+import uuid
 import json
-from functools import reduce
 
-from flask import request, Response, Blueprint, current_app as app
 from authlib.integrations.flask_oauth2.errors import _HTTPException
-
-from gn3 import db_utils as gn3db
+from flask import request, jsonify, Response, Blueprint, current_app as app
 
 from gn3.db.traits import build_trait_name
 
 from gn3.auth import db
 from gn3.auth.authentication.oauth2.resource_server import require_oauth
+from gn3.auth.authorisation.resources.checks import authorised_for
 from gn3.auth.authorisation.resources.models import (
     user_resources, public_resources, attach_resources_data)
 
@@ -20,12 +19,22 @@ data = Blueprint("data", __name__)
 def authorisation() -> Response:
     """Retrive the authorisation level for datasets/traits for the user."""
     db_uri = app.config["AUTH_DB"]
-    the_user = "ANONYMOUS"
-    with db.connection(db_uri) as auth_conn, gn3db.database_connection() as gn3conn:
+    privileges = {}
+    with db.connection(db_uri) as auth_conn:
         try:
             with require_oauth.acquire("profile group resource") as the_token:
                 resources = attach_resources_data(
                     auth_conn, user_resources(auth_conn, the_token.user))
+                privileges = {
+                    resource_id: ("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()
+                    if is_authorised
+                }
         except _HTTPException as exc:
             err_msg = json.loads(exc.body)
             if err_msg["error"] == "missing_authorization":
@@ -37,31 +46,40 @@ def authorisation() -> Response:
         # Access endpoint with somethin like:
         # curl -X GET http://127.0.0.1:8080/api/oauth2/data/authorisation \
         #    -H "Content-Type: application/json" \
-        #    -d '{"traits": ["HC_M2_0606_P::1442370_at", "BXDGeno::01.001.695", "BXDPublish::10001"]}'
+        #    -d '{"traits": ["HC_M2_0606_P::1442370_at", "BXDGeno::01.001.695",
+        #        "BXDPublish::10001"]}'
+        data_to_resource_map = {
+            (f"{data_item['dataset_type'].lower()}::"
+             f"{data_item['dataset_name']}"): 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
+            }}
+
         args = request.get_json()
-        traits_names = args["traits"]
+        traits_names = args["traits"] # type: ignore[index]
         def __translate__(val):
             return {
                 "ProbeSet": "mRNA",
                 "Geno": "Genotype",
                 "Publish": "Phenotype"
             }[val]
-        traits = (
+        return jsonify(tuple(
             {
                 **{key:trait[key] for key in ("trait_fullname", "trait_name")},
                 "dataset_name": trait["db"]["dataset_name"],
-                "dataset_type": __translate__(trait["db"]["dataset_type"])
+                "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']}",
+                        uuid.UUID("4afa415e-94cb-4189-b2c6-f9ce2b6a878d")),
+                    tuple())
             } for trait in
             (build_trait_name(trait_fullname)
-             for trait_fullname in traits_names))
-        # Retrieve the dataset/trait IDs from traits above
-
-        # Compare the traits/dataset names/ids from request with resources' data
-        # - Any trait not in resources' data is marked inaccessible
-        # - Any trait in resources' data:
-        #   - IF public is marked readable
-        #   - IF private and user has read privilege: mark readable
-        #   - ELSE mark inaccessible
-        
-
-        return "NOT COMPLETED! ..."
+             for trait_fullname in traits_names)))
-- 
cgit v1.2.3