Mercurial > templog
changeset 185:adbf70d1449f
working
author | Matt Johnston <matt@ucc.asn.au> |
---|---|
date | Thu, 06 Feb 2014 22:45:16 +0800 |
parents | cbe14244a372 |
children | be1fde83630d |
files | web/config.py web/log.py web/secure.py web/templog.py web/views/set.tpl |
diffstat | 5 files changed, 151 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/web/config.py Thu Feb 06 20:35:43 2014 +0800 +++ b/web/config.py Thu Feb 06 22:45:16 2014 +0800 @@ -44,6 +44,9 @@ # determine by zooming in an image viewer GRAPH_LEFT_MARGIN = 63 +# 1 hour +CSRF_TIMEOUT = 3600 + try: from localconfig import * except ImportError:
--- a/web/log.py Thu Feb 06 20:35:43 2014 +0800 +++ b/web/log.py Thu Feb 06 22:45:16 2014 +0800 @@ -285,3 +285,7 @@ r.append(n) return json.dumps(r, sort_keys=True, indent=4) + + +def get_csrf_blob(user_ident): + return "aaa"
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/secure.py Thu Feb 06 22:45:16 2014 +0800 @@ -0,0 +1,65 @@ +import os +import time +import fcntl +import hmac +import binascii +import sys + +import config + +__all__ = ["get_csrf_blob", "check_csrf_blob", "setup_csrf"] + +def get_user_hash(): + return "aaa" + +def setup_csrf(): + NONCE_SIZE=16 + global _csrf_fd, _csrf_key + _csrf_fd = open('%s/csrf.dat' % config.DATA_PATH, 'r+') + + try: + fcntl.lockf(_csrf_fd, fcntl.LOCK_EX | fcntl.LOCK_NB) + os.fchmod(_csrf_fd.fileno(), 0600) + _csrf_fd.write("%d-%s" % (os.getpid(), binascii.hexlify(os.urandom(NONCE_SIZE)))) + _csrf_fd.flush() + _csrf_fd.seek(0) + except IOError: + pass + fcntl.lockf(_csrf_fd, fcntl.LOCK_SH) + _csrf_key = _csrf_fd.read() + # keep the lock open until we go away + + +def get_csrf_blob(): + expiry = int(config.CSRF_TIMEOUT + time.time()) + content = '%s-%s' % (get_user_hash(), expiry) + mac = hmac.new(_csrf_key, content).hexdigest() + return "%s-%s" % (content, mac) + +def check_csrf_blob(blob): + toks = blob.split('-') + if len(toks) != 3: + return False + + user, expiry, mac = toks + if user != get_user_hash(): + return False + + try: + exp = int(expiry) + except ValueError: + return False + + if exp < 1000000000: + return False + + if exp > time.time(): + return False + + check_content = "%s-%s" % (user, expiry) + check_mac = hmac.new(_csrf_key, content).hexdigest() + if mac == check_mac: + return True + + return False +
--- a/web/templog.py Thu Feb 06 20:35:43 2014 +0800 +++ b/web/templog.py Thu Feb 06 22:45:16 2014 +0800 @@ -9,12 +9,15 @@ import urllib import sys import os +import traceback +import fcntl import bottle from bottle import route, request, response import config import log +import secure DATE_FORMAT = '%Y%m%d-%H.%M' ZOOM_SCALE = 2.0 @@ -47,7 +50,9 @@ @route('/set') def set(): - return bottle.template('set', inline_data = log.get_params()) + return bottle.template('set', + inline_data = log.get_params(), + csrf_blob = secure.get_csrf_blob()) @route('/set_current.json') def set_fresh(): @@ -100,7 +105,8 @@ @route('/env') def env(): response.set_header('Content-Type', 'text/plain') - return '\n'.join(("%s %s" % k) for k in request.environ.items()) + return '\n'.join(traceback.format_stack()) + #return '\n'.join(("%s %s" % k) for k in request.environ.items()) #return str(request.environ) #yield "\n" #var_lookup = environ['mod_ssl.var_lookup'] @@ -108,8 +114,18 @@ @bottle.get('/<filename:re:.*\.js>') def javascripts(filename): + response.set_header('Cache-Control', "public, max-age=1296000") return bottle.static_file(filename, root='static') +@route('/setparams', method='post') +def update(): + post_json = json.loads(request.forms.data) + + csrf_blob = post_json['csrf_blob'] + + return str(post_json['params']) + +secure.setup_csrf() def main(): #bottle.debug(True)
--- a/web/views/set.tpl Thu Feb 06 20:35:43 2014 +0800 +++ b/web/views/set.tpl Thu Feb 06 22:45:16 2014 +0800 @@ -46,6 +46,11 @@ text-align: center; } +#savebox { + align: center; + width: 100%; +} + .onbutton { background-color: #cdf; } @@ -64,17 +69,6 @@ <title>Set templog</title> </head> -<body> - -<section id="paramlist"> -</section> - -<div id="jsontest"> -</div> - -<input type="button" id="savebutton" value="Save"/> - -</body> <script type="html/num_input"> <div id="{id}"> @@ -97,10 +91,11 @@ <script> -function Setter(params) { +function Setter(params, csrf_blob) { var self = $.observable(this); self.params = params; + self.csrf_blob = csrf_blob $.each(self.params, function(idx, param) { param.id = "param_id_" + idx; @@ -128,17 +123,40 @@ } self.save = function() { - var j = JSON.stringify(self.params); - self.trigger("saved", j) + self.trigger("status", "Saving...") + + var post_json = {}; + post_json.csrf_blob = self.csrf_blob; + post_json.params = + self.params.map(function(v, idx, array) { + return { + name: v.name, + value: v.value + }; + }); + + var post_data = {data: JSON.stringify(post_json)}; + + var req = $.ajax({type: "POST", + url: "setparams", + data: post_data}); + + req.done(function(data, status, hdr) { + self.trigger("status", "Saved") + }); + + req.fail(function(data, status, hdr) { + self.trigger("status", + "Failed: " + status + "\n" + hdr.responseText) + }); } } (function() { 'use strict'; var params = {{!inline_data}}; -window.setter = new Setter(params); - -var root = $("#paramlist"); +var csrf_blob = "{{!csrf_blob}}"; +window.setter = new Setter(params, csrf_blob); var number_template = $("[type='html/num_input']").html(); var button_template = $("[type='html/yesno_button']").html(); @@ -172,23 +190,24 @@ $("#oldvalue", el).toggleClass("modified", !same); }); -setter.on("saved", function(j) { - $("#jsontest").text(j); -}); +setter.on("status", function(status) { + $('#status').text(status) +}) - +var root; -$.route(function(hash) { +window.onload = function() { + // clear list and add new ones + root = $("#paramlist"); -// clear list and add new ones -root.empty() && $.each(setter.params, function (idx, p) { - add(p); + root.empty() && $.each(setter.params, function (idx, p) { + add(p); + }) $("#savebutton").click(function() { setter.save(); }) -}) -}) +} function set_text_state(el, param) { @@ -256,4 +275,19 @@ </script> +<body> + +<section id="paramlist"> +</section> + +<div id="savebox"> +<input type="button" id="savebutton" value="Save"/> + +<div id="status"> +</div> +</div> + + +</body> + </html>