Skip to content

Commit 055335d

Browse files
committed
add: save votr context in flask session
1 parent a0483c6 commit 055335d

File tree

5 files changed

+70
-74
lines changed

5 files changed

+70
-74
lines changed

eprihlaska/ais_utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def save_application_form(ctx,
140140

141141
# If the priezviskoTextField is not empty, it most probably means the
142142
# person is already registered in
143-
if app.d.priezviskoTextField.value != '' and process_type is None:
143+
if app.d.priezviskoTextField.value != '' and process_type == 'none':
144144
notes['person_exists'] = {
145145
'name': app.d.menoTextField.value,
146146
'surname': app.d.priezviskoTextField.value,

eprihlaska/forms.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -345,11 +345,5 @@ class SignupForm(FlaskForm):
345345
submit = SubmitField(label=c.SIGNUP)
346346

347347

348-
class AIS2CookieForm(FlaskForm):
349-
jsessionid = StringField(label='JSESSIONID',
350-
validators=[validators.DataRequired()])
351-
submit = SubmitField(label=c.SUBMIT)
352-
353-
354348
class AIS2SubmitForm(FlaskForm):
355349
submit = SubmitField(label=c.CONTINUE)

eprihlaska/templates/admin_list.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@
4747
{% endif %}
4848

4949
{% if app.state.value == 2 %}
50-
<a class="btn btn-xs btn-default" href="{{ url_for('admin_process', id=app.id) }}">Preklopiť na BETU</a>
51-
<a class="btn btn-xs btn-default" href="{{ url_for('admin_ais2_process', id=app.id) }}">Preklopiť</a>
50+
<a class="btn btn-xs btn-default" href="{{ url_for('admin_ais2_process', ais_instance='beta', process_type='none', id=app.id) }}">Preklopiť na BETU</a>
51+
<a class="btn btn-xs btn-default" href="{{ url_for('admin_ais2_process', ais_instance='prod', process_type='none', id=app.id) }}">Preklopiť</a>
5252
{% endif %}
5353
</div>
5454
<br />

eprihlaska/templates/admin_process.html

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
<div class="container">
99
<h1 class="section-title">
1010
{% block title %}
11-
{% if beta %}
11+
{% if ais_instance == 'beta' %}
1212
Preklopenie prihlášky #{{ id }} do AIS2 (beta)
1313
{% else %}
1414
Preklopenie prihlášky #{{ id }} do AIS2
@@ -128,21 +128,13 @@ <h3>Vyplniť prihlášku bez párovania s osobou</h3>
128128
</a>
129129
</div>
130130
<div class="col-md-4">
131-
{% if beta %}
132-
<a class="btn" href="{{ url_for('admin_process_special', id=id, process_type='no_fill') }}">
133-
{% else %}
134-
<a class="btn" href="{{ url_for('admin_ais2_process_special', id=id, process_type='no_fill') }}">
135-
{% endif %}
131+
<a class="btn" href="{{ url_for('admin_ais2_process', ais_instance=ais_instance, process_type='no_fill', id=id) }}">
136132
Pokračovať s údajmi z AIS2
137133
</a>
138134
</div>
139135

140136
<div class="col-md-4">
141-
{% if beta %}
142-
<a class="btn" href="{{ url_for('admin_process_special', id=id, process_type='fill') }}">
143-
{% else %}
144-
<a class="btn" href="{{ url_for('admin_ais2_process_special', id=id, process_type='fill') }}">
145-
{% endif %}
137+
<a class="btn" href="{{ url_for('admin_ais2_process', ais_instance=ais_instance, process_type='fill', id=id) }}">
146138
Pokračovať s údajmi z prihlášky
147139
</a>
148140
</div>

eprihlaska/views.py

Lines changed: 64 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import pickle
2+
from urllib.parse import quote_plus
13
from flask import (render_template, flash, redirect, session, request, url_for,
24
make_response, send_from_directory)
35
import flask.json
@@ -9,7 +11,7 @@
911
AdmissionWaiversForm, FinalForm,
1012
ReceiptUploadForm, LoginForm, SignupForm,
1113
ForgottenPasswordForm, NewPasswordForm,
12-
AIS2CookieForm, AIS2SubmitForm)
14+
AIS2SubmitForm)
1315
from werkzeug.security import generate_password_hash, check_password_hash
1416
from flask_login import login_user, login_required, logout_user, current_user
1517
import datetime
@@ -98,9 +100,17 @@ def save_form(form):
98100
save_current_session_to_DB()
99101

