edited button disabling

This commit is contained in:
Michael Zhang 2016-01-18 00:41:11 -06:00
parent 0a47adb419
commit ecb080e358
7 changed files with 141 additions and 176 deletions

View file

@ -3,5 +3,6 @@ import logger
import models
import problem
import user
import stats
import team
import utils

View file

@ -108,11 +108,11 @@ def problem_submit():
db.session.add(problem)
db.session.commit()
logger.log("submissions.log", logger.WARNING, "%s has solved %s by submitting %s" % (team.name, problem.name, flag))
logger.log(__name__, logger.WARNING, "%s has solved %s by submitting %s" % (team.name, problem.name, flag))
return { "success": 1, "message": "Correct!" }
else:
logger.log("submissions.log", logger.WARNING, "%s has incorrectly submitted %s to %s" % (team.name, flag, problem.name))
logger.log(__name__, logger.WARNING, "%s has incorrectly submitted %s to %s" % (team.name, flag, problem.name))
raise WebException("Incorrect.")
else:

22
server/api/stats.py Normal file
View file

@ -0,0 +1,22 @@
from flask import Blueprint, request, session
from flask import current_app as app
from decorators import api_wrapper
import team
blueprint = Blueprint("stats", __name__)
@blueprint.route("/scoreboard")
@api_wrapper
def all_teams_stats():
teams = team.get_team().all()
result = [ ]
for _team in teams:
result.append({
"teamname": _team.teamname,
"tid": _team.tid,
"school": _team.school,
"points": _team.points()
})
return { "success": 1, "scoreboard": result }

View file

@ -23,50 +23,50 @@ blueprint = Blueprint("user", __name__)
@blueprint.route("/forgot/<token>", methods=["GET", "POST"])
@api_wrapper
def user_forgot_password(token=None):
params = utils.flat_multi(request.form)
if token is not None:
user = get_user(reset_token=token).first()
if user is None:
raise WebException("Invalid reset token.")
params = utils.flat_multi(request.form)
if token is not None:
user = get_user(reset_token=token).first()
if user is None:
raise WebException("Invalid reset token.")
# We are viewing the actual reset form
if request.method == "GET":
return { "success": 1, "message": ""}
# We are viewing the actual reset form
if request.method == "GET":
return { "success": 1, "message": ""}
# Submission of actual reset form
if request.method == "POST":
password = params.get("password")
confirm_password = params.get("confirm_password")
if password != confirm_password:
raise WebException("Passwords do not match.")
else:
user.password = utils.hash_password(password)
user.reset_token = None
current_session = db.session.object_session(user)
current_session.add(user)
current_session.commit()
return { "success": 1, "message": "Success!" }
else:
email = params.get("email")
# Submission of actual reset form
if request.method == "POST":
password = params.get("password")
confirm_password = params.get("confirm_password")
if password != confirm_password:
raise WebException("Passwords do not match.")
else:
user.password = utils.hash_password(password)
user.reset_token = None
current_session = db.session.object_session(user)
current_session.add(user)
current_session.commit()
return { "success": 1, "message": "Success!" }
else:
email = params.get("email").lower()
user = get_user(email=email).first()
if user is None:
raise WebException("User with that email does not exist.")
user = get_user(email=email).first()
if user is None:
raise WebException("User with that email does not exist.")
token = utils.generate_string(length=64)
user.reset_token = token
current_session = db.session.object_session(user)
current_session.add(user)
current_session.commit()
token = utils.generate_string(length=64)
user.reset_token = token
current_session = db.session.object_session(user)
current_session.add(user)
current_session.commit()
reset_link = "%s/forgot/%s" % ("127.0.0.1:8000", token)
subject = "EasyCTF password reset"
body = """%s,\n\nA request to reset your EasyCT password has been made. If you did not request this password reset, you may safely ignore this email and delete it.\n\nYou may reset your password by clicking this link or pasting it to your browser.\n\n%s\n\nThis link can only be used once, and will lead you to a page where you can reset your password.\n\nGood luck!\n\n- The EasyCTF Team""" % (user.username, reset_link)
response = utils.send_email(email, subject, body).json()
if "Queued" in response["message"]:
return { "success": 1, "message": "Email sent to %s" % email }
else:
raise WebException(response["message"])
reset_link = "%s/forgot/%s" % ("127.0.0.1:8000", token)
subject = "EasyCTF password reset"
body = """%s,\n\nA request to reset your EasyCTF password has been made. If you did not request this password reset, you may safely ignore this email and delete it.\n\nYou may reset your password by clicking this link or pasting it to your browser.\n\n%s\n\nThis link can only be used once, and will lead you to a page where you can reset your password.\n\nGood luck!\n\n- The EasyCTF Team""" % (user.username, reset_link)
response = utils.send_email(email, subject, body).json()
if "Queued" in response["message"]:
return { "success": 1, "message": "Email sent to %s" % email }
else:
raise WebException(response["message"])
@blueprint.route("/register", methods=["POST"])
@api_wrapper
@ -89,7 +89,7 @@ def user_register():
db.session.add(user)
db.session.commit()
logger.log("registrations", logger.INFO, "%s registered with %s" % (name.encode("utf-8"), email.encode("utf-8")))
logger.log(__name__, logger.INFO, "%s registered with %s" % (name.encode("utf-8"), email.encode("utf-8")))
login_user(username, password)
return { "success": 1, "message": "Success!" }
@ -200,22 +200,22 @@ UserSchema = Schema({
}, extra=True)
def get_user(username=None, username_lower=None, email=None, uid=None, reset_token=None):
match = {}
if username != None:
match.update({ "username": username })
elif username_lower != None:
match.update({ "username_lower": username_lower })
elif uid != None:
match.update({ "uid": uid })
elif email != None:
match.update({ "email": email })
elif is_logged_in():
match.update({ "username": session["username"] })
elif reset_token != None:
match.update({ "reset_token": reset_token })
with app.app_context():
result = Users.query.filter_by(**match)
return result
match = {}
if username != None:
match.update({ "username": username })
elif username_lower != None:
match.update({ "username_lower": username_lower })
elif uid != None:
match.update({ "uid": uid })
elif email != None:
match.update({ "email": email })
elif is_logged_in():
match.update({ "username": session["username"] })
elif reset_token != None:
match.update({ "reset_token": reset_token })
with app.app_context():
result = Users.query.filter_by(**match)
return result
def login_user(username, password):
user = get_user(username_lower=username.lower()).first()
@ -237,8 +237,8 @@ def login_user(username, password):
session["sid"] = token.sid
session["username"] = token.username
session["admin"] = user.admin == True
if user.tid is not None and user.tid >= 0:
session["tid"] = user.tid
if user.tid is not None and user.tid >= 0:
session["tid"] = user.tid
return True

View file

@ -24,6 +24,7 @@ app.secret_key = config.SECRET_KEY
app.register_blueprint(api.admin.blueprint, url_prefix="/api/admin")
app.register_blueprint(api.problem.blueprint, url_prefix="/api/problem")
app.register_blueprint(api.stats.blueprint, url_prefix="/api/stats")
app.register_blueprint(api.team.blueprint, url_prefix="/api/team")
app.register_blueprint(api.user.blueprint, url_prefix="/api/user")
api.logger.initialize_logs()

View file

@ -42,7 +42,7 @@ app.config(function($routeProvider, $locationProvider) {
})
.when("/scoreboard", {
templateUrl: "pages/scoreboard.html",
controller: "mainController"
controller: "scoreboardController"
})
.when("/settings", {
templateUrl: "pages/settings.html",
@ -128,6 +128,23 @@ app.controller("teamController", ["$controller", "$scope", "$http", "$routeParam
} else {
$controller("loginController", { $scope: $scope });
}
$.get("/api/team/info", data, function(result) {
if (result["success"] == 1) {
$scope.team = result["team"];
}
$scope.$apply();
$(".timeago").timeago();
});
}]);
app.controller("scoreboardController", ["$controller", "$scope", "$http", function($controller, $scope, $http) {
$controller("mainController", { $scope: $scope });
api_call("GET", "/api/stats/scoreboard", { }, function(result) {
if (result["success"] == 1) {
$scope.scoreboard = result["scoreboard"];
$scope.$apply();
}
});
}]);
app.controller("resetController", ["$controller", "$scope", "$http", "$routeParams", function($controller, $scope, $http, $routeParams) {
@ -214,20 +231,19 @@ $.fn.serializeObject = function() {
var register_form = function() {
var input = "#register_form input";
var data = $("#register_form").serializeObject();
var button = $("#register_form").find(":submit");
button.prop("disabled", true);
$(input).attr("disabled", "disabled");
api_call("POST", "/api/user/register", data, function(result) {
if (result["success"] == 1) {
location.href = "/profile";
} else {
display_message("register_msg", "danger", result["message"], function() {
button.removeAttr("disabled");
$(input).removeAttr("disabled");
});
}
}).fail(function(jqXHR, status, error) {
var result = JSON.parse(jqXHR["responseText"]);
display_message("register_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
button.removeAttr("disabled");
$(input).removeAttr("disabled");
});
});
};
@ -235,20 +251,19 @@ var register_form = function() {
// password reset
var request_reset_form = function() {
var data = $("#request_reset_form").serializeObject();
var button = $("#request_reset_form").find(":submit");
button.prop("disabled", true);
$(input).attr("disabled", "disabled");
api_call("POST", "/api/user/forgot", data, function(result) {
if (result["success"] == 1) {
display_message("reset_msg", "success", result["message"]);
} else {
display_message("reset_msg", "danger", result["message"], function() {
button.removeAttr("disabled");
$(input).removeAttr("disabled");
});
}
}).fail(function(jqXHR, status, error) {
var result = JSON.parse(jqXHR["responseText"]);
display_message("reset_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
button.removeAttr("disabled");
$(input).removeAttr("disabled");
});
});
}
@ -258,8 +273,7 @@ var reset_form = function() {
data["csrf_token"] = $.cookie("csrf_token");
var url = window.location.href;
var token = url.substr(url.lastIndexOf("/")+1);
var button = $("#reset_form").find(":submit");
button.prop("disabled", true);
$(input).attr("disabled", "disabled");
api_call("POST", "/api/user/forgot/" + token, data, function(result) {
if (result["success"] == 1) {
display_message("reset_msg", "success", result["message"], function() {
@ -267,13 +281,13 @@ var reset_form = function() {
});
} else {
display_message("reset_msg", "danger", result["message"], function() {
button.removeAttr("disabled");
$(input).removeAttr("disabled");
});
}
}).fail(function(jqXHR, status, error) {
var result = JSON.parse(jqXHR["responseText"]);
display_message("reset_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
button.removeAttr("disabled");
$(input).removeAttr("disabled");
});
});
}
@ -283,20 +297,19 @@ var reset_form = function() {
var login_form = function() {
var input = "#login_form input";
var data = $("#login_form").serializeObject();
var button = $("#login_form").find(":submit");
button.prop("disabled", true);
$(input).attr("disabled", "disabled");
api_call("POST", "/api/user/login", data, function(result) {
if (result["success"] == 1) {
location.href = "/profile";
} else {
display_message("login_msg", "danger", result["message"], function() {
button.removeAttr("disabled");
$(input).removeAttr("disabled");
});
}
}).fail(function(jqXHR, status, error) {
var result = JSON.parse(jqXHR["responseText"]);
display_message("login_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
button.removeAttr("disabled");
$(input).removeAttr("disabled");
});
});
};
@ -306,20 +319,19 @@ var login_form = function() {
var create_team = function() {
var input = "#create_team input";
var data = $("#create_team").serializeObject();
var button = $("#create_team").find(":submit");
button.prop("disabled", true);
$(input).attr("disabled", "disabled");
api_call("POST", "/api/team/create", data, function(result) {
if (result["success"] == 1) {
location.reload(true);
} else {
display_message("create_team_msg", "danger", result["message"], function() {
button.removeAttr("disabled");
$(input).removeAttr("disabled");
});
}
}).fail(function(jqXHR, status, error) {
var result = JSON.parse(jqXHR["responseText"]);
display_message("create_team_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
button.removeAttr("disabled");
$(input).removeAttr("disabled");
});
});
};
@ -327,18 +339,17 @@ var create_team = function() {
var add_member = function() {
var input = "#add_member input";
var data = $("#add_member").serializeObject();
var button = $("#add_member").find(":submit");
button.prop("disabled", true);
$(input).attr("disabled", "disabled");
api_call("POST", "/api/team/invite", data, function(result) {
if (result["success"] == 1) {
location.reload(true);
} else {
button.removeAtr("disabled");
$(input).removeAttr("disabled");
}
}).fail(function(jqXHR, status, error) {
var result = JSON.parse(jqXHR["responseText"]);
display_message("create_team_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"], function() {
button.removeAttr("disabled");
$(input).removeAttr("disabled");
});
});
};

View file

@ -1,92 +1,22 @@
<script type="text/javascript">
var chart = c3.generate({
data: {
x: 'x',
columns: [
['x', '2013-01-01', '2013-01-02', '2013-01-03', '2013-01-04', '2013-01-05', '2013-01-06'],
['Team Thomas', 30, 250, 380, 500, 620, 740],
]
},
axis: {
x: {
type: 'timeseries',
tick: {
format: '%Y-%m-%d'
}
}
}
});
setTimeout(function() {
chart.load({
columns: [
['Team Charles', 100, 210, 320, 430, 540, 650]
]
});
}, 1000);
setTimeout(function() {
chart.load({
columns: [
['Team Zach', 10, 120, 230, 340, 450, 560]
]
});
}, 2000);
setTimeout(function() {
chart.load({
columns: [
['Team Michael', 0, 80, 190, 300, 410, 520]
]
});
}, 3000);
setTimeout(function() {
chart.load({
columns: [
['Team James', 0, 100, 250, 300, 450, 600]
]
});
}, 4000);
</script>
<div class="fade_in text-center">
<h1 class="heading1">Scoreboard</h1>
<br>
<div id="chart"></div>
<br>
<table class="table">
<thead>
<tr>
<th>#</th>
<th>Team Name</th>
<th>School</th>
<th>Points</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Team Thomas</td>
<td>T. High School</td>
<td>740</td>
</tr>
<tr>
<td>2</td>
<td>Team Charles</td>
<td>C. High School</td>
<td>650</td>
</tr><tr>
<td>3</td>
<td>Team Zach</td>
<td>Z. High School</td>
<td>560</td>
</tr><tr>
<td>4</td>
<td>Team Michael</td>
<td>M. High School</td>
<td>520</td>
</tr><tr>
<td>5</td>
<td>Team James</td>
<td>J. High School</td>
<td>600</td>
</tr>
</tbody>
</table>
<div class="page-header">
<h1>Scoreboard</h1>
</div>
<table class="table table-striped">
<thead>
<tr>
<th>Rank</th>
<th>Team Name</th>
<th>School</th>
<th>Points</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="team in scoreboard">
<td></td>
<td><a ng-href="/team/{{ team['teamname'] }}">{{ team['teamname'] }}</a></td>
<td>{{ team['school'] }}</td>
<td>{{ team['points'] }}</td>
</tr>
</tbody>
</table>