about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFrederick Muriuki Muriithi2024-07-29 14:38:32 -0500
committerFrederick Muriuki Muriithi2024-08-05 09:52:18 -0500
commitd3fd64fb5237febb9628c4ccbd259969327ab2ec (patch)
tree81ef0ec177188ca80b6f95c277bf9684cfaddccd
parent09642e11e318d149cf628d6b536e04443845665d (diff)
downloadgn-uploader-d3fd64fb5237febb9628c4ccbd259969327ab2ec.tar.gz
Put endpoints behind an authorisation check
Put all endpoints that cause data changes behind authorisation.
-rw-r--r--uploader/dbinsert.py8
-rw-r--r--uploader/entry.py3
-rw-r--r--uploader/parse.py3
-rw-r--r--uploader/samples.py5
-rw-r--r--uploader/upload/rqtl2.py19
5 files changed, 38 insertions, 0 deletions
diff --git a/uploader/dbinsert.py b/uploader/dbinsert.py
index 88d16ef..66b0c41 100644
--- a/uploader/dbinsert.py
+++ b/uploader/dbinsert.py
@@ -11,6 +11,7 @@ from flask import (
     flash, request, url_for, Blueprint, redirect, render_template,
     current_app as app)
 
+from uploader.authorisation import require_login
 from uploader.db_utils import with_db_connection, database_connection
 from uploader.db import species, species_by_id, populations_by_species
 
@@ -90,6 +91,7 @@ def tissues() -> tuple:
     return tuple()
 
 @dbinsertbp.route("/platform", methods=["POST"])
+@require_login
 def select_platform():
     "Select the platform (GeneChipId) used for the data."
     job_id = request.form["job_id"]
@@ -113,6 +115,7 @@ def select_platform():
     return render_error("Unknown error")
 
 @dbinsertbp.route("/study", methods=["POST"])
+@require_login
 def select_study():
     "View to select/create the study (ProbeFreeze) associated with the data."
     form = request.form
@@ -142,6 +145,7 @@ def select_study():
         return render_error(f"Missing data: {aserr.args[0]}")
 
 @dbinsertbp.route("/create-study", methods=["POST"])
+@require_login
 def create_study():
     "Create a new study (ProbeFreeze)."
     form = request.form
@@ -218,6 +222,7 @@ def dataset_datascales() -> tuple:
     return tuple()
 
 @dbinsertbp.route("/dataset", methods=["POST"])
+@require_login
 def select_dataset():
     "Select the dataset to add the file contents against"
     form = request.form
@@ -238,6 +243,7 @@ def select_dataset():
         return render_error(f"Missing data: {aserr.args[0]}")
 
 @dbinsertbp.route("/create-dataset", methods=["POST"])
+@require_login
 def create_dataset():
     "Select the dataset to add the file contents against"
     form = request.form
@@ -317,6 +323,7 @@ def selected_keys(original: dict, keys: tuple) -> dict:
     return {key: value for key,value in original.items() if key in keys}
 
 @dbinsertbp.route("/final-confirmation", methods=["POST"])
+@require_login
 def final_confirmation():
     "Preview the data before triggering entry into the database"
     form = request.form
@@ -352,6 +359,7 @@ def final_confirmation():
         return render_error(f"Missing data: {aserr.args[0]}")
 
 @dbinsertbp.route("/insert-data", methods=["POST"])
+@require_login
 def insert_data():
     "Trigger data insertion"
     form = request.form
diff --git a/uploader/entry.py b/uploader/entry.py
index 941200a..82034ed 100644
--- a/uploader/entry.py
+++ b/uploader/entry.py
@@ -16,6 +16,7 @@ from flask import (
     send_from_directory)
 
 from uploader.db import species
+from uploader.authorisation import require_login
 from uploader.db_utils import with_db_connection
 from uploader.oauth2.client import user_logged_in
 
@@ -91,6 +92,7 @@ def index():
     return render_template("index.html" if user_logged_in() else "login.html")
 
 @entrybp.route("/upload", methods=["GET", "POST"])
+@require_login
 def upload_file():
     """Enables uploading the files"""
     if request.method == "GET":
@@ -123,6 +125,7 @@ def upload_file():
                             filetype=request.form["filetype"]))
 
 @entrybp.route("/data-review", methods=["GET"])
+@require_login
 def data_review():
     """Provide some help on data expectations to the user."""
     return render_template("data_review.html")
diff --git a/uploader/parse.py b/uploader/parse.py
index 865dae2..dea4f95 100644
--- a/uploader/parse.py
+++ b/uploader/parse.py
@@ -11,6 +11,7 @@ from quality_control.errors import InvalidValue, DuplicateHeading
 from uploader import jobs
 from uploader.dbinsert import species_by_id
 from uploader.db_utils import with_db_connection
