aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPriit Laes <plaes@plaes.org>2010-08-06 22:35:45 +0300
committerPriit Laes <plaes@plaes.org>2010-08-06 22:36:41 +0300
commitb3be2d813937358762713503b07fd52f3b61f24e (patch)
treeb9c74d9bbf37d537718a606f25ed443607695be8
parentAdded jquery-ui (diff)
downloadgsoc2010-grumpy-b3be2d813937358762713503b07fd52f3b61f24e.tar.gz
gsoc2010-grumpy-b3be2d813937358762713503b07fd52f3b61f24e.tar.bz2
gsoc2010-grumpy-b3be2d813937358762713503b07fd52f3b61f24e.zip
Added API key generation feature
-rw-r--r--grumpy/templates/_userinfo.html1
-rw-r--r--grumpy/templates/_util.html3
-rw-r--r--grumpy/templates/account.html57
-rw-r--r--grumpy/utils.py11
-rw-r--r--grumpy/webapp.py20
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():