Listing DO hosts

Swapped out API wrappers
selenium-screenshot-testing
CodeKevin 2015-01-24 03:50:45 -05:00
parent 6b81ac4577
commit b1c09e832e
5 changed files with 146 additions and 55 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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,13 +11,15 @@
<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>
</li>
</ul> </ul>
<section class="top-bar-section"> <section class="top-bar-section">
@ -27,19 +30,27 @@
<!-- Left Nav Section --> <!-- Left Nav Section -->
<ul class="left"> <ul class="left">
<li><a href="/admin/graphs">Graphs</a></li> <li><a href="/admin/graphs">Graphs</a>
<li><a href="/admin/pages">Pages</a></li> </li>
<li><a href="/admin/teams">Teams</a></li> <li><a href="/admin/pages">Pages</a>
<li><a href="/admin/scoreboard">Scoreboard</a></li> </li>
<li><a href="/admin/chals">Challenges</a></li> <li><a href="/admin/hosts">Hosts</a>
<li><a href="/admin/statistics">Statistics</a></li> </li>
<li><a href="/admin/config">Config</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> </ul>
</section> </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>
@ -48,7 +59,7 @@
<script> <script>
$(document).foundation(); $(document).foundation();
</script> </script>
{% block scripts %} {% block scripts %} {% endblock %}
{% endblock %}
</body> </body>
</html> </html>

View File

@ -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 %}