From 34fe70600b58fe66e39d612b58c52e2756dc0eb6 Mon Sep 17 00:00:00 2001 From: James Wang Date: Sat, 16 Apr 2016 22:15:57 -0400 Subject: [PATCH] Implement problem viewing and problem submitting --- server/api/logger.py | 2 +- server/api/models.py | 5 ++-- server/api/problem.py | 46 ++++++++++++++++++---------- web/js/easyctf.js | 14 +++++++++ web/pages/problems.html | 66 +++++++++++++++++++++++++++++++++++++++-- 5 files changed, 110 insertions(+), 23 deletions(-) diff --git a/server/api/logger.py b/server/api/logger.py index 1d886b7..81cd451 100644 --- a/server/api/logger.py +++ b/server/api/logger.py @@ -31,4 +31,4 @@ def initialize_logs(): def log(logname, message, level=INFO): logger = logging.getLogger(logname) message = "[%s] %s" % (datetime.datetime.now().strftime("%m/%d/%Y %X"), message) - logger.log(level, message) \ No newline at end of file + logger.log(level, message) diff --git a/server/api/models.py b/server/api/models.py index 2366a22..7bb3cb0 100644 --- a/server/api/models.py +++ b/server/api/models.py @@ -166,9 +166,8 @@ class Files(db.Model): self.location = location class Solves(db.Model): - __table_args__ = (db.UniqueConstraint("pid", "tid"), {}) sid = db.Column(db.Integer, primary_key=True) - pid = db.Column(db.Integer) + pid = db.Column(db.String(32)) tid = db.Column(db.Integer) date = db.Column(db.Integer, default=utils.get_time_since_epoch()) correct = db.Column(db.Boolean) @@ -214,7 +213,7 @@ class TeamInvitations(db.Model): class Settings(db.Model): sid = db.Column(db.Integer, primary_key=True) - key = db.Column(db.Text, unique=True) + key = db.Column(db.Text) value = db.Column(db.Text) def __init__(self, key, value): diff --git a/server/api/problem.py b/server/api/problem.py index b36af60..8f639e2 100644 --- a/server/api/problem.py +++ b/server/api/problem.py @@ -1,4 +1,5 @@ import hashlib +import imp import logger import os import shutil @@ -115,38 +116,51 @@ def problem_submit(): problem = Problems.query.filter_by(pid=pid).first() team = Teams.query.filter_by(tid=tid).first() + solved = Solves.query.filter_by(pid=pid, tid=tid, correct=1).first() + if solved: + raise WebException("You already solved this problem.") if problem: - if flag == problem.flag: - solve = Solves(pid, tid) - team.score += problem.value - problem.solves += 1 + grader = imp.load_source("grader.py", problem.grader) + if grader.grade(flag): + solve = Solves(pid, tid, flag, True) db.session.add(solve) - db.session.add(team) - db.session.add(problem) db.session.commit() - logger.log(__name__, logger.WARNING, "%s has solved %s by submitting %s" % (team.name, problem.title, flag)) + logger.log(__name__, "%s has solved %s by submitting %s" % (team.teamname, problem.title, flag), level=logger.WARNING) return { "success": 1, "message": "Correct!" } else: - logger.log(__name__, logger.WARNING, "%s has incorrectly submitted %s to %s" % (team.name, flag, problem.title)) + solve = Solves(pid, tid, flag, False) + db.session.add(solve) + db.session.commit() + logger.log(__name__, "%s has incorrectly submitted %s to %s" % (team.teamname, flag, problem.title), level=logger.WARNING) raise WebException("Incorrect.") else: raise WebException("Problem does not exist!") -@blueprint.route("/data", methods=["POST"]) -#@api_wrapper # Disable atm due to json serialization issues: will fix +@blueprint.route("/data", methods=["GET"]) @login_required +@api_wrapper def problem_data(): - problems = Problems.query.add_columns("pid", "name", "category", "description", "hint", "value", "solves").order_by(Problems.value).filter_by(disabled=False).all() - jason = [] + problems = Problems.query.order_by(Problems.value).all() + problems_return = [] 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], "title": problem[2] ,"category": problem[3], "description": problem[4], "hint": problem[5], "value": problem[6], "solves": problem[7], "files": problem_files}) - - return jsonify(data=jason) + solves = Solves.query.filter_by(pid=problem.pid, correct=1).count() + solved = Solves.query.filter_by(pid=problem.pid, tid=session.get("tid", None), correct=1) + solved = ["Solved", "Unsolved"][solved is None] + problems_return.append({ + "pid": problem.pid, + "title": problem.title, + "category": problem.category, + "description": problem.description, + "hint": problem.hint, + "value": problem.value, + "solves": solves, + "solved": solved + }) + return { "success": 1, "problems": problems_return } def insert_problem(data, force=False): with app.app_context(): diff --git a/web/js/easyctf.js b/web/js/easyctf.js index 72c8d32..b51deb9 100644 --- a/web/js/easyctf.js +++ b/web/js/easyctf.js @@ -48,6 +48,10 @@ app.config(function($routeProvider, $locationProvider) { templateUrl: "pages/settings.html", controller: "settingsController" }) + .when("/problems", { + templateUrl: "pages/problems.html", + controller: "problemsController" + }) .when("/forgot", { templateUrl: "pages/forgot.html", controller: "resetController" @@ -271,6 +275,16 @@ app.controller("settingsController", ["$controller", "$scope", "$http", function }); }]); +app.controller("problemsController", ["$controller", "$scope", "$http", function($controller, $scope, $http) { + $controller("loginController", { $scope: $scope }); + api_call("GET", "/api/problem/data", {}, function(result) { + if (result["success"] == 1) { + $scope.problems = result["problems"]; + } + $scope.$apply(); + }); +}]); + $.fn.serializeObject = function() { var a, o; o = {}; diff --git a/web/pages/problems.html b/web/pages/problems.html index 614ed91..e189f66 100644 --- a/web/pages/problems.html +++ b/web/pages/problems.html @@ -5,7 +5,67 @@ 3) remove these instructions (:P) -->
-

Problems

-
+

Problems

+
+
+
+
+

+ {{ problem["title"] }} {{ problem["value"] }} points +
{{ problem["category"] }} - {{ problem["solved"] }} ({{ problem["solves"] }} {{ problem["solves"] === 1 ? "solve" : "solves" }})
+

+
+
+
+ + +
+
+ + + + + + + + +
+
+
+
+
+
-