From f4c7938cb61d22914edaab60d598769f29df0dfe Mon Sep 17 00:00:00 2001 From: burnout87 Date: Thu, 29 Aug 2024 14:26:09 +0200 Subject: [PATCH 1/8] load-frontend-fits-file-uri --- cdci_data_analysis/flask_app/app.py | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/cdci_data_analysis/flask_app/app.py b/cdci_data_analysis/flask_app/app.py index 41136b1d..ce4bc585 100644 --- a/cdci_data_analysis/flask_app/app.py +++ b/cdci_data_analysis/flask_app/app.py @@ -14,6 +14,8 @@ import string import random import hashlib + +import requests import validators import re import logging @@ -535,6 +537,33 @@ def resolve_job_url(): return redirect(location, 302) +@app.route('/load-frontend-fits-file-uri') +def load_frontend_file_uri(): + par_dic = request.values.to_dict() + sanitized_request_values = sanitize_dict_before_log(par_dic) + logger.info('\033[32m===========================> load_frontend_file_uri\033[0m') + + logger.info('\033[33m raw request values: %s \033[0m', dict(sanitized_request_values)) + + token = par_dic.pop('token', None) + app_config = app.config.get('conf') + secret_key = app_config.secret_key + output, output_code = tokenHelper.validate_token_from_request(token=token, secret_key=secret_key, + required_roles=['gallery contributor'], + action="post on the product gallery") + + if output_code is not None: + return make_response(output, output_code) + + url_to_request = request.values.get('url_request', None) + + if url_to_request is not None: + response = requests.get(url_to_request) + return Response(response.content, status=response.status_code, mimetype='application/octet-stream') + else: + raise MissingRequestParameter("url_request not provided") + + @app.route('/call_back', methods=['POST', 'GET']) def dataserver_call_back(): sanitized_request_values = sanitize_dict_before_log(request.values) From 9b26e9dd2ba0d3752161f7b60791e2a0916fb934 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Thu, 29 Aug 2024 14:29:34 +0200 Subject: [PATCH 2/8] no required role --- cdci_data_analysis/flask_app/app.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cdci_data_analysis/flask_app/app.py b/cdci_data_analysis/flask_app/app.py index ce4bc585..bebf5221 100644 --- a/cdci_data_analysis/flask_app/app.py +++ b/cdci_data_analysis/flask_app/app.py @@ -549,7 +549,8 @@ def load_frontend_file_uri(): app_config = app.config.get('conf') secret_key = app_config.secret_key output, output_code = tokenHelper.validate_token_from_request(token=token, secret_key=secret_key, - required_roles=['gallery contributor'], + # TODO do we actually need a special role for this? + required_roles=[''], action="post on the product gallery") if output_code is not None: From cad45b7495db5ada3ac77bfe48159dbacfba7685 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Thu, 29 Aug 2024 15:55:30 +0200 Subject: [PATCH 3/8] token check --- cdci_data_analysis/flask_app/app.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cdci_data_analysis/flask_app/app.py b/cdci_data_analysis/flask_app/app.py index bebf5221..1d085c78 100644 --- a/cdci_data_analysis/flask_app/app.py +++ b/cdci_data_analysis/flask_app/app.py @@ -537,8 +537,8 @@ def resolve_job_url(): return redirect(location, 302) -@app.route('/load-frontend-fits-file-uri') -def load_frontend_file_uri(): +@app.route('/load-frontend-fits-file-url') +def load_frontend_fits_file_url(): par_dic = request.values.to_dict() sanitized_request_values = sanitize_dict_before_log(par_dic) logger.info('\033[32m===========================> load_frontend_file_uri\033[0m') @@ -550,16 +550,16 @@ def load_frontend_file_uri(): secret_key = app_config.secret_key output, output_code = tokenHelper.validate_token_from_request(token=token, secret_key=secret_key, # TODO do we actually need a special role for this? - required_roles=[''], + required_roles=None, action="post on the product gallery") if output_code is not None: return make_response(output, output_code) - url_to_request = request.values.get('url_request', None) + fits_file_url = request.values.get('fits_file_url', None) - if url_to_request is not None: - response = requests.get(url_to_request) + if fits_file_url is not None: + response = requests.get(fits_file_url) return Response(response.content, status=response.status_code, mimetype='application/octet-stream') else: raise MissingRequestParameter("url_request not provided") From 1c1f308bd72cf4c061e92f6a4006ec209d588c32 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Thu, 29 Aug 2024 17:31:14 +0200 Subject: [PATCH 4/8] logging --- cdci_data_analysis/flask_app/app.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cdci_data_analysis/flask_app/app.py b/cdci_data_analysis/flask_app/app.py index 1d085c78..4970b2c5 100644 --- a/cdci_data_analysis/flask_app/app.py +++ b/cdci_data_analysis/flask_app/app.py @@ -541,7 +541,7 @@ def resolve_job_url(): def load_frontend_fits_file_url(): par_dic = request.values.to_dict() sanitized_request_values = sanitize_dict_before_log(par_dic) - logger.info('\033[32m===========================> load_frontend_file_uri\033[0m') + logger.info('\033[32m===========================> load_frontend_fits_file_url\033[0m') logger.info('\033[33m raw request values: %s \033[0m', dict(sanitized_request_values)) @@ -562,7 +562,7 @@ def load_frontend_fits_file_url(): response = requests.get(fits_file_url) return Response(response.content, status=response.status_code, mimetype='application/octet-stream') else: - raise MissingRequestParameter("url_request not provided") + raise MissingRequestParameter("fits_file_url arg not provided") @app.route('/call_back', methods=['POST', 'GET']) From 1fefd319941dbbb50f6ea20a4555ab3751de9263 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Fri, 30 Aug 2024 08:48:55 +0200 Subject: [PATCH 5/8] endpoint renaming --- cdci_data_analysis/flask_app/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cdci_data_analysis/flask_app/app.py b/cdci_data_analysis/flask_app/app.py index 4970b2c5..ef0e5492 100644 --- a/cdci_data_analysis/flask_app/app.py +++ b/cdci_data_analysis/flask_app/app.py @@ -537,7 +537,7 @@ def resolve_job_url(): return redirect(location, 302) -@app.route('/load-frontend-fits-file-url') +@app.route('/load_frontend_fits_file_url') def load_frontend_fits_file_url(): par_dic = request.values.to_dict() sanitized_request_values = sanitize_dict_before_log(par_dic) From 2fe0c64319b4bd066836798eb6dbcc56dfc45a71 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Fri, 30 Aug 2024 08:51:11 +0200 Subject: [PATCH 6/8] action token check --- cdci_data_analysis/flask_app/app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cdci_data_analysis/flask_app/app.py b/cdci_data_analysis/flask_app/app.py index ef0e5492..2e6bd497 100644 --- a/cdci_data_analysis/flask_app/app.py +++ b/cdci_data_analysis/flask_app/app.py @@ -551,7 +551,7 @@ def load_frontend_fits_file_url(): output, output_code = tokenHelper.validate_token_from_request(token=token, secret_key=secret_key, # TODO do we actually need a special role for this? required_roles=None, - action="post on the product gallery") + action="loading a fits file from the frontend via a URL") if output_code is not None: return make_response(output, output_code) From 9ef5aed9b8658f8039e6fe06d25c98b3b582360e Mon Sep 17 00:00:00 2001 From: burnout87 Date: Fri, 30 Aug 2024 09:44:48 +0200 Subject: [PATCH 7/8] logging --- cdci_data_analysis/flask_app/app.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/cdci_data_analysis/flask_app/app.py b/cdci_data_analysis/flask_app/app.py index 2e6bd497..8627ac8b 100644 --- a/cdci_data_analysis/flask_app/app.py +++ b/cdci_data_analysis/flask_app/app.py @@ -556,13 +556,15 @@ def load_frontend_fits_file_url(): if output_code is not None: return make_response(output, output_code) - fits_file_url = request.values.get('fits_file_url', None) + fits_file_url = par_dic.get('fits_file_url', None) if fits_file_url is not None: + logger.info(f"Loading fits file from URL: {fits_file_url}") response = requests.get(fits_file_url) return Response(response.content, status=response.status_code, mimetype='application/octet-stream') else: - raise MissingRequestParameter("fits_file_url arg not provided") + logging.warning(f'fits_file_url argument missing in request: {par_dic}') + return make_response("fits_file_url arg not provided", 400) @app.route('/call_back', methods=['POST', 'GET']) From 9faf4bd8f35f79d14506248cc178a2f696e1f454 Mon Sep 17 00:00:00 2001 From: burnout87 Date: Fri, 30 Aug 2024 09:44:53 +0200 Subject: [PATCH 8/8] testing --- tests/test_server_basic.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/test_server_basic.py b/tests/test_server_basic.py index 88f13826..25af7d2f 100644 --- a/tests/test_server_basic.py +++ b/tests/test_server_basic.py @@ -179,6 +179,31 @@ def test_empty_request(dispatcher_live_fixture): logger.info(jdata['config']) +@pytest.mark.parametrize('fits_file_url', [ 'valid', 'invalid', 'empty']) +def test_load_frontend_fits_file_url(dispatcher_live_fixture, fits_file_url): + server = dispatcher_live_fixture + print("constructed server:", server) + + # let's generate a valid token + encoded_token = jwt.encode(default_token_payload, secret_key, algorithm='HS256') + + if fits_file_url == 'valid': + fits_file_url = 'https://fits.gsfc.nasa.gov/samples/testkeys.fits' + output_status_code = 200 + elif fits_file_url == 'invalid': + fits_file_url = 'https://fits.gsfc.nasa.gov/samples/aaaaaa.fits' + output_status_code = 404 + else: + fits_file_url = None + output_status_code = 400 + + c=requests.get(os.path.join(server, 'load_frontend_fits_file_url'), + params={'fits_file_url': fits_file_url, + 'token': encoded_token}) + + assert c.status_code == output_status_code + + def test_no_debug_mode_empty_request(dispatcher_live_fixture_no_debug_mode): server = dispatcher_live_fixture_no_debug_mode print("constructed server:", server)