Skip to content

Commit 8d16996

Browse files
committed
Add view to download the current set of submissions
1 parent 79d5cc7 commit 8d16996

File tree

2 files changed

+66
-1
lines changed

2 files changed

+66
-1
lines changed

code_submitter/server.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import io
22
import zipfile
3+
import datetime
34

45
import databases
56
from sqlalchemy.sql import select
@@ -13,7 +14,7 @@
1314
from starlette.datastructures import UploadFile
1415
from starlette.middleware.authentication import AuthenticationMiddleware
1516

16-
from . import auth, config
17+
from . import auth, utils, config
1718
from .auth import User
1819
from .tables import Archive, ChoiceHistory
1920

@@ -119,9 +120,28 @@ async def upload(request: Request) -> Response:
119120
status_code=302,
120121
)
121122

123+
124+
@requires(['authenticated', 'blueshirt'])
125+
async def download_submissions(request: Request) -> Response:
126+
buffer = io.BytesIO()
127+
with zipfile.ZipFile(buffer, mode='w') as zf:
128+
await utils.collect_submissions(database, zf)
129+
130+
filename = 'submissions-{now}.zip'.format(
131+
now=datetime.datetime.now(datetime.timezone.utc),
132+
)
133+
134+
return Response(
135+
buffer.getvalue(),
136+
headers={'Content-Disposition': f'attachment; filename="{filename}"'},
137+
media_type='application/zip',
138+
)
139+
140+
122141
routes = [
123142
Route('/', endpoint=homepage, methods=['GET']),
124143
Route('/upload', endpoint=upload, methods=['POST']),
144+
Route('/download-submissions', endpoint=download_submissions, methods=['GET']),
125145
]
126146

127147
middleware = [

tests/tests_app.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,48 @@ def test_upload_archive_without_robot_py(self) -> None:
275275
self.database.fetch_all(ChoiceHistory.select()),
276276
)
277277
self.assertEqual([], choices, "Should not have created a choice")
278+
279+
def test_download_submissions_requires_blueshirt(self) -> None:
280+
response = self.session.get(self.url_for('download_submissions'))
281+
self.assertEqual(403, response.status_code)
282+
283+
def test_download_submissions_when_none(self) -> None:
284+
self.session.auth = ('blueshirt', 'blueshirt')
285+
286+
response = self.session.get(self.url_for('download_submissions'))
287+
self.assertEqual(200, response.status_code)
288+
289+
with zipfile.ZipFile(io.BytesIO(response.content)) as zf:
290+
self.assertCountEqual(
291+
['summary.txt'],
292+
zf.namelist(),
293+
)
294+
295+
def test_download_submissions(self) -> None:
296+
self.session.auth = ('blueshirt', 'blueshirt')
297+
298+
self.await_(self.database.execute(
299+
Archive.insert().values(
300+
id=8888888888,
301+
content=b'',
302+
username='someone_else',
303+
team='ABC',
304+
created=datetime.datetime(2020, 8, 8, 12, 0),
305+
),
306+
))
307+
self.await_(self.database.execute(
308+
ChoiceHistory.insert().values(
309+
archive_id=8888888888,
310+
username='test_user',
311+
created=datetime.datetime(2020, 9, 9, 12, 0),
312+
),
313+
))
314+
315+
response = self.session.get(self.url_for('download_submissions'))
316+
self.assertEqual(200, response.status_code)
317+
318+
with zipfile.ZipFile(io.BytesIO(response.content)) as zf:
319+
self.assertCountEqual(
320+
['summary.txt', 'ABC.zip'],
321+
zf.namelist(),
322+
)

0 commit comments

Comments
 (0)