+from uploader.authorisation import require_login
 
 parsebp = Blueprint("parse", __name__)
 
@@ -23,6 +24,7 @@ def isduplicateheading(item):
     return isinstance(item, DuplicateHeading)
 
 @parsebp.route("/parse", methods=["GET"])
+@require_login
 def parse():
     """Trigger file parsing"""
     errors = False
@@ -160,6 +162,7 @@ def fail(job_id: str):
     return render_template("no_such_job.html", job_id=job_id)
 
 @parsebp.route("/abort", methods=["POST"])
+@require_login
 def abort():
     """Handle user request to abort file processing"""
     job_id = request.form["job_id"]
diff --git a/uploader/samples.py b/uploader/samples.py
index 9c95770..7a80336 100644
--- a/uploader/samples.py
+++ b/uploader/samples.py
@@ -22,6 +22,7 @@ from functional_tools import take
 
 from uploader import jobs
 from uploader.files import save_file
+from uploader.authorisation import require_login
 from uploader.input_validation import is_integer_input
 from uploader.db_utils import (
     with_db_connection,
@@ -37,6 +38,7 @@ from uploader.db import (
 samples = Blueprint("samples", __name__)
 
 @samples.route("/upload/species", methods=["GET", "POST"])
+@require_login
 def select_species():
     """Select the species."""
     if request.method == "GET":
@@ -58,6 +60,7 @@ def select_species():
 
 @samples.route("/upload/species/<int:species_id>/create-population",
                methods=["POST"])
+@require_login
 def create_population(species_id: int):
     """Create new grouping/population."""
     if not is_integer_input(species_id):
@@ -100,6 +103,7 @@ def create_population(species_id: int):
 
 @samples.route("/upload/species/<int:species_id>/population",
                methods=["GET", "POST"])
+@require_login
 def select_population(species_id: int):
     """Select from existing groupings/populations."""
     if not is_integer_input(species_id):
@@ -233,6 +237,7 @@ def build_sample_upload_job(# pylint: disable=[too-many-arguments]
 
 @samples.route("/upload/species/<int:species_id>/populations/<int:population_id>/samples",
                methods=["GET", "POST"])
+@require_login
 def upload_samples(species_id: int, population_id: int):#pylint: disable=[too-many-return-statements]
     """Upload the samples."""
     samples_uploads_page = redirect(url_for("samples.upload_samples",
diff --git a/uploader/upload/rqtl2.py b/uploader/upload/rqtl2.py
index 6aed1f7..ff7556d 100644
--- a/uploader/upload/rqtl2.py
+++ b/uploader/upload/rqtl2.py
@@ -32,6 +32,7 @@ from uploader.files import save_file, fullpath
 from uploader.dbinsert import species as all_species
 from uploader.db_utils import with_db_connection, database_connection
 
+from uploader.authorisation import require_login
 from uploader.db.platforms import platform_by_id, platforms_by_species
 from uploader.db.averaging import averaging_methods, averaging_method_by_id
 from uploader.db.tissues import all_tissues, tissue_by_id, create_new_tissue
@@ -53,8 +54,10 @@ from uploader.db.datasets import (
 
 rqtl2 = Blueprint("rqtl2", __name__)
 
+
 @rqtl2.route("/", methods=["GET", "POST"])
 @rqtl2.route("/select-species", methods=["GET", "POST"])
+@require_login
 def select_species():
     """Select the species."""
     if request.method == "GET":
@@ -72,6 +75,7 @@ def select_species():
 
 @rqtl2.route("/upload/species/<int:species_id>/select-population",
              methods=["GET", "POST"])
+@require_login
 def select_population(species_id: int):
     """Select/Create the population to organise data under."""
     with database_connection(app.config["SQL_URI"]) as conn:
@@ -101,6 +105,7 @@ def select_population(species_id: int):
 
 @rqtl2.route("/upload/species/<int:species_id>/create-population",
              methods=["POST"])
+@require_login
 def create_population(species_id: int):
     """Create a new population for the given species."""
     population_page = redirect(url_for("upload.rqtl2.select_population",
@@ -143,6 +148,7 @@ class __RequestError__(Exception): #pylint: disable=[invalid-name]
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle"),
     methods=["GET", "POST"])
+@require_login
 def upload_rqtl2_bundle(species_id: int, population_id: int):
     """Allow upload of R/qtl2 bundle."""
     with database_connection(app.config["SQL_URI"]) as conn:
@@ -241,6 +247,7 @@ def chunks_directory(uniqueidentifier: str) -> Path:
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle-chunked"),
              methods=["GET"])
+@require_login
 def upload_rqtl2_bundle_chunked_get(# pylint: disable=["unused-argument"]
         species_id: int,
         population_id: int
@@ -285,6 +292,7 @@ def __merge_chunks__(targetfile: Path, chunkpaths: tuple[Path, ...]) -> Path:
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle-chunked"),
              methods=["POST"])
+@require_login
 def upload_rqtl2_bundle_chunked_post(species_id: int, population_id: int):
     """
     Extension to the `upload_rqtl2_bundle` endpoint above that allows large
@@ -343,6 +351,7 @@ def upload_rqtl2_bundle_chunked_post(species_id: int, population_id: int):
 
 @rqtl2.route("/upload/species/rqtl2-bundle/qc-status/<uuid:jobid>",
              methods=["GET", "POST"])
+@require_login
 def rqtl2_bundle_qc_status(jobid: UUID):
     """Check the status of the QC jobs."""
     with (Redis.from_url(app.config["REDIS_URL"], decode_responses=True) as rconn,
@@ -564,6 +573,7 @@ def with_errors(endpointthunk: Callable, *checkfns):
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/select-geno-dataset"),
              methods=["POST"])
+@require_login
 def select_geno_dataset(species_id: int, population_id: int):
     """Select from existing geno datasets."""
     with database_connection(app.config["SQL_URI"]) as conn:
@@ -602,6 +612,7 @@ def select_geno_dataset(species_id: int, population_id: int):
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/create-geno-dataset"),
              methods=["POST"])
+@require_login
 def create_geno_dataset(species_id: int, population_id: int):
     """Create a new geno dataset."""
     with database_connection(app.config["SQL_URI"]) as conn:
@@ -671,6 +682,7 @@ def create_geno_dataset(species_id: int, population_id: int):
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/select-tissue"),
              methods=["POST"])
+@require_login
 def select_tissue(species_id: int, population_id: int):
     """Select from existing tissues."""
     with database_connection(app.config["SQL_URI"]) as conn:
@@ -701,6 +713,7 @@ def select_tissue(species_id: int, population_id: int):
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/create-tissue"),
              methods=["POST"])
+@require_login
 def create_tissue(species_id: int, population_id: int):
     """Add new tissue, organ or biological material to the system."""
     form = request.form
@@ -745,6 +758,7 @@ def create_tissue(species_id: int, population_id: int):
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/select-probeset-study"),
              methods=["POST"])
+@require_login
 def select_probeset_study(species_id: int, population_id: int):
     """Select or create a probeset study."""
     with database_connection(app.config["SQL_URI"]) as conn:
@@ -780,6 +794,7 @@ def select_probeset_study(species_id: int, population_id: int):
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/select-probeset-dataset"),
              methods=["POST"])
+@require_login
 def select_probeset_dataset(species_id: int, population_id: int):
     """Select or create a probeset dataset."""
     with database_connection(app.config["SQL_URI"]) as conn:
@@ -820,6 +835,7 @@ def select_probeset_dataset(species_id: int, population_id: int):
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/create-probeset-study"),
              methods=["POST"])
+@require_login
 def create_probeset_study(species_id: int, population_id: int):
     """Create a new probeset study."""
     errorclasses = "alert-error error-rqtl2 error-rqtl2-create-probeset-study"
@@ -882,6 +898,7 @@ def create_probeset_study(species_id: int, population_id: int):
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/create-probeset-dataset"),
              methods=["POST"])
+@require_login
 def create_probeset_dataset(species_id: int, population_id: int):#pylint: disable=[too-many-return-statements]
     """Create a new probeset dataset."""
     errorclasses = "alert-error error-rqtl2 error-rqtl2-create-probeset-dataset"
@@ -973,6 +990,7 @@ def create_probeset_dataset(species_id: int, population_id: int):#pylint: disabl
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/dataset-info"),
              methods=["POST"])
+@require_login
 def select_dataset_info(species_id: int, population_id: int):
     """
     If `geno` files exist in the R/qtl2 bundle, prompt user to provide the
@@ -1065,6 +1083,7 @@ def select_dataset_info(species_id: int, population_id: int):
 @rqtl2.route(("/upload/species/<int:species_id>/population/<int:population_id>"
               "/rqtl2-bundle/confirm-bundle-details"),
              methods=["POST"])
+@require_login
 def confirm_bundle_details(species_id: int, population_id: int):
     """Confirm the details and trigger R/qtl2 bundle processing..."""
     redisuri = app.config["REDIS_URL"]