about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2025-06-05 14:51:05 -0500
committerFrederick Muriuki Muriithi2025-06-05 15:09:16 -0500
commitb6c27b907ddb3a1aa7d97632fcc9aa36901df459 (patch)
treeb82455c22ee373af7442fb09259c863ea4b1373b
parent650dbc306101a4c2bd0e910e3a5c744f2f09929c (diff)
downloadgn-uploader-b6c27b907ddb3a1aa7d97632fcc9aa36901df459.tar.gz
Request token for use with script to update authorisations
After the script has completed loading the data into the database, the
user who uploads the data will need to access the data they've
uploaded.

This commit requests a new token to use with the script for updating
the authorisations as appropriate, to grant the user access to their
data.
-rw-r--r--uploader/phenotypes/views.py78
1 files changed, 65 insertions, 13 deletions
diff --git a/uploader/phenotypes/views.py b/uploader/phenotypes/views.py
index c90b072..49c12b5 100644
--- a/uploader/phenotypes/views.py
+++ b/uploader/phenotypes/views.py
@@ -4,14 +4,17 @@ import csv
 import uuid
 import json
 import logging
-import datetime
 import tempfile
 from typing import Any
 from pathlib import Path
 from zipfile import ZipFile
+from urllib.parse import urljoin
 from functools import wraps, reduce
 from logging import INFO, ERROR, DEBUG, FATAL, CRITICAL, WARNING
 
+import datetime
+from datetime import timedelta
+
 from redis import Redis
 from pymonad.either import Left
 from requests.models import Response
@@ -21,7 +24,9 @@ from werkzeug.utils import secure_filename
 from gn_libs import sqlite3
 from gn_libs import jobs as gnlibs_jobs
 from gn_libs.mysqldb import database_connection
+from gn_libs import monadic_requests as mrequests
 
+from authlib.jose import jwt
 from flask import (flash,
                    request,
                    url_for,
@@ -35,11 +40,14 @@ from flask import (flash,
 from r_qtl import r_qtl2_qc as rqc
 from r_qtl import exceptions as rqe
 
+
 from uploader import jobs
+from uploader import session
 from uploader.files import save_file#, fullpath
 from uploader.ui import make_template_renderer
 from uploader.oauth2.client import oauth2_post
 from uploader.authorisation import require_login
+from uploader.oauth2 import jwks, client as oauth2client
 from uploader.route_utils import generic_select_population
 from uploader.datautils import safe_int, enumerate_sequence
 from uploader.species.models import all_species, species_by_id
@@ -640,21 +648,65 @@ def load_data_to_database(
                 app.logger.getEffectiveLevel()
             ).lower()
         ]
-        load_job = gnlibs_jobs.launch_job(
-            gnlibs_jobs.initialise_job(conn,
-                                       load_job_id,
-                                       command,
-                                       "load-new-phenotypes-data",
-                                       extra_meta={
-                                           "species_id": species["SpeciesId"],
-                                           "population_id": population["Id"],
-                                           "dataset_id": dataset["Id"],
-                                           "bundle_file": _meta["bundle"]
-                                       }),
+
+        def __handle_error__(resp):
+            raise Exception(resp)
+
+        def __handle_success__(load_job):
+            app.logger.debug("The phenotypes loading job: %s", load_job)
+            return str(load_job)
+        issued = datetime.datetime.now()
+        jwtkey = jwks.newest_jwk_with_rotation(
+            jwks.jwks_directory(app, "UPLOADER_SECRETS"),
+            int(app.config["JWKS_ROTATION_AGE_DAYS"]))
+
+        return mrequests.post(
+            urljoin(oauth2client.authserver_uri(), "auth/token"),
+            json={
+                "grant_type": "urn:ietf:params:oauth:grant-type:jwt-bearer",
+                "scope": oauth2client.SCOPE,
+                "assertion": jwt.encode(
+                    header={
+                        "alg": "RS256",
+                        "typ": "JWT",
+                        "kid": jwtkey.as_dict()["kid"]
+                    },
+                    payload={
+                        "iss": str(oauth2client.oauth2_clientid()),
+                        "sub": str(session.user_details()["user_id"]),
+                        "aud": urljoin(oauth2client.authserver_uri(),
+                                       "auth/token"),
+                        # TODO: Update expiry time once fix is implemented in
+                        #       auth server.
+                        "exp": (issued + timedelta(minutes=5)).timestamp(),
+                        "nbf": int(issued.timestamp()),
+                        "iat": int(issued.timestamp()),
+                        "jti": str(uuid.uuid4())
+                    },
+                    key=jwtkey).decode("utf8"),
+                "client_id": oauth2client.oauth2_clientid()
+            }
+        ).then(
+            lambda token: gnlibs_jobs.initialise_job(
+                conn,
+                load_job_id,
+                command,
+                "load-new-phenotypes-data",
+                extra_meta={
+                    "species_id": species["SpeciesId"],
+                    "population_id": population["Id"],
+                    "dataset_id": dataset["Id"],
+                    "bundle_file": _meta["bundle"],
+                    "authserver": oauth2client.authserver_uri(),
+                    "token": token["access_token"]
+                })
+        ).then(
+            lambda job: gnlibs_jobs.launch_job(
+            job,
             jobs_db,
             f"{app.config['UPLOAD_FOLDER']}/job_errors",
             worker_manager="gn_libs.jobs.launcher")
-        return str(load_job)
+        ).either(__handle_error__, __handle_success__)
 
 
 def update_phenotype_metadata(conn, metadata: dict):