Repository: CTFd/CTFd

Issue:
Hints can move the scoreboard after the CTF is over
If someone pays to unlock a hint after the CTF is over their dot will move on the scoreboard to reflect it.

1 possible solution. Make hints automatically free after CTF time is done
Hints can move the scoreboard after the CTF is over
If someone pays to unlock a hint after the CTF is over their dot will move on the scoreboard to reflect it.

1 possible solution. Make hints automatically free after CTF time is done


Discussion:
Ah good catch I didn't think of that. Hints for free after the CTF is over makes sense. 
i found that the hints can not be deleted,please help.

Thanks 

Sounds like things need a good overhaul. In the meantime you can edit it into a useless hint with no value. 

Hopefully I'll work on it over the weekend. 
@Colbert337 I'm not able to reproduce, do you have some kind of example or stack trace I could see? 
Ah good catch I didn't think of that. Hints for free after the CTF is over makes sense. 
i found that the hints can not be deleted,please help.

Thanks 

Sounds like things need a good overhaul. In the meantime you can edit it into a useless hint with no value. 

Hopefully I'll work on it over the weekend. 
@Colbert337 I'm not able to reproduce, do you have some kind of example or stack trace I could see? 

Resolving patch:
diff --git a/CTFd/challenges.py b/CTFd/challenges.py
--- a/CTFd/challenges.py
+++ b/CTFd/challenges.py
@@ -17,6 +17,8 @@
 
 @challenges.route('/hints/<int:hintid>', methods=['GET', 'POST'])
 def hints_view(hintid):
+    if not utils.ctf_started():
+        abort(403)
     hint = Hints.query.filter_by(id=hintid).first_or_404()
     chal = Challenges.query.filter_by(id=hint.chal).first()
     unlock = Unlocks.query.filter_by(model='hints', itemid=hintid, teamid=session['id']).first()
@@ -33,7 +35,7 @@ def hints_view(hintid):
                 'cost': hint.cost
             })
     elif request.method == 'POST':
-        if not unlock:
+        if not unlock and utils.ctftime():
             team = Teams.query.filter_by(id=session['id']).first()
             if team.score() < hint.cost:
                 return jsonify({'errors': 'Not enough points'})
@@ -49,6 +51,14 @@ def hints_view(hintid):
             }
             db.session.close()
             return jsonify(json_data)
+        elif utils.ctf_ended():
+            json_data = {
+                'hint': hint.hint,
+                'chal': hint.chal,
+                'cost': hint.cost
+            }
+            db.session.close()
+            return jsonify(json_data)
         else:
             json_data = {
                 'hint': hint.hint,
@@ -104,7 +114,7 @@ def chals():
             unlocked_hints = set([u.itemid for u in Unlocks.query.filter_by(model='hints', teamid=session['id'])])
             hints = []
             for hint in Hints.query.filter_by(chal=x.id).all():
-                if hint.id in unlocked_hints:
+                if hint.id in unlocked_hints or utils.ctf_ended():
                     hints.append({'id': hint.id, 'cost': hint.cost, 'hint': hint.hint})
                 else:
                     hints.append({'id': hint.id, 'cost': hint.cost})


Test patch: