From 60e1b5fae8e281af16a4d4f2fb25adf9ecb760ba Mon Sep 17 00:00:00 2001 From: Jonathan Wu Date: Sat, 5 Aug 2023 11:31:30 -0400 Subject: [PATCH] Fixes #209 --- src/application.py | 14 +++++++------- src/templates/contest/edit_problem.html | 6 +++++- src/templates/problem/edit_problem.html | 6 +++++- src/tests/conftest.py | 1 + src/tests/test_contest.py | 7 +++++-- src/tests/test_problems.py | 17 +++++++++++++---- src/views/contest.py | 12 +++++++++++- src/views/problem.py | 9 +++++++++ 8 files changed, 56 insertions(+), 16 deletions(-) diff --git a/src/application.py b/src/application.py index 1c7d642..2f879fc 100644 --- a/src/application.py +++ b/src/application.py @@ -737,13 +737,6 @@ def create_problem(): flash('A problem with this name or ID already exists', 'danger') return render_template("problem/create.html"), 409 - # Check if file exists & upload if it does - file = request.files["file"] - if file.filename: - filename = problem_id + ".zip" - file.save("dl/" + filename) - description += f'\n\n[{filename}](/dl/{filename})' - # Modify problems table db.execute(("INSERT INTO problems (id, name, point_value, category, flag, draft, " "flag_hint, instanced) VALUES (:id, :name, :point_value, :category, " @@ -751,6 +744,13 @@ def create_problem(): id=problem_id, name=name, point_value=point_value, category=category, flag=flag, draft=draft, fhint=flag_hint, inst=instanced) + # Check if file exists & upload if it does + file = request.files["file"] + if file.filename: + filename = problem_id + ".zip" + file.save("dl/" + filename) + description += f'\n\n[{filename}](/dl/{filename})' + os.makedirs('metadata/problems/' + problem_id) write_file('metadata/problems/' + problem_id + '/description.md', description) write_file('metadata/problems/' + problem_id + '/hints.md', hints) diff --git a/src/templates/contest/edit_problem.html b/src/templates/contest/edit_problem.html index 54c76f4..c687302 100644 --- a/src/templates/contest/edit_problem.html +++ b/src/templates/contest/edit_problem.html @@ -9,7 +9,7 @@ {% block main %}

Edit {{ data["name"] }}

-
+
Edit {{ data["name"] }} required>
+
+ + +
diff --git a/src/templates/problem/edit_problem.html b/src/templates/problem/edit_problem.html index d50b165..39bc5c7 100644 --- a/src/templates/problem/edit_problem.html +++ b/src/templates/problem/edit_problem.html @@ -9,7 +9,7 @@ {% block main %}

Edit {{ data["name"] }}

