aboutsummaryrefslogtreecommitdiff
path: root/gn3
diff options
context:
space:
mode:
Diffstat (limited to 'gn3')
-rw-r--r--gn3/auth/authorisation/data/genotypes.py45
-rw-r--r--gn3/auth/authorisation/data/views.py34
2 files changed, 71 insertions, 8 deletions
diff --git a/gn3/auth/authorisation/data/genotypes.py b/gn3/auth/authorisation/data/genotypes.py
index 690293c..fe06726 100644
--- a/gn3/auth/authorisation/data/genotypes.py
+++ b/gn3/auth/authorisation/data/genotypes.py
@@ -1,11 +1,14 @@
"""Handle linking of Genotype data to the Auth(entic|oris)ation system."""
+import uuid
from typing import Iterable
from MySQLdb.cursors import DictCursor
import gn3.auth.db as authdb
import gn3.db_utils as gn3db
+from gn3.auth.dictify import dictify
from gn3.auth.authorisation.checks import authorised_p
+from gn3.auth.authorisation.groups.models import Group
def linked_genotype_data(conn: authdb.DbConnection) -> Iterable[dict]:
"""Retrive genotype data that is linked to user groups."""
@@ -39,11 +42,11 @@ def ungrouped_genotype_data(
query = query + "WHERE "
if len(params) > 0:
- paramstr = ", ".join(["(?, ?, ?)"] * len(params))
+ paramstr = ", ".join(["(%s, %s, %s)"] * len(params))
query = query + (
- "(s.SpeciesId, iset.InbredSetId, GenoFreezeId) "
+ "(s.SpeciesId, iset.InbredSetId, gf.Id) "
f"NOT IN ({paramstr}) "
- "AND ")
+ ) + ("AND " if bool(search_query) else "")
if bool(search_query):
query = query + (
@@ -51,7 +54,41 @@ def ungrouped_genotype_data(
params = params + ((search_query,),)# type: ignore[operator]
query = query + f"LIMIT {int(limit)} OFFSET {int(offset)}"
+ final_params = tuple(item for sublist in params for item in sublist)
with gn3conn.cursor(DictCursor) as cursor:
cursor.execute(
- query, tuple(item for sublist in params for item in sublist))
+ query, final_params)
return tuple(row for row in cursor.fetchall())
+
+@authorised_p(
+ ("system:data:link-to-group",),
+ error_description=(
+ "You do not have sufficient privileges to link data to (a) "
+ "group(s)."),
+ oauth2_scope="profile group resource")
+def link_genotype_data(
+ conn: authdb.DbConnection, group: Group, datasets: dict) -> dict:
+ """Link genotye `datasets` to `group`."""
+ with authdb.cursor(conn) as cursor:
+ cursor.executemany(
+ "INSERT INTO linked_genotype_data VALUES "
+ "(:data_link_id, :group_id, :SpeciesId, :InbredSetId, "
+ ":GenoFreezeId, :dataset_name, :dataset_fullname, "
+ ":dataset_shortname) "
+ "ON CONFLICT (SpeciesId, InbredSetId, GenoFreezeId) DO NOTHING",
+ tuple({
+ "data_link_id": str(uuid.uuid4()),
+ "group_id": str(group.group_id),
+ **{
+ key: value for key,value in dataset.items() if key in (
+ "GenoFreezeId", "InbredSetId", "SpeciesId",
+ "dataset_fullname", "dataset_name", "dataset_shortname")
+ }
+ } for dataset in datasets))
+ return {
+ "description": (
+ f"Successfully linked {len(datasets)} to group "
+ f"'{group.group_name}'."),
+ "group": dictify(group),
+ "datasets": datasets
+ }
diff --git a/gn3/auth/authorisation/data/views.py b/gn3/auth/authorisation/data/views.py
index 70b14d7..55a7373 100644
--- a/gn3/auth/authorisation/data/views.py
+++ b/gn3/auth/authorisation/data/views.py
@@ -6,7 +6,7 @@ import random
import string
import datetime
from functools import reduce, partial
-from typing import Sequence, Iterable
+from typing import Any, Sequence, Iterable
import redis
from MySQLdb.cursors import DictCursor
@@ -21,14 +21,14 @@ from gn3.auth import db
from gn3.auth.dictify import dictify
from gn3.auth.db_utils import with_db_connection
-from gn3.auth.authorisation.errors import NotFoundError
+from gn3.auth.authorisation.errors import InvalidData, NotFoundError
from gn3.auth.authorisation.roles.models import(
revoke_user_role_by_name, assign_user_role_by_name)
from gn3.auth.authorisation.groups.data import retrieve_ungrouped_data
from gn3.auth.authorisation.groups.models import (
- Group, user_group, add_user_to_group)
+ Group, user_group, group_by_id, add_user_to_group)
from gn3.auth.authorisation.resources.checks import authorised_for
from gn3.auth.authorisation.resources.models import (
@@ -40,7 +40,8 @@ from gn3.auth.authorisation.errors import ForbiddenAccess
from gn3.auth.authentication.oauth2.resource_server import require_oauth
from gn3.auth.authentication.users import User, user_by_email, set_user_password
-from gn3.auth.authorisation.data.genotypes import ungrouped_genotype_data
+from gn3.auth.authorisation.data.genotypes import (
+ link_genotype_data, ungrouped_genotype_data)
data = Blueprint("data", __name__)
@@ -336,3 +337,28 @@ def search_unlinked_data():
"phenotype": __search_phenotypes__
}
return search_fns[dataset_type]()
+
+@data.route("/link/genotype", methods=["POST"])
+def link_genotypes() -> Response:
+ """Link genotype data to group."""
+ def __values__(form) -> dict[str, Any]:
+ if not bool(form.get("species_name", "").strip()):
+ raise InvalidData("Expected 'species_name' not provided.")
+ if not bool(form.get("group_id")):
+ raise InvalidData("Expected 'group_id' not provided.",)
+ try:
+ _group_id = uuid.UUID(form.get("group_id"))
+ except TypeError as terr:
+ raise InvalidData("Expected a UUID for 'group_id' value.") from terr
+ if not bool(form.get("selected_datasets")):
+ raise InvalidData("Expected at least one dataset to be provided.")
+ return {
+ "group_id": uuid.UUID(form.get("group_id")),
+ "datasets": form.get("selected_datasets")
+ }
+
+ def __link__(conn: db.DbConnection, group_id: uuid.UUID, datasets: dict):
+ return link_genotype_data(conn, group_by_id(conn, group_id), datasets)
+
+ return jsonify(with_db_connection(
+ partial(__link__, **__values__(request.json))))