Skip to content

Commit

Permalink
added create variant shortcut and added no_login option
Browse files Browse the repository at this point in the history
  • Loading branch information
MarvinDo committed Nov 3, 2024
1 parent 412f6e2 commit 4d37712
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 34 deletions.
1 change: 1 addition & 0 deletions .env_example
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
HOST=
PORT=
NO_PROXY=localhost
LOGIN_REQUIRED=True

########## DB SETTINGS #########
DB_HOST=
Expand Down
2 changes: 2 additions & 0 deletions src/frontend_celery/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class Config(object):
HOST = os.environ.get('HOST')
PORT = os.environ.get('PORT')

LOGIN_REQUIRED = os.environ.get('LOGIN_REQUIRED', "True").lower() in ["true"]

##### production config ####
TESTING = False
DEBUG = False
Expand Down
29 changes: 27 additions & 2 deletions src/frontend_celery/webapp/auth/auth_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,42 @@

@auth_blueprint.route('/login')
def login():

next_url = request.args.get('next_login', url_for('main.index'))

if not current_app.config["LOGIN_REQUIRED"]:
return redirect(url_for("auth.auth", next_login=next_url))

# construct redirect uri: first redirect to keycloak login page
# then redirect to auth with the next param which defaults to the '/' route
# auth itself redirects to next ie. the page which required a login
redirect_uri = url_for('auth.auth', _external=True, next_login=request.args.get('next_login', url_for('main.index')))
redirect_uri = url_for('auth.auth', _external=True, next_login=next_url)

return oauth.keycloak.authorize_redirect(redirect_uri)


@auth_blueprint.route('/auth')
def auth():
token_response = oauth.keycloak.authorize_access_token()

if not current_app.config["LOGIN_REQUIRED"]:
token_response = {
"access_token": "xxx",
"expires_in": 300,
"refresh_expires_in": 1800,
"refresh_token": "xxx",
"token_type": "bearer",
"not-before-policy": 0,
"session_state": "xxx",
"userinfo": {
"preferred_username": "anonymous",
"given_name": "Arno",
"family_name": "Nym",
"affiliation": "Anonymous",
"roles": ["super_user", "user", "read_only"]
}
}
else:
token_response = oauth.keycloak.authorize_access_token()

#userinfo = oauth.keycloak.userinfo(request)
#idToken = oauth.keycloak.parse_id_token(tokenResponse)
Expand Down
8 changes: 8 additions & 0 deletions src/frontend_celery/webapp/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ <h4>Overview</h4>
<div class="bst bsb">
<h4>Changelog</h4>

<div class="underline">v 1.14.4 (03.11.2024)</div>
<div>
General changes:
<ul>
<li>Added shortcut to insert unknown variants from variant display page</li>
</ul>
</div>

