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 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 itsdangerous import TimedSerializer, BadTimeSignature
|
||||
from werkzeug.utils import secure_filename
|
||||
|
@ -59,6 +59,8 @@ def init_admin(app):
|
|||
view_challenges_unregistered = 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.value = start
|
||||
|
||||
|
@ -79,39 +81,31 @@ def init_admin(app):
|
|||
db.session.commit()
|
||||
return redirect('/admin/config')
|
||||
|
||||
start = Config.query.filter_by(key="start").first()
|
||||
if start:
|
||||
start = start.value
|
||||
else:
|
||||
start = Config('start', None)
|
||||
db.session.add(start)
|
||||
do_api_key = get_config('do_api_key')
|
||||
if not do_api_key:
|
||||
set_config('do_api_key', None)
|
||||
|
||||
end = Config.query.filter_by(key="end").first()
|
||||
if end:
|
||||
end = end.value
|
||||
else:
|
||||
end = Config('end', None)
|
||||
db.session.add(end)
|
||||
start = get_config('start')
|
||||
if not start:
|
||||
set_config('start', None)
|
||||
|
||||
view_challenges_unregistered = Config.query.filter_by(key='view_challenges_unregistered').first()
|
||||
if view_challenges_unregistered:
|
||||
view_challenges_unregistered = (view_challenges_unregistered.value == '1')
|
||||
else:
|
||||
view_challenges_unregistered = Config('view_challenges_unregistered', None)
|
||||
db.session.add(view_challenges_unregistered)
|
||||
end = get_config('end')
|
||||
if not end:
|
||||
set_config('end', None)
|
||||
|
||||
prevent_registration = Config.query.filter_by(key='prevent_registration').first()
|
||||
if prevent_registration:
|
||||
prevent_registration = (prevent_registration.value == '1')
|
||||
else:
|
||||
prevent_registration = Config('prevent_registration', None)
|
||||
db.session.add(prevent_registration)
|
||||
view_challenges_unregistered = get_config('view_challenges_unregistered') == '1'
|
||||
if not view_challenges_unregistered:
|
||||
set_config('view_challenges_unregistered', None)
|
||||
|
||||
prevent_registration = get_config('prevent_registration') == '1'
|
||||
if not prevent_registration:
|
||||
set_config('prevent_registration', None)
|
||||
|
||||
db.session.commit()
|
||||
db.session.close()
|
||||
|
||||
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/<route>', methods=['GET', 'POST'])
|
||||
|
@ -148,7 +142,18 @@ def init_admin(app):
|
|||
@app.route('/admin/hosts', methods=['GET'])
|
||||
@admins_only
|
||||
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'])
|
||||
@admins_only
|
||||
|
|
|
@ -11,7 +11,7 @@ from struct import unpack, pack
|
|||
import time
|
||||
import datetime
|
||||
import hashlib
|
||||
import json
|
||||
import digitalocean
|
||||
|
||||
def init_utils(app):
|
||||
app.jinja_env.filters['unix_time'] = unix_time
|
||||
|
@ -40,6 +40,7 @@ def is_admin():
|
|||
else:
|
||||
return False
|
||||
|
||||
|
||||
def can_register():
|
||||
config = Config.query.filter_by(key='prevent_registration').first()
|
||||
if config:
|
||||
|
@ -111,6 +112,23 @@ def get_kpm(teamid): # keys per minute
|
|||
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())
|
||||
|
||||
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():
|
||||
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):
|
||||
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
|
||||
six==1.8.0
|
||||
itsdangerous
|
||||
dop
|
||||
python-digitalocean
|
|
@ -1,5 +1,6 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title></title>
|
||||
<meta charset="utf-8">
|
||||
|
@ -10,45 +11,55 @@
|
|||
<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>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<nav class="top-bar" data-topbar>
|
||||
<ul class="title-area">
|
||||
<li class="name">
|
||||
<h1><a href="/">CTF</a></h1>
|
||||
</li>
|
||||
<li class="toggle-topbar menu-icon"><a href="#">Menu</a></li>
|
||||
</ul>
|
||||
|
||||
<section class="top-bar-section">
|
||||
<!-- Right Nav Section -->
|
||||
<ul class="right">
|
||||
<ul class="title-area">
|
||||
<li class="name">
|
||||
<h1><a href="/">CTF</a></h1>
|
||||
</li>
|
||||
<li class="toggle-topbar menu-icon"><a href="#">Menu</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Left Nav Section -->
|
||||
<ul class="left">
|
||||
<li><a href="/admin/graphs">Graphs</a></li>
|
||||
<li><a href="/admin/pages">Pages</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>
|
||||
<section class="top-bar-section">
|
||||
<!-- Right Nav Section -->
|
||||
<ul class="right">
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- Left Nav Section -->
|
||||
<ul class="left">
|
||||
<li><a href="/admin/graphs">Graphs</a>
|
||||
</li>
|
||||
<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>
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
{% block content %} {% 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/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/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>
|
||||
$(document).foundation();
|
||||
$(document).foundation();
|
||||
</script>
|
||||
{% block scripts %}
|
||||
{% endblock %}
|
||||
{% block scripts %} {% endblock %}
|
||||
</body>
|
||||
|
||||
</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