about summary refs log tree commit diff
path: root/gn3/auth
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2023-04-12 11:41:43 +0300
committerFrederick Muriuki Muriithi2023-04-12 11:41:43 +0300
commit7022a3145586a7e5298bf2bf50226eb63a51d563 (patch)
tree8dd48acb5934be72b12ea1044bf3a71e5f935bce /gn3/auth
parent54e8769a8cfbf12967c26598b97ce0e88d891e86 (diff)
downloadgenenetwork3-7022a3145586a7e5298bf2bf50226eb63a51d563.tar.gz
auth: Enable listing of unlinked genotype/mRNA group data.
Diffstat (limited to 'gn3/auth')
-rw-r--r--gn3/auth/authorisation/groups/views.py93
-rw-r--r--gn3/auth/authorisation/resources/models.py16
2 files changed, 57 insertions, 52 deletions
diff --git a/gn3/auth/authorisation/groups/views.py b/gn3/auth/authorisation/groups/views.py
index 6f1a6df..d7a46c0 100644
--- a/gn3/auth/authorisation/groups/views.py
+++ b/gn3/auth/authorisation/groups/views.py
@@ -14,11 +14,11 @@ from gn3.auth.db_utils import with_db_connection
 
 from .data import link_data_to_group, retrieve_ungrouped_data
 from .models import (
-    user_group, all_groups, DUMMY_GROUP, GroupRole, group_by_id, join_requests,
-    group_role_by_id, GroupCreationError, accept_reject_join_request,
-    group_users as _group_users, create_group as _create_group,
-    add_privilege_to_group_role, delete_privilege_to_group_role,
-    create_group_role as _create_group_role)
+    Group, user_group, all_groups, DUMMY_GROUP, GroupRole, group_by_id,
+    join_requests, group_role_by_id, GroupCreationError,
+    accept_reject_join_request, group_users as _group_users,
+    create_group as _create_group, add_privilege_to_group_role,
+    delete_privilege_to_group_role, create_group_role as _create_group_role)
 
 from ..roles.models import Role
 from ..checks import authorised_p
@@ -138,6 +138,42 @@ def reject_join_requests() -> Response:
             accept_reject_join_request, request_id=request_id,
             user=the_token.user, status="REJECTED")))
 
+def unlinked_mrna_data(
+        conn: db.DbConnection, group: Group) -> tuple[dict, ...]:
+    """
+    Retrieve all mRNA Assay data linked to a group but not linked to any
+    resource.
+    """
+    query = (
+        "SELECT lmd.* FROM linked_mrna_data lmd "
+        "LEFT JOIN mrna_resources mr ON lmd.data_link_id=mr.data_link_id "
+        "WHERE lmd.group_id=? AND mr.data_link_id IS NULL")
+    with db.cursor(conn) as cursor:
+        cursor.execute(query, (str(group.group_id),))
+        return tuple(dict(row) for row in cursor.fetchall())
+
+def unlinked_genotype_data(
+        conn: db.DbConnection, group: Group) -> tuple[dict, ...]:
+    """
+    Retrieve all genotype data linked to a group but not linked to any resource.
+    """
+    query = (
+        "SELECT lgd.* FROM linked_genotype_data lgd "
+        "LEFT JOIN genotype_resources gr ON lgd.data_link_id=gr.data_link_id "
+        "WHERE lgd.group_id=? AND gr.data_link_id IS NULL")
+    with db.cursor(conn) as cursor:
+        cursor.execute(query, (str(group.group_id),))
+        return tuple(dict(row) for row in cursor.fetchall())
+
+def unlinked_phenotype_data(
+        conn: db.DbConnection, group: Group) -> tuple[dict, ...]:#pylint: disable=[unused-argument]
+    """
+    Retrieve all phenotype data linked to a group but not linked to any
+    resource.
+    """
+    raise NotImplementedError(
+        "The feature to fetch unlinked phenotype data is not implemented yet.")
+
 @groups.route("/<string:resource_type>/unlinked-data")
 @require_oauth("profile group resource")
 def unlinked_data(resource_type: str) -> Response:
@@ -147,48 +183,19 @@ def unlinked_data(resource_type: str) -> Response:
 
     with require_oauth.acquire("profile group resource") as the_token:
         db_uri = current_app.config["AUTH_DB"]
-        with db.connection(db_uri) as conn, db.cursor(conn) as cursor:
+        with db.connection(db_uri) as conn:
             ugroup = user_group(conn, the_token.user).maybe(# type: ignore[misc]
                 DUMMY_GROUP, lambda grp: grp)
             if ugroup == DUMMY_GROUP:
                 return jsonify(tuple())
-            type_filter = {
-                "all": "",
-                "mrna": 'WHERE dataset_type="mRNA"',
-                "genotype": 'WHERE dataset_type="Genotype"',
-                "phenotype": 'WHERE dataset_type="Phenotype"'
-            }[resource_type]
-
-            except_filter = (
-                "SELECT group_id, dataset_type, "
-                "dataset_id AS dataset_or_trait_id FROM mrna_resources "
-                "UNION "
-                "SELECT group_id, dataset_type, "
-                "trait_id AS dataset_or_trait_id FROM genotype_resources "
-                "UNION "
-                "SELECT group_id, dataset_type, "
-                "trait_id AS dataset_or_trait_id FROM phenotype_resources")
-
-            ids_query = (
-                "SELECT * FROM ("
-                "SELECT group_id, dataset_type, dataset_or_trait_id "
-                "FROM linked_group_data "
-                f"EXCEPT SELECT * FROM ({except_filter})"
-                f") {type_filter}")
-            cursor.execute(ids_query)
-            ids = cursor.fetchall()
-
-            if ids:
-                clause = ", ".join(["(?, ?, ?)"] * len(ids))
-                data_query = (
-                    "SELECT * FROM linked_group_data "
-                    "WHERE (group_id, dataset_type, dataset_or_trait_id) "
-                    f"IN (VALUES {clause}) ")
-                params = tuple(item for sublist in
-                               ((row[0], row[1], row[2]) for row in ids)
-                               for item in sublist)
-                cursor.execute(data_query, params)
-                return jsonify(tuple(dict(row) for row in cursor.fetchall()))
+
+            unlinked_fns = {
+                "mrna": unlinked_mrna_data,
+                "genotype": unlinked_genotype_data,
+                "phenotype": unlinked_phenotype_data
+            }
+            return jsonify(tuple(
+                dict(row) for row in unlinked_fns[resource_type](conn, ugroup)))
 
     return jsonify(tuple())
 
diff --git a/gn3/auth/authorisation/resources/models.py b/gn3/auth/authorisation/resources/models.py
index afda5e8..4c71ade 100644
--- a/gn3/auth/authorisation/resources/models.py
+++ b/gn3/auth/authorisation/resources/models.py
@@ -217,9 +217,8 @@ def mrna_resource_data(
         cursor: db.DbCursor, resource_id: UUID) -> Sequence[sqlite3.Row]:
     """Fetch data linked to a mRNA resource"""
     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 lmr"
+        " ON mr.data_link_id=lmr.data_link_id "
         "WHERE mr.resource_id=?",
         (str(resource_id),))
     return cursor.fetchall()
@@ -229,9 +228,8 @@ def genotype_resource_data(
     """Fetch data linked to a Genotype resource"""
     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) "
+        "INNER JOIN linked_genotype_data AS lgd "
+        "ON gr.data_link_id=lgd.data_link_id "
         "WHERE gr.resource_id=?",
         (str(resource_id),))
     return cursor.fetchall()
@@ -241,9 +239,9 @@ def phenotype_resource_data(
     """Fetch data linked to a Phenotype resource"""
     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) "
+        "INNER JOIN linked_phenotype_data AS lpd "
+        "ON (pr.trait_id=lpd.dataset_or_trait_id "
+        "AND pr.dataset_type=lpd.dataset_type) "
         "WHERE pr.resource_id=?",
         (str(resource_id),))
     return cursor.fetchall()