<div class="underline">v 1.14.3 (15.10.2024)</div>
<div>
General changes:
Expand Down
11 changes: 7 additions & 4 deletions src/frontend_celery/webapp/templates/variant/create.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ <h1 class="bst">{% block title %} Create a new variant {% endblock %}</h1>
<label for="Chromosome" class="form-label">Chromosome</label>
<select class="form-select" name="chr" id="Chromosome" required>
{% for chr in chrs %}
<option value="{{chr}}" {% if (chr == request.form['chr']) %} selected="selected" {% endif %}> {{chr}} </option>
<option value="{{chr}}" {% if chr == request.form['chr'] or chr == request.args.get('chrom') %} selected="selected" {% endif %}> {{chr}} </option>
{% endfor %}
</select>
<div class="invalid-feedback">
Expand All @@ -43,7 +43,8 @@ <h1 class="bst">{% block title %} Create a new variant {% endblock %}</h1>
<label for="Position" class="form-label">Chromosomal position</label>
<input type="text" name="pos" pattern="[0-9 ]+" id="Position"
placeholder="pos" class="form-control validationreq"
value="{{ request.form['pos'] }}" required>
value={% if request.form.get('pos') is not none %}"{{ request.form.get('pos', '') }}"{% else %}"{{ request.args.get('pos', '') }}"{% endif %}
required>
<div class="invalid-feedback">
Please provide a chromosomal position!
</div>
Expand All @@ -53,7 +54,8 @@ <h1 class="bst">{% block title %} Create a new variant {% endblock %}</h1>
<label for="Reference" class="form-label">Reference sequence</label>
<input type="text" name="ref"
placeholder="ref" class="form-control validationreq"
value="{{ request.form['ref'] }}" id="Reference" required>
value={% if request.form.get('ref') is not none %}"{{ request.form.get('ref', '') }}"{% else %}"{{ request.args.get('ref', '') }}"{% endif %}
id="Reference" required>
<div class="invalid-feedback">
Please provide a reference sequence!
</div>
Expand All @@ -63,7 +65,8 @@ <h1 class="bst">{% block title %} Create a new variant {% endblock %}</h1>
<label for="Alternative" class="form-label">Alternative sequence</label>
<input type="text" name="alt"
placeholder="alt" class="form-control validationreq"
value="{{ request.form['alt'] }}" id="Alternative" required>
value={% if request.form.get('alt') is not none %}"{{ request.form.get('alt', '') }}"{% else %}"{{ request.args.get('alt', '') }}"{% endif %}
id="Alternative" required>
<div class="invalid-feedback">
Please provide an alternative sequence!
</div>
Expand Down
25 changes: 25 additions & 0 deletions src/frontend_celery/webapp/templates/variant/unknown_variant.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{% extends 'base.html' %}

{% block content %}
<div class="container">



<h1 class="bst">{% block title %} Unknown variant {% endblock %}</h1>


<div class="bst">
<div>The variant you are trying to access is unknown by HerediVar. Please click to following button to request a new variant:</div>
<div>
<a class="btn btn-primary" href="{{url_for('variant.create', **request.args)}}">create new variant</a>
</div>
</div>


</div>

{% endblock %}

{% block special_scripts %}
<script src="/static/js/create.js"></script>
{% endblock%}
56 changes: 29 additions & 27 deletions src/frontend_celery/webapp/utils/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,34 +74,35 @@ def decorated_function(*args, **kwargs):
if session.get('user') is None:
return redirect(url_for('auth.login', next_login=request.url))

# user is logged in -> check if access token is still valid using introspect endpoint --> introspect endpoint can be omitted if token is validated locally using some jwt lib
if current_app.config["LOGIN_REQUIRED"]:
# user is logged in -> check if access token is still valid using introspect endpoint --> introspect endpoint can be omitted if token is validated locally using some jwt lib

token = session['tokenResponse']
token = session['tokenResponse']

#print(session['user'])
#print(token)
#print(session['user'])
#print(token)

# maybe also add:
# state=5AzjFWCkQzjmh4YozUfuE8pHytJj3i
# nonce=fvdZHHR1mmAHBIbCQtgZ
# code_challenge=hoiDWU7Vf4tOreIeYyIi7IKcw2BseRW7j5wwXROJtPA
# code_challenge_method=S256
# maybe also add:
# state=5AzjFWCkQzjmh4YozUfuE8pHytJj3i
# nonce=fvdZHHR1mmAHBIbCQtgZ
# code_challenge=hoiDWU7Vf4tOreIeYyIi7IKcw2BseRW7j5wwXROJtPA
# code_challenge_method=S256

issuer = current_app.config['ISSUER']
url = f'{issuer}/protocol/openid-connect/token/introspect'
data = {'token': token.get("access_token"), 'token_type_hint': 'access_token', 'username': session['user']['preferred_username'], 'client_secret': current_app.config['CLIENTSECRET'], 'client_id': current_app.config['CLIENTID']}
header = {'Authorization': f'Bearer {token.get("access_token")}'}
resp = requests.post(url, data=data, headers=header)
resp.raise_for_status()
resp = resp.json()

