added CSRF check
This commit is contained in:
parent
f4a3f4513c
commit
b7f4e75350
7 changed files with 100 additions and 71 deletions
|
@ -1,31 +0,0 @@
|
|||
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<html><head><title>Python: package api</title>
|
||||
<meta charset="utf-8">
|
||||
</head><body bgcolor="#f0f0f8">
|
||||
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="heading">
|
||||
<tr bgcolor="#7799ee">
|
||||
<td valign=bottom> <br>
|
||||
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong>api</strong></big></big></font></td
|
||||
><td align=right valign=bottom
|
||||
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/vagrant/server/api/__init__.py">/home/vagrant/server/api/__init__.py</a></font></td></tr></table>
|
||||
<p></p>
|
||||
<p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#aa55cc">
|
||||
<td colspan=3 valign=bottom> <br>
|
||||
<font color="#ffffff" face="helvetica, arial"><big><strong>Package Contents</strong></big></font></td></tr>
|
||||
|
||||
<tr><td bgcolor="#aa55cc"><tt> </tt></td><td> </td>
|
||||
<td width="100%"><table width="100%" summary="list"><tr><td width="25%" valign=top><a href="api.admin.html">admin</a><br>
|
||||
<a href="api.api.html">api</a><br>
|
||||
<a href="api.decorators.html">decorators</a><br>
|
||||
</td><td width="25%" valign=top><a href="api.logger.html">logger</a><br>
|
||||
<a href="api.models.html">models</a><br>
|
||||
<a href="api.problem.html">problem</a><br>
|
||||
</td><td width="25%" valign=top><a href="api.schemas.html">schemas</a><br>
|
||||
<a href="api.user.html">user</a><br>
|
||||
<a href="api.utils.html">utils</a><br>
|
||||
</td><td width="25%" valign=top></td></tr></table></td></tr></table>
|
||||
</body></html>
|
|
@ -1,42 +1,59 @@
|
|||
from functools import wraps
|
||||
from flask import abort, request, session, make_response
|
||||
|
||||
import json
|
||||
import traceback
|
||||
|
||||
from functools import wraps
|
||||
from flask import session
|
||||
import utils
|
||||
|
||||
class WebException(Exception): pass
|
||||
response_header = { "Content-Type": "application/json; charset=utf-8" }
|
||||
|
||||
def api_wrapper(f):
|
||||
@wraps(f)
|
||||
def wrapper(*args, **kwds):
|
||||
web_result = {}
|
||||
response = 200
|
||||
try:
|
||||
web_result = f(*args, **kwds)
|
||||
except WebException as error:
|
||||
response = 200
|
||||
web_result = { "success": 0, "message": str(error) }
|
||||
except Exception as error:
|
||||
response = 200
|
||||
traceback.print_exc()
|
||||
web_result = { "success": 0, "message": "Something went wrong! Please notify us about this immediately.", "error": [ str(error), traceback.format_exc() ] }
|
||||
return json.dumps(web_result), response, { "Content-Type": "application/json; charset=utf-8" }
|
||||
return wrapper
|
||||
@wraps(f)
|
||||
def wrapper(*args, **kwds):
|
||||
if request.method == "POST":
|
||||
token = session.pop("csrf_token")
|
||||
if not token or token != request.form.get("csrf_token"):
|
||||
return make_response(json.dumps({ "success": 0, "message": "Token has been tampered with." }), 403, response_header)
|
||||
|
||||
web_result = {}
|
||||
response = 200
|
||||
try:
|
||||
web_result = f(*args, **kwds)
|
||||
except WebException as error:
|
||||
response = 200
|
||||
web_result = { "success": 0, "message": str(error) }
|
||||
except Exception as error:
|
||||
response = 200
|
||||
traceback.print_exc()
|
||||
web_result = { "success": 0, "message": "Something went wrong! Please notify us about this immediately.", "error": [ str(error), traceback.format_exc() ] }
|
||||
result = (json.dumps(web_result), response, response_header)
|
||||
|
||||
# Setting CSRF token
|
||||
if "token" not in session:
|
||||
token = utils.generate_string()
|
||||
response = make_response(result)
|
||||
response.set_cookie("csrf_token", token)
|
||||
session["csrf_token"] = token
|
||||
|
||||
return response
|
||||
return wrapper
|
||||
|
||||
import user # Must go below api_wrapper to prevent import loops
|
||||
|
||||
def login_required(f):
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if not user.is_logged_in():
|
||||
return { "success": 0, "message": "Not logged in." }
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if not user.is_logged_in():
|
||||
return { "success": 0, "message": "Not logged in." }
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
||||
def admins_only(f):
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if not user.is_admin():
|
||||
return { "success": 0, "message": "Not authorized." }
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
@wraps(f)
|
||||
def decorated_function(*args, **kwargs):
|
||||
if not user.is_admin():
|
||||
return { "success": 0, "message": "Not authorized." }
|
||||
return f(*args, **kwargs)
|
||||
return decorated_function
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
from flask import Blueprint, session, request, redirect, url_for
|
||||
from flask import Blueprint, make_response, session, request, redirect, url_for
|
||||
from flask import current_app as app
|
||||
from voluptuous import Schema, Length, Required
|
||||
|
||||
|
@ -44,7 +44,7 @@ def user_register():
|
|||
|
||||
return { "success": 1, "message": "Success!" }
|
||||
|
||||
@blueprint.route("/logout", methods=["POST"])
|
||||
@blueprint.route("/logout", methods=["GET"])
|
||||
@api_wrapper
|
||||
def user_logout():
|
||||
sid = session["sid"]
|
||||
|
@ -69,7 +69,7 @@ def user_login():
|
|||
|
||||
return { "success": 1, "message": "Success!" }
|
||||
|
||||
@blueprint.route("/status", methods=["POST"])
|
||||
@blueprint.route("/status", methods=["GET"])
|
||||
@api_wrapper
|
||||
def user_status():
|
||||
logged_in = is_logged_in()
|
||||
|
@ -79,9 +79,10 @@ def user_status():
|
|||
"admin": is_admin(),
|
||||
"username": session["username"] if logged_in else "",
|
||||
}
|
||||
|
||||
return result
|
||||
|
||||
@blueprint.route("/info", methods=["POST"])
|
||||
@blueprint.route("/info", methods=["GET"])
|
||||
@api_wrapper
|
||||
def user_info():
|
||||
logged_in = is_logged_in()
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.9.3/js/bootstrap-select.min.js" integrity="sha384-1qZEXZBmj54fSiiWT8bZQGEpCumJWDrAoEqMdg6N5bTTLCkU5RXoNeUsKWekRYob" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-timeago/1.4.3/jquery.timeago.min.js" integrity="sha384-Bap3DetwPgo4GEFvaIDVSIrz5G0mUAUsfCUcEsi+JrrNu7dyj3gBmuAG4hDIGg/4" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/smooth-scroll/7.1.1/js/smooth-scroll.min.js" integrity="sha384-bznoxhRX5dRiE60JhQSru8t7g2RPG9lwqvyut8sjFFWmsAlp+R38e7DiATv1YyIu" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-cookie/1.4.1/jquery.cookie.min.js" integrity="sha384-tSi+YsgNwyohDGfW/VhY51IK3RKAPYDcj1sNXJ16oRAyDP++K0NCzSCUW78EMFmf" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ckeditor/4.5.4/ckeditor.js" integrity="sha384-N2/iPbB6nrU8RupS9WXTBZ1d2TRMI9qixvmdYNC+cbc12q9+YRW0Kw99QZfmYQzq" crossorigin="anonymous"></script>
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.2.2/ace.js" integrity="sha384-niN+bRlaXMBoq/f5L4zKOEYGxuD0YRGBocto9LP2fB1UiMfxrymATRN4GqjVUt6J" crossorigin="anonymous"></script>
|
||||
<script src="/js/easyctf.js"></script>
|
||||
|
|
|
@ -57,7 +57,7 @@ app.config(function($routeProvider, $locationProvider) {
|
|||
|
||||
app.controller("mainController", ["$scope", "$http", function($scope, $http) {
|
||||
$scope.config = { navbar: { } };
|
||||
$.post("/api/user/status", function(result) {
|
||||
$.get("/api/user/status", function(result) {
|
||||
if (result["success"] == 1) {
|
||||
$scope.config.navbar.logged_in = result["logged_in"];
|
||||
$scope.config.navbar.username = result["username"];
|
||||
|
@ -74,7 +74,7 @@ app.controller("mainController", ["$scope", "$http", function($scope, $http) {
|
|||
}]);
|
||||
|
||||
app.controller("logoutController", function() {
|
||||
$.post("/api/user/logout", function(result) {
|
||||
$.get("/api/user/logout", function(result) {
|
||||
location.href = "/";
|
||||
});
|
||||
});
|
||||
|
@ -83,7 +83,7 @@ app.controller("profileController", ["$controller", "$scope", "$http", "$routePa
|
|||
var data = { };
|
||||
if ("username" in $routeParams) data["username"] = $routeParams["username"];
|
||||
$controller("mainController", { $scope: $scope });
|
||||
$.post("/api/user/info", data, function(result) {
|
||||
$.get("/api/user/info", data, function(result) {
|
||||
if (result["success"] == 1) {
|
||||
$scope.user = result["user"];
|
||||
}
|
||||
|
@ -108,7 +108,7 @@ app.controller("adminController", ["$controller", "$scope", "$http", function($c
|
|||
|
||||
app.controller("adminProblemsController", ["$controller", "$scope", "$http", function($controller, $scope, $http) {
|
||||
$controller("adminController", { $scope: $scope });
|
||||
$.post("/api/admin/problems/list", function(result) {
|
||||
$.get("/api/admin/problems/list", function(result) {
|
||||
if (result["success"] == 1) {
|
||||
$scope.problems = result["problems"];
|
||||
}
|
||||
|
@ -147,12 +147,16 @@ $.fn.serializeObject = function() {
|
|||
var register_form = function() {
|
||||
var input = "#register_form input";
|
||||
var data = $("#register_form").serializeObject();
|
||||
data["csrf_token"] = $.cookie("csrf_token");
|
||||
$.post("/api/user/register", data, function(result) {
|
||||
if (result["success"] == 1) {
|
||||
location.href = "/profile";
|
||||
} else {
|
||||
display_message("register_msg", "danger", result["message"])
|
||||
display_message("register_msg", "danger", result["message"]);
|
||||
}
|
||||
}).fail(function(jqXHR, status, error) {
|
||||
var result = JSON.parse(jqXHR["responseText"]);
|
||||
display_message("register_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"]);
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -161,11 +165,15 @@ var register_form = function() {
|
|||
var login_form = function() {
|
||||
var input = "#login_form input";
|
||||
var data = $("#login_form").serializeObject();
|
||||
data["csrf_token"] = $.cookie("csrf_token");
|
||||
$.post("/api/user/login", data, function(result) {
|
||||
if (result["success"] == 1) {
|
||||
location.href = "/profile";
|
||||
} else {
|
||||
display_message("login_msg", "danger", result["message"])
|
||||
display_message("login_msg", "danger", result["message"]);
|
||||
}
|
||||
}).fail(function(jqXHR, status, error) {
|
||||
var result = JSON.parse(jqXHR["responseText"]);
|
||||
display_message("login_msg", "danger", "Error " + jqXHR["status"] + ": " + result["message"]);
|
||||
});
|
||||
};
|
|
@ -31,6 +31,7 @@
|
|||
<div class="row">
|
||||
<div class="col-sm-12 form-group">
|
||||
<center>
|
||||
<input type="hidden" id="_csrf" value="{{ csrf_token }}" />
|
||||
<input type="submit" class="btn btn-success btn-lg" value="Login" />
|
||||
</center>
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<img src="//www.gravatar.com/avatar/?size=512" id="avatar" style="max-width:100%;" />
|
||||
<small style="display:block;text-align:right;" ng-show="user['me']==true"><a href="http://en.gravatar.com/emails/" target="_blank">Edit Picture</a></small>
|
||||
<h2 style="margin:0px;font-weight:bold;font-size:2em;">{{ user.name }}</h2>
|
||||
<small style="display:block;font-size:1.5em;">@{{ user.username }}</small>
|
||||
<small style="display:block;font-size:1.5em;color:#999;">@{{ user.username }}</small>
|
||||
<hr>
|
||||
<div>
|
||||
<i class="fa fa-fw fa-user"></i>
|
||||
|
@ -34,6 +34,38 @@
|
|||
</ul>
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="profile">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Team Information</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Hi.
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Statistics</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Hi.
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Top Solves</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Hi.
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h4 class="panel-title">Achievements</h4>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Hi.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="activity">
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue