diff --git a/ctf.nginx b/ctf.nginx
index f866686..bd36907 100644
--- a/ctf.nginx
+++ b/ctf.nginx
@@ -17,6 +17,10 @@ server {
default_type text/html;
try_files /index.html /index.html;
}
+ location ~^/admin/(problems)$ {
+ default_type text/html;
+ try_files /index.html /index.html;
+ }
location ~ /api {
proxy_set_header Host $host;
diff --git a/deploy b/deploy
index 2d6014c..bb04d8e 100755
--- a/deploy
+++ b/deploy
@@ -5,7 +5,9 @@ pkill gunicorn
sudo service nginx stop
tmux kill-session -t ctf 2> /dev/null
+sudo cp /vagrant/ctf.nginx /etc/nginx/sites-enabled/ctf
+
echo "Starting the server..."
cd /home/vagrant/server
sudo service nginx start
-tmux new-session -s ctf -d 'gunicorn "app:app" -c /home/vagrant/scripts/gunicorn.py.ini'
+tmux new-session -s ctf -d 'gunicorn "app:app" -c /home/vagrant/scripts/gunicorn.py.ini'
\ No newline at end of file
diff --git a/server/api.html b/server/api.html
new file mode 100644
index 0000000..dfb8ca9
--- /dev/null
+++ b/server/api.html
@@ -0,0 +1,31 @@
+
+
+
Python: package api
+
+
+
+
+
+
+
+
+
+Package Contents |
+
+ | |
+ |
+
\ No newline at end of file
diff --git a/server/api/admin.py b/server/api/admin.py
index 5152a88..8af0c3c 100644
--- a/server/api/admin.py
+++ b/server/api/admin.py
@@ -1,19 +1,26 @@
from flask import Blueprint, jsonify
-from decorators import admins_only, api_wrapper, login_required
+from decorators import admins_only, api_wrapper
from models import db, Problems, Files
+import json
+
blueprint = Blueprint("admin", __name__)
-@blueprint.route("/problem/data", methods=["POST"])
-#@api_wrapper # Disable atm due to json serialization issues: will fix
+@blueprint.route("/problems/list", methods=["POST"])
+@api_wrapper
@admins_only
-@login_required
def problem_data():
- problems = Problems.query.add_columns("pid", "name", "category", "description", "hint", "value", "solves", "disabled", "flag").order_by(Problems.value).all()
- jason = []
-
- for problem in problems:
- problem_files = [ str(_file.location) for _file in Files.query.filter_by(pid=int(problem.pid)).all() ]
- jason.append({"pid": problem[1], "name": problem[2] ,"category": problem[3], "description": problem[4], "hint": problem[5], "value": problem[6], "solves": problem[7], "disabled": problem[8], "flag": problem[9], "files": problem_files})
-
- return jsonify(data=jason)
+ problems = Problems.query.order_by(Problems.value).all()
+ problems_return = [ ]
+ for problem in problems:
+ problems_return.append({
+ "pid": problem.pid,
+ "name": problem.name,
+ "category": problem.category,
+ "description": problem.description,
+ "hint": problem.hint,
+ "value": problem.value,
+ "threshold": problem.threshold,
+ "weightmap": json.loads(problem.weightmap)
+ })
+ return { "success": 1, "problems": problems_return }
\ No newline at end of file
diff --git a/server/api/models.py b/server/api/models.py
index e93fa88..715d880 100644
--- a/server/api/models.py
+++ b/server/api/models.py
@@ -1,5 +1,5 @@
from flask.ext.sqlalchemy import SQLAlchemy
-import datetime
+import time
import utils
db = SQLAlchemy()
@@ -14,6 +14,8 @@ class Users(db.Model):
password = db.Column(db.String(128))
admin = db.Column(db.Boolean)
utype = db.Column(db.Integer)
+ tid = db.Column(db.Integer)
+ registertime = db.Column(db.Integer)
def __init__(self, name, username, email, password, utype=1):
self.name = name
@@ -23,6 +25,7 @@ class Users(db.Model):
self.password = utils.hash_password(password)
self.utype = utype
self.admin = False
+ self.registertime = int(time.time())
class Teams(db.Model):
tid = db.Column(db.Integer, primary_key=True)
@@ -90,11 +93,11 @@ class LoginTokens(db.Model):
ua = db.Column(db.String(128))
ip = db.Column(db.String(16))
- def __init__(self, uid, username, expiry=datetime.datetime.utcnow(), active=True, ua=None, ip=None):
+ def __init__(self, uid, username, expiry=int(time.time()), active=True, ua=None, ip=None):
self.sid = utils.generate_string()
self.uid = uid
self.username = username
- self.issued = datetime.datetime.utcnow()
+ self.issued = int(time.time())
self.expiry = expiry
self.active = active
self.ua = ua
diff --git a/server/api/user.py b/server/api/user.py
index c814368..bc786c8 100644
--- a/server/api/user.py
+++ b/server/api/user.py
@@ -6,6 +6,7 @@ from models import db, LoginTokens, Users
from decorators import api_wrapper, WebException
from schemas import verify_to_schema, check
+import datetime
import logger
import re
import requests
@@ -43,7 +44,7 @@ def user_register():
return { "success": 1, "message": "Success!" }
-@blueprint.route("/logout", methods=["GET", "POST"])
+@blueprint.route("/logout", methods=["POST"])
@api_wrapper
def user_logout():
sid = session["sid"]
@@ -80,6 +81,36 @@ def user_status():
}
return result
+@blueprint.route("/info", methods=["POST"])
+@api_wrapper
+def user_info():
+ logged_in = is_logged_in()
+ username = utils.flat_multi(request.form).get("username")
+ if username is None:
+ if logged_in:
+ username = session["username"]
+ if username is None:
+ raise WebException("No user specified.")
+ me = username.lower() == session["username"].lower()
+ user = get_user(username_lower=username.lower()).first()
+ if user is None:
+ raise WebException("User not found.")
+
+ show_email = me if logged_in else False
+ userdata = {
+ "user_found": True,
+ "name": user.name,
+ "username": user.username,
+ "type": ["Student", "Instructor", "Observer"][user.utype - 1],
+ "admin": user.admin,
+ "registertime": datetime.datetime.fromtimestamp(user.registertime).isoformat() + "Z",
+ "me": me,
+ "show_email": show_email
+ }
+ if show_email:
+ userdata["email"] = user.email
+ return { "success": 1, "user": userdata }
+
##################
# USER FUNCTIONS #
##################
@@ -148,7 +179,7 @@ def login_user(username, password):
session["sid"] = token.sid
session["username"] = token.username
- session["admin"] = user.utype == 0
+ session["admin"] = user.admin == True
return True
diff --git a/server/app.py b/server/app.py
index 7ba7b69..e5bd14a 100644
--- a/server/app.py
+++ b/server/app.py
@@ -5,6 +5,8 @@ import api
import config
import json
+from api.decorators import api_wrapper
+
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = config.SQLALCHEMY_DATABASE_URI
@@ -24,8 +26,9 @@ app.register_blueprint(api.problem.blueprint, url_prefix="/api/problem")
api.logger.initialize_logs()
@app.route("/api")
+@api_wrapper
def api_main():
- return json.dumps({ "success": 1, "message": "The API is online." })
+ return { "success": 1, "message": "The API is online." }
if __name__ == "__main__":
with app.app_context():
diff --git a/web/css/easyctf.css b/web/css/easyctf.css
index 4690001..9325a9e 100644
--- a/web/css/easyctf.css
+++ b/web/css/easyctf.css
@@ -10,4 +10,14 @@
* {
font-family: "Proxima Nova";
+}
+
+.tab-content {
+ padding: 10px;
+ > .tab-pane {
+ display: none;
+ }
+ > .active {
+ display: block;
+ }
}
\ No newline at end of file
diff --git a/web/index.html b/web/index.html
index 47c0305..d875017 100644
--- a/web/index.html
+++ b/web/index.html
@@ -39,6 +39,16 @@
Chat
+
+ Admin
+
+
{{ config.navbar["username"] }}