100102

103+
def current_session_to_json():
104+
# Don't store internal keys used by flask (e.g. "_flashes"), flask-login
105+
# (e.g. "_user_id", "_fresh", "_id") and our admin ("_votr_context_*") in
106+
# the SQL database.
107+
filtered = { k: v for k, v in session.items() if not k.startswith('_') }
108+
return flask.json.dumps(filtered)
109+
110+
101111
def save_current_session_to_DB():
102112
app = ApplicationForm.query.filter_by(user_id=current_user.id).first()
103-
app.application = flask.json.dumps(dict(session))
113+
app.application = current_session_to_json()
104114
db.session.commit()
105115

106116

@@ -126,7 +136,7 @@ def load_session():
126136
if 'application_submitted' in session:
127137
del session['application_submitted']
128138

129-
app.application = flask.json.dumps(dict(session))
139+
app.application = current_session_to_json()
130140
db.session.commit()
131141

132142
session.modified = True
@@ -469,7 +479,7 @@ def final():
469479
save_form(form)
470480

471481
session['application_submitted'] = True
472-
app_form.application = flask.json.dumps(dict(session))
482+
app_form.application = current_session_to_json()
473483
app_form.state = ApplicationStates.submitted
474484
app_form.submitted_at = datetime.datetime.now()
475485
db.session.commit()
@@ -692,7 +702,7 @@ def signup():
692702
new_application_form = ApplicationForm(user_id=new_user.id)
693703
# FIXME: band-aid for last_updated_at
694704
new_application_form.last_updated_at = datetime.datetime.now()
695-
new_application_form.application = flask.json.dumps(dict(session))
705+
new_application_form.application = current_session_to_json()
696706
db.session.add(new_application_form)
697707
db.session.commit()
698708

@@ -794,7 +804,7 @@ def create_or_get_user_and_login(site, token, name, surname, email):
794804
new_application_form = ApplicationForm(user_id=user.id)
795805
# FIXME: band-aid for last_updated_at
796806
new_application_form.last_updated_at = datetime.datetime.now()
797-
new_application_form.application = flask.json.dumps(dict(session))
807+
new_application_form.application = current_session_to_json()
798808
db.session.add(new_application_form)
799809
db.session.commit()
800810

@@ -970,22 +980,53 @@ def admin_file_download(id, uuid):
970980
return send_from_directory(receipt_dir, file, as_attachment=True)
971981

972982

973-
def create_votr_context(*, beta):
983+
@app.route('/admin/init_votr/<any(prod,beta):ais_instance>')
984+
@require_remote_user
985+
def admin_init_votr(ais_instance):
986+
next = request.args['next']
987+
if not next.startswith('/admin/'):
988+
return 'Bad next', 400
989+
974990
from .ais_utils import create_context
975-
return create_context(
991+
votr_context = create_context(
976992
my_entity_id=app.config['MY_ENTITY_ID'],
977993
andrvotr_api_key=app.config['ANDRVOTR_API_KEY'],
978994
andrvotr_authority_token=request.environ['ANDRVOTR_AUTHORITY_TOKEN'],
979-
beta=beta,
995+
beta=(ais_instance == 'beta'),
980996
)
997+
# flask-session docs say it'll stop using pickle in the future.
998+
# Wrap the votr_context in our own pickle.
999+
session[f'_votr_context_{ais_instance}'] = pickle.dumps(votr_context, pickle.HIGHEST_PROTOCOL)
1000+
1001+
return redirect(next)
1002+
1003+
1004+
def require_votr_context(func):
1005+
@wraps(func)
1006+
def wrapper(*args, **kwargs):
1007+
ais_instance = kwargs['ais_instance']
1008+
session_key = f'_votr_context_{ais_instance}'
1009+
if not session.get(session_key):
1010+
# First time we visited an admin page that requires votr_context?
1011+
# 1. Re-login with mod_shib to get a fresh andrvotr authority token.
1012+
# 2. Create a votr_context and store it in the flask session.
1013+
# 3. Redirect back here.
1014+
target = url_for('admin_init_votr', ais_instance=ais_instance, next=request.full_path)
1015+
return redirect(f'/Shibboleth.sso/Login?target={quote_plus(target)}')
1016+
1017+
votr_context = pickle.loads(session[session_key])
1018+
result = func(*args, **kwargs, votr_context=votr_context)
1019+
session[session_key] = pickle.dumps(votr_context, pickle.HIGHEST_PROTOCOL)
1020+
return result
1021+
return wrapper
9811022

9821023

983-
@app.route('/admin/ais_test')
1024+
@app.route('/admin/ais_test/<any(prod,beta):ais_instance>')
9841025
@require_remote_user
985-
def admin_ais_test():
1026+
@require_votr_context
1027+
def admin_ais_test(ais_instance, votr_context):
9861028
from .ais_utils import test_ais
987-
ctx = create_votr_context(beta=False)
988-
test_ais(ctx)
1029+
test_ais(votr_context)
9891030
return redirect(url_for('admin_list'))
9901031

9911032

@@ -1096,61 +1137,29 @@ def generate():
10961137
mimetype='text/tsv', headers=headers)
10971138

