mirror of https://github.com/JohnHammond/CTFd.git
parent
6b81ac4577
commit
b1c09e832e
|
@ -1,5 +1,5 @@
|
||||||
from flask import render_template, request, redirect, abort, jsonify, url_for, session
|
from flask import render_template, request, redirect, abort, jsonify, url_for, session
|
||||||
from CTFd.utils import sha512, is_safe_url, authed, admins_only, is_admin, unix_time, unix_time_millis
|
from CTFd.utils import sha512, is_safe_url, authed, admins_only, is_admin, unix_time, unix_time_millis, get_config, set_config, get_digitalocean
|
||||||
from CTFd.models import db, Teams, Solves, Challenges, WrongKeys, Keys, Tags, Files, Tracking, Pages, Config
|
from CTFd.models import db, Teams, Solves, Challenges, WrongKeys, Keys, Tags, Files, Tracking, Pages, Config
|
||||||
from itsdangerous import TimedSerializer, BadTimeSignature
|
from itsdangerous import TimedSerializer, BadTimeSignature
|
||||||
from werkzeug.utils import secure_filename
|
from werkzeug.utils import secure_filename
|
||||||
|
@ -59,6 +59,8 @@ def init_admin(app):
|
||||||
view_challenges_unregistered = None
|
view_challenges_unregistered = None
|
||||||
prevent_registration = None
|
prevent_registration = None
|
||||||
|
|
||||||
|
do_api_key = set_config("do_api_key", request.form.get('do_api_key', None))
|
||||||
|
|
||||||
db_start = Config.query.filter_by(key='start').first()
|
db_start = Config.query.filter_by(key='start').first()
|
||||||
db_start.value = start
|
db_start.value = start
|
||||||
|
|
||||||
|
@ -79,39 +81,31 @@ def init_admin(app):
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return redirect('/admin/config')
|
return redirect('/admin/config')
|
||||||
|
|
||||||
start = Config.query.filter_by(key="start").first()
|
do_api_key = get_config('do_api_key')
|
||||||
if start:
|
if not do_api_key:
|
||||||
start = start.value
|
set_config('do_api_key', None)
|
||||||
else:
|
|
||||||
start = Config('start', None)
|
|
||||||
db.session.add(start)
|
|
||||||
|
|
||||||
end = Config.query.filter_by(key="end").first()
|
start = get_config('start')
|
||||||
if end:
|
if not start:
|
||||||
end = end.value
|
set_config('start', None)
|
||||||
else:
|
|
||||||
end = Config('end', None)
|
|
||||||
db.session.add(end)
|
|
||||||
|
|
||||||
view_challenges_unregistered = Config.query.filter_by(key='view_challenges_unregistered').first()
|
end = get_config('end')
|
||||||
if view_challenges_unregistered:
|
if not end:
|
||||||
view_challenges_unregistered = (view_challenges_unregistered.value == '1')
|
set_config('end', None)
|
||||||
else:
|
|
||||||
view_challenges_unregistered = Config('view_challenges_unregistered', None)
|
|
||||||
db.session.add(view_challenges_unregistered)
|
|
||||||
|
|
||||||
prevent_registration = Config.query.filter_by(key='prevent_registration').first()
|
view_challenges_unregistered = get_config('view_challenges_unregistered') == '1'
|
||||||
if prevent_registration:
|
if not view_challenges_unregistered:
|
||||||
prevent_registration = (prevent_registration.value == '1')
|
set_config('view_challenges_unregistered', None)
|
||||||
else:
|
|
||||||
prevent_registration = Config('prevent_registration', None)
|
prevent_registration = get_config('prevent_registration') == '1'
|
||||||
db.session.add(prevent_registration)
|
if not prevent_registration:
|
||||||
|
set_config('prevent_registration', None)
|
||||||
|
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
db.session.close()
|
db.session.close()
|
||||||
|
|
||||||
return render_template('admin/config.html', start=start, end=end, view_challenges_unregistered=view_challenges_unregistered,
|
return render_template('admin/config.html', start=start, end=end, view_challenges_unregistered=view_challenges_unregistered,
|
||||||
prevent_registration=prevent_registration)
|
prevent_registration=prevent_registration, do_api_key=do_api_key)
|
||||||
|
|
||||||
@app.route('/admin/pages', defaults={'route': None}, methods=['GET', 'POST'])
|
@app.route('/admin/pages', defaults={'route': None}, methods=['GET', 'POST'])
|
||||||
@app.route('/admin/pages/<route>', methods=['GET', 'POST'])
|
@app.route('/admin/pages/<route>', methods=['GET', 'POST'])
|
||||||
|
@ -148,7 +142,18 @@ def init_admin(app):
|
||||||
@app.route('/admin/hosts', methods=['GET'])
|
@app.route('/admin/hosts', methods=['GET'])
|
||||||
@admins_only
|
@admins_only
|
||||||
def admin_hosts():
|
def admin_hosts():
|
||||||
return render_template('admin/hosts.html')
|
m = get_digitalocean()
|
||||||
|
errors = []
|
||||||
|
if not m:
|
||||||
|
errors.append("Your Digital Ocean API key is not set")
|
||||||
|
return render_template('admin/hosts.html', errors=errors)
|
||||||
|
|
||||||
|
hosts = m.get_all_droplets()
|
||||||
|
slugs = m.get_all_sizes()
|
||||||
|
images = m.get_all_images()
|
||||||
|
regions = m.get_all_regions()
|
||||||
|
|
||||||
|
return render_template('admin/hosts.html', hosts=hosts, slugs=slugs, images=images, regions=regions)
|
||||||
|
|
||||||
@app.route('/admin/chals', methods=['POST', 'GET'])
|
@app.route('/admin/chals', methods=['POST', 'GET'])
|
||||||
@admins_only
|
@admins_only
|
||||||
|
|
|
@ -11,7 +11,7 @@ from struct import unpack, pack
|
||||||
import time
|
import time
|
||||||
import datetime
|
import datetime
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import digitalocean
|
||||||
|
|
||||||
def init_utils(app):
|
def init_utils(app):
|
||||||
app.jinja_env.filters['unix_time'] = unix_time
|
app.jinja_env.filters['unix_time'] = unix_time
|
||||||
|
@ -40,6 +40,7 @@ def is_admin():
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def can_register():
|
def can_register():
|
||||||
config = Config.query.filter_by(key='prevent_registration').first()
|
config = Config.query.filter_by(key='prevent_registration').first()
|
||||||
if config:
|
if config:
|
||||||
|
@ -111,6 +112,23 @@ def get_kpm(teamid): # keys per minute
|
||||||
one_min_ago = datetime.datetime.utcnow() + datetime.timedelta(minutes=-1)
|
one_min_ago = datetime.datetime.utcnow() + datetime.timedelta(minutes=-1)
|
||||||
return len(db.session.query(WrongKeys).filter(WrongKeys.team == teamid, WrongKeys.date >= one_min_ago).all())
|
return len(db.session.query(WrongKeys).filter(WrongKeys.team == teamid, WrongKeys.date >= one_min_ago).all())
|
||||||
|
|
||||||
|
def get_config(key):
|
||||||
|
config = Config.query.filter_by(key=key).first()
|
||||||
|
if config:
|
||||||
|
return config.value
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def set_config(key, value):
|
||||||
|
config = Config.query.filter_by(key=key).first()
|
||||||
|
if config:
|
||||||
|
config.value = value
|
||||||
|
else:
|
||||||
|
config = Config(key, value)
|
||||||
|
db.session.add(config)
|
||||||
|
db.session.commit()
|
||||||
|
return config
|
||||||
|
|
||||||
|
|
||||||
def mailserver():
|
def mailserver():
|
||||||
if app.config['MAIL_SERVER'] and app.config['MAIL_PORT'] and app.config['ADMINS']:
|
if app.config['MAIL_SERVER'] and app.config['MAIL_PORT'] and app.config['ADMINS']:
|
||||||
|
@ -133,3 +151,10 @@ def is_safe_url(target):
|
||||||
|
|
||||||
def sha512(string):
|
def sha512(string):
|
||||||
return hashlib.sha512(string).hexdigest()
|
return hashlib.sha512(string).hexdigest()
|
||||||
|
|
||||||
|
def get_digitalocean():
|
||||||
|
token = get_config('do_api_key')
|
||||||
|
if token:
|
||||||
|
return digitalocean.Manager(token=token)
|
||||||
|
else:
|
||||||
|
return False
|
|
@ -8,4 +8,4 @@ passlib==1.6.2
|
||||||
py-bcrypt==0.4
|
py-bcrypt==0.4
|
||||||
six==1.8.0
|
six==1.8.0
|
||||||
itsdangerous
|
itsdangerous
|
||||||
dop
|
python-digitalocean
|
|
@ -1,5 +1,6 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title></title>
|
<title></title>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
|
@ -10,45 +11,55 @@
|
||||||
<link rel="stylesheet" type="text/css" href="/static/admin/css/style.css">
|
<link rel="stylesheet" type="text/css" href="/static/admin/css/style.css">
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.5.1/moment.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav class="top-bar" data-topbar>
|
<nav class="top-bar" data-topbar>
|
||||||
<ul class="title-area">
|
<ul class="title-area">
|
||||||
<li class="name">
|
<li class="name">
|
||||||
<h1><a href="/">CTF</a></h1>
|
<h1><a href="/">CTF</a></h1>
|
||||||
</li>
|
</li>
|
||||||
<li class="toggle-topbar menu-icon"><a href="#">Menu</a></li>
|
<li class="toggle-topbar menu-icon"><a href="#">Menu</a>
|
||||||
</ul>
|
|
||||||
|
|
||||||
<section class="top-bar-section">
|
|
||||||
<!-- Right Nav Section -->
|
|
||||||
<ul class="right">
|
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<!-- Left Nav Section -->
|
<section class="top-bar-section">
|
||||||
<ul class="left">
|
<!-- Right Nav Section -->
|
||||||
<li><a href="/admin/graphs">Graphs</a></li>
|
<ul class="right">
|
||||||
<li><a href="/admin/pages">Pages</a></li>
|
</li>
|
||||||
<li><a href="/admin/teams">Teams</a></li>
|
</ul>
|
||||||
<li><a href="/admin/scoreboard">Scoreboard</a></li>
|
|
||||||
<li><a href="/admin/chals">Challenges</a></li>
|
<!-- Left Nav Section -->
|
||||||
<li><a href="/admin/statistics">Statistics</a></li>
|
<ul class="left">
|
||||||
<li><a href="/admin/config">Config</a></li>
|
<li><a href="/admin/graphs">Graphs</a>
|
||||||
</ul>
|
</li>
|
||||||
</section>
|
<li><a href="/admin/pages">Pages</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="/admin/hosts">Hosts</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="/admin/teams">Teams</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="/admin/scoreboard">Scoreboard</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="/admin/chals">Challenges</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="/admin/statistics">Statistics</a>
|
||||||
|
</li>
|
||||||
|
<li><a href="/admin/config">Config</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
{% block content %}
|
{% block content %} {% endblock %}
|
||||||
{% endblock %}
|
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/vendor/jquery.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/vendor/jquery.js"></script>
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/vendor/modernizr.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/vendor/modernizr.js"></script>
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/pagedown/1.0/Markdown.Converter.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/pagedown/1.0/Markdown.Converter.min.js"></script>
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/foundation.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/foundation.min.js"></script>
|
||||||
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/foundation/foundation.topbar.min.js"></script>
|
<script src="//cdnjs.cloudflare.com/ajax/libs/foundation/5.4.7/js/foundation/foundation.topbar.min.js"></script>
|
||||||
<script>
|
<script>
|
||||||
$(document).foundation();
|
$(document).foundation();
|
||||||
</script>
|
</script>
|
||||||
{% block scripts %}
|
{% block scripts %} {% endblock %}
|
||||||
{% endblock %}
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
|
@ -0,0 +1,50 @@
|
||||||
|
{% extends "admin/base.html" %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="row">
|
||||||
|
<br>
|
||||||
|
<h1>Hosts</h1>
|
||||||
|
<br>
|
||||||
|
{% for error in errors %}
|
||||||
|
<div class="large-8 large-centered columns">
|
||||||
|
<div data-alert class="alert-box alert radius centered text-center">
|
||||||
|
<span>{{ error }}</span>
|
||||||
|
<a href="#" class="close">×</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
<table id="teamsboard">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<td><b>ID</b>
|
||||||
|
</td>
|
||||||
|
<td><b>Status</b>
|
||||||
|
</td>
|
||||||
|
<td><b>Name</b>
|
||||||
|
</td>
|
||||||
|
<td><b>IP Address</b>
|
||||||
|
</td>
|
||||||
|
<td><b>Memory</b>
|
||||||
|
</td>
|
||||||
|
<td><b>Disk</b>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for host in hosts %}
|
||||||
|
<tr>
|
||||||
|
<td>{{ host.id }}</td>
|
||||||
|
<td>{{ host.status }}</td>
|
||||||
|
<td>{{ host.name }}</td>
|
||||||
|
<td>{{ host.ip_address }}</td>
|
||||||
|
<td>{{ host.memory }} <sub>MB</sub></td>
|
||||||
|
<td>{{ host.disk }} <sub>GB</sub></td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block scripts %}
|
||||||
|
{% endblock %}
|
Loading…
Reference in New Issue