Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle auth and data errors #4

Merged
merged 9 commits into from
Nov 21, 2023
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Ignore local data again once API turned on
src/data/group_bold.csv
src/data/archive/

.env

# Byte-compiled / optimized / DLL files
__pycache__/
Expand Down
60 changes: 42 additions & 18 deletions src/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,10 @@
requests_pathname_prefix=REQUESTS_PATHNAME_PREFIX,
suppress_callback_exceptions=True
)
gunicorn_logger = logging.getLogger('gunicorn.error')
app.logger = logging.getLogger("imaging_ui")
app.logger.handlers = gunicorn_logger.handlers
app.logger.setLevel(logging.INFO)

# ----------------------------------------------------------------------------
# DASH HTML COMPONENTS
Expand Down Expand Up @@ -319,7 +323,19 @@ def get_filtered_data_store(raw_data_store, filter_type=None, start_date: dateti

def load_imaging_api(api_url):
api_address = api_url + 'imaging'
app.logger.info('Requesting data from api {0}'.format(api_address))
api_json = get_api_data(api_address)
if 'error' in api_json:
app.logger.info('Error response from datastore: {0}'.format(api_json))
if 'error_code' in api_json:
error_code = api_json['error_code']
if error_code in ('MISSING_SESSION_ID', 'INVALID_TAPIS_TOKEN'):
raise PortalAuthException

if 'date' not in api_json or 'imaging' not in api_json['data'] or 'qc' not in api_json['data']:
app.logger.info('Requesting data from api {0} to ignore cache.'.format(api_address))
api_json = get_api_data(api_address, True)

data_date = api_json['date']
imaging = api_json['data']['imaging']
qc = api_json['data']['qc']
Expand Down Expand Up @@ -484,24 +500,32 @@ def create_content(source, data_date, sites):
return content

def serve_layout():
# raw_data_dictionary = serve_raw_data_store(data_url_root, DATA_PATH, DATA_SOURCE)
# try: #load data from api
raw_data_dictionary = load_imaging_api(DATASTORE_URL)
source ='api'
# except:
# imaging, qc = load_local_data(DATA_PATH)
# raw_data_dictionary = local_data_as_dict(imaging, qc, LOCAL_DATA_DATE)
# source = 'local'
# try:
page_layout = html.Div([
# change to 'url' before deploy
# serve_data_stores('url'),
create_data_stores(source, raw_data_dictionary),
], className='delay')

# except:
# page_layout = html.Div(['There has been a problem accessing the data for this application.'])
return page_layout
try:
# raw_data_dictionary = serve_raw_data_store(data_url_root, DATA_PATH, DATA_SOURCE)
# try: #load data from api
app.logger.info('serving layout using datastore: {0}'.format(DATASTORE_URL))
raw_data_dictionary = load_imaging_api(DATASTORE_URL)
source ='api'
# except:
# imaging, qc = load_local_data(DATA_PATH)
# raw_data_dictionary = local_data_as_dict(imaging, qc, LOCAL_DATA_DATE)
# source = 'local'
# try:
page_layout = html.Div([
# change to 'url' before deploy
# serve_data_stores('url'),
create_data_stores(source, raw_data_dictionary),
], className='delay')

# except:
# page_layout = html.Div(['There has been a problem accessing the data for this application.'])
return page_layout
except PortalAuthException:
app.logger.warn('Auth error from datastore, asking user to authenticate')
return html.Div([html.H4('Please login and authenticate on the portal to access the report.')])
except Exception as ex:
app.logger.warn('Exception serving layout {0}'.format(ex))
return html.Div([html.H4('Error processing report data')])

app.layout = serve_layout

Expand Down
31 changes: 16 additions & 15 deletions src/datastore_loading.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
import os
import json
import flask
import requests
import json
import traceback
import logging

# ---------------------------------
# MOVE THIS TO REFERENCE FROM ENV
# ---------------------------------
DATASTORE_URL = os.getenv('DATASTORE_URL')
DATASTORE_URL = os.environ.get("DATASTORE_URL","url not found")
DATASTORE_URL = os.path.join(DATASTORE_URL, "api/")
logger = logging.getLogger("imaging_app")

# ---------------------------------
# Get Data From datastore
# ---------------------------------

def get_api_data(api_address):
class PortalAuthException(Exception):
'''Custom Exception for issues with Authentication'''

def get_api_data(api_address, ignore_cache=False):
api_json = {}
try:
try:
response = requests.get(api_address, cookies=flask.request.cookies)
except:
return('error: {}'.format(e))
request_status = response.status_code
if request_status == 200:
api_json = response.json()
return api_json
else:
return request_status
params = {}
if ignore_cache:
params = {'ignore_cache':True}
response = requests.get(api_address, params=params, cookies=flask.request.cookies)
response.raise_for_status()
return response.json()
except Exception as e:
traceback.print_exc()
logger.warn(e)
api_json['json'] = 'error: {}'.format(e)
return api_json
Loading