10981139

1099-
@app.route('/admin/ais2_process/<id>', methods=['GET', 'POST'])
1140+
@app.route('/admin/ais2_process/<any(prod,beta):ais_instance>/<any(none,fill,no_fill):process_type>/<id>', methods=['GET', 'POST'])
11001141
@require_remote_user
1101-
def admin_ais2_process(id):
1142+
@require_votr_context
1143+
def admin_ais2_process(ais_instance, process_type, id, votr_context):
11021144
application = ApplicationForm.query.get(id)
11031145

11041146
form = AIS2SubmitForm()
1105-
return send_application_to_ais2(id, application, form,
1106-
process_type=None, beta=False)
1107-
11081147

1109-
@app.route('/admin/ais2_process/<id>/<process_type>', methods=['GET', 'POST'])
1110-
def admin_ais2_process_special(id, process_type):
1111-
application = ApplicationForm.query.get(id)
1112-
1113-
form = AIS2SubmitForm()
1114-
return send_application_to_ais2(id, application, form,
1115-
process_type=process_type, beta=False)
1116-
1117-
1118-
@app.route('/admin/process/<id>', methods=['GET', 'POST'])
1119-
@require_remote_user
1120-
def admin_process(id):
1121-
application = ApplicationForm.query.get(id)
1122-
1123-
form = AIS2SubmitForm()
1124-
return send_application_to_ais2(id, application, form, None, beta=True)
1125-
1126-
1127-
@app.route('/admin/process/<id>/<process_type>', methods=['GET', 'POST'])
1128-
def admin_process_special(id, process_type):
1129-
application = ApplicationForm.query.get(id)
1130-
1131-
form = AIS2CookieForm()
1132-
return send_application_to_ais2(id, application, form, process_type,
1133-
beta=True)
1134-
1135-
1136-
def send_application_to_ais2(id, application, form, process_type, beta=False):
11371148
from .ais_utils import save_application_form
11381149
if form.validate_on_submit():
1139-
ctx = create_votr_context(beta=beta)
1140-
11411150
ais2_output = None
11421151
error_output = None
11431152
notes = {}
11441153

11451154
logfile = None
11461155
try:
1147-
if beta:
1156+
if ais_instance == 'beta':
11481157
import gzip
11491158
import random
11501159
logfile = gzip.open('/tmp/log_%s_%s' % (id, random.randrange(10000)), 'wt', encoding='utf8')
1151-
ctx.logger.log_file = logfile
1160+
votr_context.logger.log_file = logfile
11521161

1153-
ais2_output, notes = save_application_form(ctx,
1162+
ais2_output, notes = save_application_form(votr_context,
11541163
application,
11551164
LISTS,
11561165
id,
@@ -1176,7 +1185,7 @@ def send_application_to_ais2(id, application, form, process_type, beta=False):
11761185

11771186
# Only update the application state of it is not sent to beta and the
11781187
# 'person_exists' note is not added
1179-
if not beta and error_output is None and 'person_exists' not in notes:
1188+
if ais_instance != 'beta' and error_output is None and 'person_exists' not in notes:
11801189
application.state = ApplicationStates.processed
11811190
db.session.commit()
11821191

@@ -1185,13 +1194,14 @@ def send_application_to_ais2(id, application, form, process_type, beta=False):
11851194
ais2_output=ais2_output,
11861195
notes=notes, id=id,
11871196
error_output=error_output,
1188-
beta=beta, process_type=process_type,
1197+
ais_instance=ais_instance,
1198+
process_type=process_type,
11891199
session=sess,
11901200
lists=LISTS)
11911201

11921202
return render_template('admin_process.html',
11931203
form=form, id=id,
1194-
beta=beta)
1204+
ais_instance=ais_instance)
11951205

11961206

11971207
@app.route('/admin/impersonate/list')

0 commit comments

Comments
 (0)