From 7aa6204116a8b92dfab155b97c824a9ddc38afa7 Mon Sep 17 00:00:00 2001 From: Kevin Chung Date: Sun, 6 Aug 2017 19:33:02 -0400 Subject: [PATCH] Users should always be able to get their score, even if banned (#333) * Users should always be able to get their score, even if banned * Fixing scoring logic when users haven't solved problems * Hide None descriptions for awards --- CTFd/models.py | 8 +++- CTFd/themes/original/templates/team.html | 2 +- tests/helpers.py | 7 +++ tests/test_user_facing.py | 58 ++++++++++++++++++++++++ 4 files changed, 72 insertions(+), 3 deletions(-) diff --git a/CTFd/models.py b/CTFd/models.py index 70a9ca5..f56e91c 100644 --- a/CTFd/models.py +++ b/CTFd/models.py @@ -178,7 +178,7 @@ class Teams(db.Model): def score(self, admin=False): score = db.func.sum(Challenges.value).label('score') - team = db.session.query(Solves.teamid, score).join(Teams).join(Challenges).filter(Teams.banned == False, Teams.id == self.id) + team = db.session.query(Solves.teamid, score).join(Teams).join(Challenges).filter(Teams.id == self.id) award_score = db.func.sum(Awards.value).label('award_score') award = db.session.query(award_score).filter_by(teamid=self.id) @@ -193,8 +193,12 @@ class Teams(db.Model): team = team.group_by(Solves.teamid).first() award = award.first() - if team: + if team and award: return int(team.score or 0) + int(award.award_score or 0) + elif team: + return int(team.score or 0) + elif award: + return int(award.award_score or 0) else: return 0 diff --git a/CTFd/themes/original/templates/team.html b/CTFd/themes/original/templates/team.html index 0c90dba..b9614c6 100644 --- a/CTFd/themes/original/templates/team.html +++ b/CTFd/themes/original/templates/team.html @@ -61,7 +61,7 @@ {% endif %}

{{ award.name }}

{% if award.category %}

{{ award.category }}

{% endif %} -

{{ award.description }}

+ {% if award.description %}

{{ award.description }}

{% endif %}

{{ award.value }}

{% endfor %} diff --git a/tests/helpers.py b/tests/helpers.py index 864fc60..abc0def 100644 --- a/tests/helpers.py +++ b/tests/helpers.py @@ -101,6 +101,13 @@ def gen_team(db, name='name', email='user@ctfd.io', password='password'): return team +def gen_hint(db, chal, hint="This is a hint", cost=0, type=0): + hint = Hints(chal, hint, cost, type) + db.session.add(hint) + db.session.commit() + return hint + + def gen_solve(db, teamid, chalid, ip='127.0.0.1', flag='rightkey'): solve = Solves(teamid, chalid, ip, flag) db.session.add(solve) diff --git a/tests/test_user_facing.py b/tests/test_user_facing.py index 1140a91..ca59009 100644 --- a/tests/test_user_facing.py +++ b/tests/test_user_facing.py @@ -495,3 +495,61 @@ def test_ctfd_setup_redirect(): r = client.get('/themes/original/static/css/style.css') assert r.status_code == 200 destroy_ctfd(app) + + +def test_user_cannot_unlock_hint(): + """Test that a user can't unlock a hint if they don't have enough points""" + app = create_ctfd() + with app.app_context(): + with app.test_client() as client: + register_user(app, name="user1", email="user1@ctfd.io") + + chal = gen_challenge(app.db, value=100) + chal_id = chal.id + + flag = gen_flag(app.db, chal=chal.id, flag='flag') + + hint = gen_hint(db, chal_id, cost=10) + hint_id = hint.id + + client = login_as_user(app, name="user1", password="password") + + with client.session_transaction() as sess: + data = { + "nonce": sess.get('nonce') + } + r = client.post('/hints/{}'.format(hint_id), data=data) + resp = json.loads(r.data.decode('utf8')) + assert resp.get('errors') == 'Not enough points' + destroy_ctfd(app) + + +def test_user_can_unlock_hint(): + """Test that a user can unlock a hint if they have enough points""" + app = create_ctfd() + with app.app_context(): + with app.test_client() as client: + register_user(app, name="user1", email="user1@ctfd.io") + + chal = gen_challenge(app.db, value=100) + chal_id = chal.id + + flag = gen_flag(app.db, chal=chal.id, flag='flag') + + hint = gen_hint(app.db, chal_id, cost=10) + hint_id = hint.id + + award = gen_award(app.db, teamid=2, value=15) + + client = login_as_user(app, name="user1", password="password") + + with client.session_transaction() as sess: + data = { + "nonce": sess.get('nonce') + } + r = client.post('/hints/{}'.format(hint_id), data=data) + resp = json.loads(r.data.decode('utf8')) + assert resp.get('errors') is None + assert resp.get('hint') + assert resp.get('chal') == chal_id + destroy_ctfd(app)