diff options
-rw-r--r-- | grumpy/templates/_userinfo.html | 1 | ||||
-rw-r--r-- | grumpy/templates/_util.html | 3 | ||||
-rw-r--r-- | grumpy/templates/account.html | 57 | ||||
-rw-r--r-- | grumpy/utils.py | 11 | ||||
-rw-r--r-- | grumpy/webapp.py | 20 |
5 files changed, 88 insertions, 4 deletions
diff --git a/grumpy/templates/_userinfo.html b/grumpy/templates/_userinfo.html index 704ee79..7f5ac0e 100644 --- a/grumpy/templates/_userinfo.html +++ b/grumpy/templates/_userinfo.html @@ -2,6 +2,7 @@ {% if g.user -%} <ul> <li><a href="{{ url_for('dashboard') }}">{{ g.user.email.split('@')[0] | e }}</a> +<li><a href="{{ url_for('account') }}">Account</a> <li><a href="{{ url_for('logout') }}">Log out</a> </ul> {% if g.user.regtoken -%} diff --git a/grumpy/templates/_util.html b/grumpy/templates/_util.html index 5e6ee0b..6c2c837 100644 --- a/grumpy/templates/_util.html +++ b/grumpy/templates/_util.html @@ -1,3 +1,6 @@ +{% macro load_css(filename) -%} +<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/' + filename + '.css')}}"> +{% endmacro -%} {% macro load_js(filename) -%} <script type="text/javascript" language="javascript" src="{{ url_for('static', filename='js/' + filename +'.js' )}}"></script> {% endmacro -%} diff --git a/grumpy/templates/account.html b/grumpy/templates/account.html new file mode 100644 index 0000000..f5b8224 --- /dev/null +++ b/grumpy/templates/account.html @@ -0,0 +1,57 @@ +{% extends "layout.html" %} +{% block title %}Your Account{% endblock %} +{% block script %} +{{ importer.load_js('jquery.min') }} +{{ importer.load_js('jquery-ui.min') }} +<script type="text/javascript"> +$(document).ready(function() { + function post_api_key_query(elem) { + $.ajax({ + url: "{{ url_for('api_generate_api_key') }}", + dataType: 'json', + type: 'POST', + error: function(req, xxx, error) { + alert('Unknown error occurred.'); + }, + success: function(data) { + $('#api_key').html('<strong>' + data.apikey + '</strong>'); + } + }); + }; + + $('#new_key_button').click(function() { + elem = $('#api_key'); + if (elem.text() != 'unset') { + $('#warn_dialog').dialog({ + title: "API key already exists!", + modal: true, + buttons: { + "Cancel": function() { $(this).dialog("close"); }, + "Generate New": function() { post_api_key_query(elem); $(this).dialog("close"); } + } + }); + } else + post_api_key_query(elem); + }); +}); +</script> +{{ importer.load_css('ui-lightness/jquery-ui') }} +{% endblock %} +{% block body %} +<h2>Account overview</h2> +<dl> + <dt>Developer email</dt> + <dd>{{ g.user.email }}</dd> + <dt>API token <button id="new_key_button">Generate</button></dt> + <dd>Your API token is <span id="api_key"> + {%- if g.user.apitoken -%} + <tt>{{ g.user.apitoken }}</tt><br> + Please keep it safe. + {% else -%} + unset + {%- endif -%} + </span> + </dd> +</dl> +<span id="warn_dialog" style="display: none;">FIXME: Need a nice description here ;)</span> +{% endblock %} diff --git a/grumpy/utils.py b/grumpy/utils.py index 4891c3d..36bdd0a 100644 --- a/grumpy/utils.py +++ b/grumpy/utils.py @@ -7,7 +7,7 @@ :copyright: (c) 2010 Priit Laes """ -from flask import request, Response +from flask import flash, g, redirect, request, url_for, Response from functools import wraps from smtplib import SMTP, SMTPException @@ -31,6 +31,15 @@ def check_auth(username, password): return username == app.config['TINDERBOX_USER'] and \ password == app.config['TINDERBOX_PASS'] +def requires_auth(f): + @wraps(f) + def decorated(*args, **kwargs): + if not g.user: + flash(u'This view requires valid user') + return redirect(url_for('index')) + return f(*args, **kwargs) + return decorated + def requires_auth_basic(f): @wraps(f) def decorated(*args, **kwargs): diff --git a/grumpy/webapp.py b/grumpy/webapp.py index dfb7972..b430301 100644 --- a/grumpy/webapp.py +++ b/grumpy/webapp.py @@ -8,14 +8,16 @@ :copyright: (c) by 2010 Priit Laes. :license: BSD, see LICENSE for details. """ -from . import app -from .models import db, Category, Developer, Package, User -from .utils import requires_auth_basic, send_email +import hashlib, random from flask import (flash, g, jsonify, redirect, render_template, request, \ session, url_for) from flaskext.openid import OpenID +from . import app +from .models import db, Category, Developer, Package, User +from .utils import requires_auth, requires_auth_basic, send_email + # OpenID support oid = OpenID(app) @@ -42,6 +44,10 @@ def index(): cats = Category.query.order_by(Category.name.asc()).all() return render_template('index.html', cats=cats) +@app.route('/account/') +def account(): + return render_template('account.html') + @app.route('/browse/<cat>/') def browse_cat(cat): if cat: @@ -132,6 +138,14 @@ def confirm_account(email): db.session.commit() return render_template('confirm_account.html', success=True) +@app.route('/_api/1.0/account/generate_api_key', methods=['POST']) +@requires_auth +def api_generate_api_key(): + salt = random.randrange(1000, 10000) + g.user.apitoken = hashlib.md5("%s$%d" % (g.user.email, salt)).hexdigest() + db.session.commit() + return jsonify(dict(apikey=g.user.apitoken)) + @app.route('/_api/1.0/tinderbox/') @requires_auth_basic def tinderbox_api(): |