-
+
Edit {{ data["name"] }} required>
+
+ + +
diff --git a/src/tests/conftest.py b/src/tests/conftest.py index 154a076..e0a773e 100644 --- a/src/tests/conftest.py +++ b/src/tests/conftest.py @@ -23,6 +23,7 @@ def client(): app.config['USE_CAPTCHA'] = False app.config['WTF_CSRF_ENABLED'] = False app.config['SECRET_KEY'] = 'testing_secret_key' + open('fake_empty_file', 'w').close() return app.test_client() diff --git a/src/tests/test_contest.py b/src/tests/test_contest.py index 28d5e56..7419833 100644 --- a/src/tests/test_contest.py +++ b/src/tests/test_contest.py @@ -121,6 +121,7 @@ def test_contest(client, database): 'hints': 'try looking at the title 2', 'point_value': 2, 'category': 'web', + 'file': ('fake_empty_file', ''), 'instanced': True, }) assert result.status_code == 302 @@ -281,7 +282,8 @@ def test_contest(client, database): 'name': 'dynscore', 'description': 'dynamic is fun', 'category': 'web', - 'flag': 'ctf{nobodywillguessme}' + 'flag': 'ctf{nobodywillguessme}', + 'file': ('fake_empty_file', ''), }) assert result.status_code == 302 @@ -293,7 +295,8 @@ def test_contest(client, database): 'description': 'dynamic is fun', 'category': 'web', 'flag': 'ctf{nobodywillguessmeagain}', - 'rejudge': True + 'rejudge': True, + 'file': ('fake_empty_file', ''), }) assert result.status_code == 302 diff --git a/src/tests/test_problems.py b/src/tests/test_problems.py index f4ac5e5..6aab635 100644 --- a/src/tests/test_problems.py +++ b/src/tests/test_problems.py @@ -61,7 +61,8 @@ def test_problem(client, database): 'point_value': 2, 'rejudge': True, 'category': 'web', - 'flag': 'ctf{hello}' + 'flag': 'ctf{hello}', + 'file': ('fake_empty_file', ''), }) assert result.status_code == 400 assert b'required' in result.data @@ -73,11 +74,15 @@ def test_problem(client, database): 'point_value': 2, 'rejudge': True, 'category': 'web', - 'flag': '\x2f\x10' + 'flag': '\x2f\x10', + 'file': ('fake_empty_file', ''), }) assert result.status_code == 400 assert b'Invalid' in result.data + file = open("test_upload.txt", "w") + file.write('ree2') + file.close() result = client.post('/problem/helloworldtesting/edit', data={ 'name': 'hello world 2', 'description': 'a short fun problem 2', @@ -86,10 +91,14 @@ def test_problem(client, database): 'rejudge': True, 'category': 'web', 'flag': 'ctf{hello}', - 'flag_hint': 'ctf{...}' + 'flag_hint': 'ctf{...}', + 'file': ('test_upload.txt', 'test_upload.txt'), }, follow_redirects=True) assert result.status_code == 200 + result = client.get('/dl/helloworldtesting.zip') + assert result.data == b'ree2' + result = client.get('/users/admin/profile') assert result.status_code == 200 assert b'2 Points' in result.data @@ -112,7 +121,7 @@ def test_problem(client, database): result = client.get('/api/problem?id=helloworldtesting') assert json.loads(result.data)['status'] == 'success' - assert json.loads(result.data)['data']['description'] == 'a short fun problem 2' + assert json.loads(result.data)['data']['description'].startswith('a short fun problem 2') assert json.loads(result.data)['data']['hints'] == 'try looking at the title 2' assert json.loads(result.data)['data']['editorial'] == 'sample editorial' assert json.loads(result.data)['data']['flag_hint'] == 'ctf{...}' diff --git a/src/views/contest.py b/src/views/contest.py index e527a86..5de339f 100644 --- a/src/views/contest.py +++ b/src/views/contest.py @@ -315,6 +315,7 @@ def publish_contest_problem(contest_id, problem_id): @api.route('//problem//edit', methods=["GET", "POST"]) @admin_required def edit_contest_problem(contest_id, problem_id): + # Ensure contest exists if not contest_exists(contest_id): return render_template("contest/contest_noexist.html"), 404 @@ -376,7 +377,16 @@ def edit_contest_problem(contest_id, problem_id): "flag_hint=:fhint, instanced=:inst WHERE contest_id=:cid AND problem_id=:pid"), name=new_name, category=new_category, flag=new_flag, cid=contest_id, pid=problem_id, fhint=new_flag_hint, inst=new_instanced) - + # Check if file exists & upload if it does + file = request.files["file"] + if file.filename: + if not os.path.exists("dl/" + contest_id): + os.makedirs("dl/" + contest_id) + filename = problem_id + ".zip" + filepath = "dl/" + contest_id + "/" + file.save(filepath + filename) + if f'[{filename}](/{filepath + filename})' not in new_description: + new_description += f'\n\n[{filename}](/{filepath + filename})' write_file( f'metadata/contests/{contest_id}/{problem_id}/description.md', new_description) write_file(f'metadata/contests/{contest_id}/{problem_id}/hints.md', new_hint) diff --git a/src/views/problem.py b/src/views/problem.py index a6d08df..59d661c 100644 --- a/src/views/problem.py +++ b/src/views/problem.py @@ -178,6 +178,15 @@ def editproblem(problem_id): "(SELECT user_id FROM problem_solved WHERE problem_id=:pid)"), dpv=new_points - data[0]["point_value"], pid=problem_id ) + + # Check if file exists & upload if it does + file = request.files["file"] + if file.filename: + filename = problem_id + ".zip" + file.save("dl/" + filename) + if f'[{filename}](/dl/{filename})' not in new_description: + new_description += f'\n\n[{filename}](/dl/{filename})' + write_file('metadata/problems/' + problem_id + '/description.md', new_description) write_file('metadata/problems/' + problem_id + '/hints.md', new_hint)