# if access token is not valid request a new one using the refresh token
if not resp['active']:
print('access token invalid refreshing token')
refresh_status_code = refresh_token()
# if the refresh token is expired as well promt a new login by invalidating the client session
if refresh_status_code != 200:
return redirect(url_for('auth.logout', auto_logout='True', next_logout=url_for('auth.login', next_login=request.url))) # logout and return to login page! with next= page which you wanted to access in the first place
issuer = current_app.config['ISSUER']
url = f'{issuer}/protocol/openid-connect/token/introspect'
data = {'token': token.get("access_token"), 'token_type_hint': 'access_token', 'username': session['user']['preferred_username'], 'client_secret': current_app.config['CLIENTSECRET'], 'client_id': current_app.config['CLIENTID']}
header = {'Authorization': f'Bearer {token.get("access_token")}'}
resp = requests.post(url, data=data, headers=header)
resp.raise_for_status()
resp = resp.json()

# if access token is not valid request a new one using the refresh token
if not resp['active']:
print('access token invalid refreshing token')
refresh_status_code = refresh_token()
# if the refresh token is expired as well promt a new login by invalidating the client session
if refresh_status_code != 200:
return redirect(url_for('auth.logout', auto_logout='True', next_logout=url_for('auth.login', next_login=request.url))) # logout and return to login page! with next= page which you wanted to access in the first place

return f(*args, **kwargs)
return decorated_function
Expand All @@ -113,9 +114,10 @@ def decorator(f):
@require_login
@wraps(f)
def wrapper(*args, **kwargs):
grant_access, status_code = request_uma_ticket(resources)
if not grant_access:
abort(status_code)
if current_app.config["LOGIN_REQUIRED"]:
grant_access, status_code = request_uma_ticket(resources)
if not grant_access:
abort(status_code)
return f(*args, **kwargs)
return wrapper
return decorator
Expand Down
11 changes: 10 additions & 1 deletion src/frontend_celery/webapp/variant/variant_routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def create():

if do_redirect:
return redirect(url_for('variant.create'))
return render_template('variant/create.html', chrs=chroms, vcf_file_import_active=current_app.config["VCF_FILE_IMPORT_ACTIVE"])
return render_template('variant/create.html', chrs=chroms, vcf_file_import_active=current_app.config["VCF_FILE_IMPORT_ACTIVE"], **request.args)



Expand Down Expand Up @@ -125,12 +125,15 @@ def create_sv():
@variant_blueprint.route('/display/chr=<string:chr>&pos=<int:pos>&ref=<string:ref>&alt=<string:alt>', methods=['GET']) # alternative url using vcf information
@require_permission(['read_resources'])
def display(variant_id=None, chr=None, pos=None, ref=None, alt=None):

conn = get_connection()

# get variant id from parameters or pull from genomic coordinates
if variant_id is None:
require_set(chr, pos, ref, alt)
variant_id = conn.get_variant_id(chr, pos, ref, alt)
if variant_id is None and any([e is not None for e in [chr, pos, ref, alt]]):
return redirect(url_for('variant.unknown_variant', chrom=chr, pos=pos, ref=ref, alt=alt))
require_valid(variant_id, "variant", conn)

# get available lists for user
Expand All @@ -146,6 +149,12 @@ def display(variant_id=None, chr=None, pos=None, ref=None, alt=None):
)


@variant_blueprint.route('/unknown_variant', methods=["GET"])
@require_permission(['read_resources'])
def unknown_variant():
return render_template('variant/unknown_variant.html', **request.args)


@variant_blueprint.route('/get_clinvar_upload_status', methods=['GET'])
@require_permission(['read_resources'])
def get_clinvar_upload_status():
Expand Down

0 comments on commit 4d37712

Please sign in to comment.