Skip to content

Commit e45a88a

Browse files
committed
BUG allow user to download a submission (#397)
1 parent 9c0f6ca commit e45a88a

File tree

3 files changed

+71
-1
lines changed

3 files changed

+71
-1
lines changed

doc/whats_new/v0.5.rst

+5-1
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,13 @@ Changelog
1515
`ramp-frontend`
1616
...............
1717

18+
- Bug: fix a bug for which it was impossible to download a submission
19+
via the frontend.
20+
:pr:`397` by :user:`Guillaume Lemaitre <glemaitre>`.
21+
1822
`ramp-utils`
1923
............
2024

2125
- Enhancement: add :func:`ramp_utils.datasets.fetch_from_osf` allowing to fetch
2226
a file from OSF.
23-
By :pr:`396` by :user:`Guillaume Lemaitre <glemaitre>`.
27+
:pr:`396` by :user:`Guillaume Lemaitre <glemaitre>`.

ramp-frontend/ramp_frontend/tests/test_ramp.py

+23
Original file line numberDiff line numberDiff line change
@@ -803,3 +803,26 @@ def test_toggle_competition(client_session):
803803
assert b"Pull out this submission from the competition" in rv.data
804804
session.commit()
805805
assert submission.is_in_competition
806+
807+
808+
def test_download_submission(client_session):
809+
client, session = client_session
810+
811+
# unknown submission
812+
with login_scope(client, 'test_user', 'test') as client:
813+
rv = client.get("download/xxxxx")
814+
assert rv.status_code == 302
815+
assert rv.location == 'http://localhost/problems'
816+
with client.session_transaction() as cs:
817+
flash_message = dict(cs['_flashes'])
818+
assert "Missing submission" in flash_message['message']
819+
820+
submission = (session.query(Submission)
821+
.filter_by(name="starting_kit_test",
822+
event_team_id=1)
823+
.first())
824+
825+
with login_scope(client, 'test_user', 'test') as client:
826+
rv = client.get(f"download/{submission.hash_}")
827+
assert rv.status_code == 200
828+
assert rv.data

ramp-frontend/ramp_frontend/views/ramp.py

+43
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import datetime
22
import difflib
33
import logging
4+
import io
45
import os
56
import shutil
67
import tempfile
8+
import time
9+
import zipfile
710

811
from bokeh.embed import components
912

@@ -15,6 +18,7 @@
1518
from flask import render_template
1619
from flask import request
1720
from flask import send_from_directory
21+
from flask import send_file
1822

1923
from wtforms import StringField
2024
from wtforms.widgets import TextArea
@@ -992,3 +996,42 @@ def toggle_competition(submission_hash):
992996
return redirect(
993997
'/{}/{}'.format(submission_hash, submission.files[0].f_name)
994998
)
999+
1000+
1001+
@mod.route("/download/<submission_hash>")
1002+
@flask_login.login_required
1003+
def download_submission(submission_hash):
1004+
"""Download a submission from the server.
1005+
1006+
Parameters
1007+
----------
1008+
submission_hash : str
1009+
The submission hash of the current submission.
1010+
"""
1011+
submission = (Submission.query.filter_by(hash_=submission_hash)
1012+
.one_or_none())
1013+
if submission is None:
1014+
error_str = 'Missing submission: {}'.format(submission_hash)
1015+
return redirect_to_user(error_str)
1016+
1017+
access_code = is_accessible_code(
1018+
db.session, submission.event_team.event.name,
1019+
flask_login.current_user.name, submission.id
1020+
)
1021+
if not access_code:
1022+
error_str = 'Unauthorized access: {}'.format(submission_hash)
1023+
return redirect_to_user(error_str)
1024+
1025+
file_in_memory = io.BytesIO()
1026+
with zipfile.ZipFile(file_in_memory, 'w') as zf:
1027+
for ff in submission.files:
1028+
data = zipfile.ZipInfo(ff.f_name)
1029+
data.date_time = time.localtime(time.time())[:6]
1030+
data.compress_type = zipfile.ZIP_DEFLATED
1031+
zf.writestr(data, ff.get_code())
1032+
file_in_memory.seek(0)
1033+
return send_file(
1034+
file_in_memory,
1035+
attachment_filename=f"submission_{submission.id}.zip",
1036+
as_attachment=True,
1037+
)

0 commit comments

Comments
 (0)