Repository: CTFd/CTFd
Pull request #859 (2019-01-30 23:45:26)

Fix showing incorrect 'CTF has ended' error if view_after_ctf is set
* Fix showing incorrect 'CTF has ended' error if `view_after_ctf` is set.

codecov[bot]: # [Codecov](https://codecov.io/gh/CTFd/CTFd/pull/859?src=pr&el=h1) Report
> Merging [#859](https://codecov.io/gh/CTFd/CTFd/pull/859?src=pr&el=desc) into [master](https://codecov.io/gh/CTFd/CTFd/commit/ae8ce0b4309fa62d5781b26754c6f7463c32e584?src=pr&el=desc) will **decrease** coverage by `0.28%`.
> The diff coverage is `100%`.

[![Impacted file tree graph](https://codecov.io/gh/CTFd/CTFd/pull/859/graphs/tree.svg?width=650&token=IfPqkWkt9A&height=150&src=pr)](https://codecov.io/gh/CTFd/CTFd/pull/859?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master     #859      +/-   ##
==========================================
- Coverage   86.44%   86.15%   -0.29%     
==========================================
  Files          91       91              
  Lines        4595     4595              
==========================================
- Hits         3972     3959      -13     
- Misses        623      636      +13
```


| [Impacted Files](https://codecov.io/gh/CTFd/CTFd/pull/859?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [CTFd/challenges.py](https://codecov.io/gh/CTFd/CTFd/pull/859/diff?src=pr&el=tree#diff-Q1RGZC9jaGFsbGVuZ2VzLnB5) | `100% <100%> (ø)` | :arrow_up: |
| [CTFd/utils/encoding/\_\_init\_\_.py](https://codecov.io/gh/CTFd/CTFd/pull/859/diff?src=pr&el=tree#diff-Q1RGZC91dGlscy9lbmNvZGluZy9fX2luaXRfXy5weQ==) | `65.62% <0%> (-21.88%)` | :arrow_down: |
| [CTFd/utils/\_\_init\_\_.py](https://codecov.io/gh/CTFd/CTFd/pull/859/diff?src=pr&el=tree#diff-Q1RGZC91dGlscy9fX2luaXRfXy5weQ==) | `93.47% <0%> (-6.53%)` | :arrow_down: |
| [CTFd/admin/challenges.py](https://codecov.io/gh/CTFd/CTFd/pull/859/diff?src=pr&el=tree#diff-Q1RGZC9hZG1pbi9jaGFsbGVuZ2VzLnB5) | `96.55% <0%> (-3.45%)` | :arrow_down: |
| [CTFd/utils/exports/\_\_init\_\_.py](https://codecov.io/gh/CTFd/CTFd/pull/859/diff?src=pr&el=tree#diff-Q1RGZC91dGlscy9leHBvcnRzL19faW5pdF9fLnB5) | `79.03% <0%> (-0.81%)` | :arrow_down: |
| [CTFd/api/v1/challenges.py](https://codecov.io/gh/CTFd/CTFd/pull/859/diff?src=pr&el=tree#diff-Q1RGZC9hcGkvdjEvY2hhbGxlbmdlcy5weQ==) | `93.7% <0%> (-0.4%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/CTFd/CTFd/pull/859?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/CTFd/CTFd/pull/859?src=pr&el=footer). Last update [ae8ce0b...fc59c4f](https://codecov.io/gh/CTFd/CTFd/pull/859?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).


Patch:
diff --git a/CTFd/challenges.py b/CTFd/challenges.py
index d2a2b6d2..30ef0cf2 100644
--- a/CTFd/challenges.py
+++ b/CTFd/challenges.py
@@ -10,7 +10,7 @@ from CTFd.utils.decorators import (
 )
 from CTFd.utils.decorators.visibility import check_challenge_visibility
 from CTFd.utils import config, text_type, user as current_user, get_config
-from CTFd.utils.dates import ctf_paused, view_after_ctf
+from CTFd.utils.dates import ctf_paused, view_after_ctf, ctf_ended
 from CTFd.utils.helpers import get_errors, get_infos
 
 challenges = Blueprint('challenges', __name__)
@@ -30,7 +30,8 @@ def listing():
     if ctf_paused():
         infos.append('{} is paused'.format(config.ctf_name()))
 
-    if view_after_ctf():
+    # CTF has ended but we want to allow view_after_ctf. Show error but let JS load challenges.
+    if ctf_ended() and view_after_ctf():
         infos.append('{} has ended'.format(config.ctf_name()))
 
     return render_template('challenges.html', infos=infos, errors=errors, start=int(start), end=int(end))


Test patch:
diff --git a/tests/users/test_challenges.py b/tests/users/test_challenges.py
index d6f83355..a1b2f5ca 100644
--- a/tests/users/test_challenges.py
+++ b/tests/users/test_challenges.py
@@ -503,6 +503,55 @@ def test_challenges_cannot_be_solved_while_paused():
     destroy_ctfd(app)
 
 
+def test_challenge_board_under_view_after_ctf():
+    """Test that the challenge board does not show an error under view_after_ctf"""
+    app = create_ctfd()
+    with app.app_context():
+        set_config('view_after_ctf', True)
+        set_config('start', '1507089600')  # Wednesday, October 4, 2017 12:00:00 AM GMT-04:00 DST
+        set_config('end', '1507262400')  # Friday, October 6, 2017 12:00:00 AM GMT-04:00 DST
+
+        register_user(app)
+        client = login_as_user(app)
+
+        gen_challenge(app.db)
+        gen_flag(app.db, challenge_id=1, content='flag')
+
+        gen_challenge(app.db)
+        gen_flag(app.db, challenge_id=2, content='flag')
+
+        # CTF is ongoing. Normal operation.
+        with freeze_time("2017-10-5"):
+            r = client.get('/challenges')
+            assert r.status_code == 200
+            assert "has ended" not in r.get_data(as_text=True)
+
+            data = {
+                "submission": 'flag',
+                "challenge_id": 1
+            }
+            r = client.post('/api/v1/challenges/attempt', json=data)
+            assert r.status_code == 200
+            assert r.get_json()['data']['status'] == "correct"
+            assert Solves.query.count() == 1
+
+        # CTF is now over. There should be a message and challenges should show submission status but not store solves
+        with freeze_time("2017-10-7"):
+            r = client.get('/challenges')
+            assert r.status_code == 200
+            assert "has ended" in r.get_data(as_text=True)
+
+            data = {
+                "submission": 'flag',
+                "challenge_id": 2
+            }
+            r = client.post('/api/v1/challenges/attempt', json=data)
+            assert r.status_code == 200
+            assert r.get_json()['data']['status'] == "correct"
+            assert Solves.query.count() == 1
+    destroy_ctfd(app)
+
+
 def test_challenges_under_view_after_ctf():
     app = create_ctfd()
     with app.app_context(), freeze_time("2017-10-7"):