mirror of https://github.com/JohnHammond/CTFd.git
Optionally allow unregistered users to view challenges
Add a Config entry `view_challenges_unregistered` to indicate whether unregistered users can view challenges. Add the setting to the admin config page. Add can_view_challenges() to utils to test if a user is either authed, or the configuration allow unauthenticated users to view the challenges. Return a HTTP 401 Unauthorized error when the /chals/solves API can't provide results for an unauthenticated user. This is needed because the client side code in `chalboard.js` doesn't know if it's logged in or not and requests this anyway. (And AJAX doesn't handle redirects very well.) Alternately the client could actually know if they're logged in and not make needless API calls. When an unregistered user attempts to submit a flag, it will also fail. The user will be redirected to a login page.selenium-screenshot-testing
parent
c5c3126bb4
commit
2972cf506d
|
@ -52,7 +52,12 @@ def init_admin(app):
|
|||
start = None
|
||||
end = None
|
||||
|
||||
print repr(start), repr(end)
|
||||
try:
|
||||
view_challenges_unregistered = bool(request.form.get('view_challenges_unregistered', None))
|
||||
except (ValueError, TypeError):
|
||||
view_challenges_unregistered = None
|
||||
|
||||
print repr(start), repr(end), repr(view_challenges_unregistered)
|
||||
|
||||
db_start = Config.query.filter_by(key='start').first()
|
||||
db_start.value = start
|
||||
|
@ -60,14 +65,19 @@ def init_admin(app):
|
|||
db_end = Config.query.filter_by(key='end').first()
|
||||
db_end.value = end
|
||||
|
||||
db_view_challenges_unregistered = Config.query.filter_by(key='view_challenges_unregistered').first()
|
||||
db_view_challenges_unregistered.value = view_challenges_unregistered
|
||||
|
||||
db.session.add(db_start)
|
||||
db.session.add(db_end)
|
||||
db.session.add(db_view_challenges_unregistered)
|
||||
|
||||
db.session.commit()
|
||||
return redirect('/admin/config')
|
||||
start = Config.query.filter_by(key="start").first().value
|
||||
end = Config.query.filter_by(key="end").first().value
|
||||
return render_template('admin/config.html', start=start, end=end)
|
||||
view_challenges_unregistered = (Config.query.filter_by(key='view_challenges_unregistered').first().value == '1')
|
||||
return render_template('admin/config.html', start=start, end=end, view_challenges_unregistered=view_challenges_unregistered)
|
||||
|
||||
@app.route('/admin/pages', defaults={'route': None}, methods=['GET', 'POST'])
|
||||
@app.route('/admin/pages/<route>', methods=['GET', 'POST'])
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from flask import current_app as app, render_template, request, redirect, abort, jsonify, json as json_mod, url_for, session
|
||||
|
||||
from CTFd.utils import ctftime, authed, unix_time, get_kpm
|
||||
from CTFd.utils import ctftime, authed, unix_time, get_kpm, can_view_challenges
|
||||
from CTFd.models import db, Challenges, Files, Solves, WrongKeys, Keys
|
||||
|
||||
import time
|
||||
|
@ -12,7 +12,7 @@ def init_challenges(app):
|
|||
def challenges():
|
||||
if not ctftime():
|
||||
return redirect('/')
|
||||
if authed():
|
||||
if can_view_challenges():
|
||||
return render_template('chals.html')
|
||||
else:
|
||||
return redirect(url_for('login', next="challenges"))
|
||||
|
@ -21,7 +21,7 @@ def init_challenges(app):
|
|||
def chals():
|
||||
if not ctftime():
|
||||
return redirect('/')
|
||||
if authed():
|
||||
if can_view_challenges():
|
||||
chals = Challenges.query.add_columns('id', 'name', 'value', 'description', 'category').order_by(Challenges.value).all()
|
||||
|
||||
json = {'game':[]}
|
||||
|
@ -37,7 +37,7 @@ def init_challenges(app):
|
|||
|
||||
@app.route('/chals/solves')
|
||||
def chals_per_solves():
|
||||
if authed():
|
||||
if can_view_challenges():
|
||||
solves = Solves.query.add_columns(db.func.count(Solves.chalid)).group_by(Solves.chalid).all()
|
||||
json = {}
|
||||
for chal, count in solves:
|
||||
|
@ -52,7 +52,7 @@ def init_challenges(app):
|
|||
if authed():
|
||||
solves = Solves.query.filter_by(teamid=session['id']).all()
|
||||
else:
|
||||
return redirect('/login')
|
||||
abort(401)
|
||||
else:
|
||||
solves = Solves.query.filter_by(teamid=teamid).all()
|
||||
db.session.close()
|
||||
|
|
|
@ -83,6 +83,9 @@ def ctftime():
|
|||
|
||||
return False
|
||||
|
||||
def can_view_challenges():
|
||||
return authed() or (Config.query.filter_by(key="view_challenges_unregistered").first().value == '1');
|
||||
|
||||
def unix_time(dt):
|
||||
epoch = datetime.datetime.utcfromtimestamp(0)
|
||||
delta = dt - epoch
|
||||
|
|
|
@ -63,12 +63,16 @@ def init_views(app):
|
|||
start = Config('start', None)
|
||||
end = Config('end', None)
|
||||
|
||||
## Challenges cannot be viewed by unregistered users
|
||||
view_challenges_unregistered = Config('view_challenges_unregistered', None)
|
||||
|
||||
setup = Config('setup', True)
|
||||
|
||||
db.session.add(admin)
|
||||
db.session.add(page)
|
||||
db.session.add(start)
|
||||
db.session.add(end)
|
||||
db.session.add(view_challenges_unregistered)
|
||||
db.session.add(setup)
|
||||
db.session.commit()
|
||||
app.setup = False
|
||||
|
|
|
@ -6,11 +6,21 @@
|
|||
<h1>Config</h1>
|
||||
<form method="POST">
|
||||
<input name='nonce' type='hidden' value="{{ nonce }}">
|
||||
<strong>Start Date:</strong>
|
||||
<input name='start' type='text' placeholder="Start Date (UTC timestamp)" {% if start is defined and start != None %}value="{{ start }}"{% endif %}>
|
||||
|
||||
<strong>End Date:</strong>
|
||||
<input name='end' type='text' placeholder="End Date (UTC timestamp)" {% if end is defined and end != None %}value="{{ end }}"{% endif %}>
|
||||
<div class="row">
|
||||
<label for="start">Start Date:</label>
|
||||
<input id='start' name='start' type='text' placeholder="Start Date (UTC timestamp)" {% if start is defined and start != None %}value="{{ start }}"{% endif %}>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<label for="end">End Date:</label>
|
||||
<input id='end' name='end' type='text' placeholder="End Date (UTC timestamp)" {% if end is defined and end != None %}value="{{ end }}"{% endif %}>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<input id="view_challenges_unregistered" name="view_challenges_unregistered" type="checkbox" {% if view_challenges_unregistered %}checked{% endif %}>
|
||||
<label for="view_challenges_unregistered">Unregistered users can view challenges</label>
|
||||
</div>
|
||||
|
||||
<button class="radius" type='submit'>Submit</button>
|
||||
</form>
|
||||
|
|
Loading…
Reference in New Issue