Fix freeze time regressions (#989)

* Fix freeze time regressions in 2.x
* Make `/api/v1/[users,teams]/[me,id]/[solves,fails,awards]` endpoints load as admin to load all rows and bypass freeze
    * Closes #988
* Make `/api/v1/challenges/[id]/solves` respect freeze time. `/api/v1/challenges/[id]/solves?preview=true` is exposed for admins to see solves as a user would. 
    * Closes #986
This commit is contained in:
Kevin Chung
2019-05-11 00:18:56 -04:00
committed by GitHub
parent b7a19f74ff
commit 3d23ece370
8 changed files with 321 additions and 42 deletions

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from CTFd.models import Users, Challenges, Tags, Hints, Flags
from CTFd.models import Users, Challenges, Tags, Hints, Flags, Solves
from CTFd.utils import set_config
from tests.helpers import (
create_ctfd,
@@ -442,6 +442,54 @@ def test_api_challenge_get_solves_ctftime_public():
destroy_ctfd(app)
def test_api_challenge_get_solves_ctf_frozen():
"""Test users can only see challenge solves that happened before freeze time"""
app = create_ctfd()
with app.app_context():
register_user(app, name="user1", email="user1@ctfd.io")
register_user(app, name="user2", email="user2@ctfd.io")
# Friday, October 6, 2017 12:00:00 AM GMT-04:00 DST
set_config('freeze', '1507262400')
with freeze_time("2017-10-4"):
chal = gen_challenge(app.db)
chal_id = chal.id
gen_solve(app.db, user_id=2, challenge_id=chal_id)
chal2 = gen_challenge(app.db)
chal2_id = chal2.id
with freeze_time("2017-10-8"):
chal2 = gen_solve(app.db, user_id=2, challenge_id=chal2_id)
# There should now be two solves assigned to the same user.
assert Solves.query.count() == 2
client = login_as_user(app, name="user2")
# Challenge 1 should have one solve
r = client.get('/api/v1/challenges/1/solves')
data = r.get_json()['data']
assert len(data) == 1
# Challenge 2 should have a solve shouldn't be shown to the user
r = client.get('/api/v1/challenges/2/solves')
data = r.get_json()['data']
assert len(data) == 0
# Admins should see data as an admin with no modifications
admin = login_as_user(app, name="admin")
r = admin.get('/api/v1/challenges/2/solves')
data = r.get_json()['data']
assert len(data) == 1
# But should see as a user if the preview param is passed
r = admin.get('/api/v1/challenges/2/solves?preview=true')
data = r.get_json()['data']
assert len(data) == 0
destroy_ctfd(app)
def test_api_challenge_get_solves_visibility_private():
"""Can a private user get /api/v1/challenges/<challenge_id>/solves if challenge_visibility is private/public"""
app = create_ctfd()