diff options
author | 2010-07-17 23:30:46 +0300 | |
---|---|---|
committer | 2010-07-17 23:30:46 +0300 | |
commit | ca08281c1dedd5dfe026048a32641a29d1f013cb (patch) | |
tree | 5920e3c83c0a4f78cdbebd1156807bf488b96825 | |
parent | Improve wording for developer check QA issue info (diff) | |
download | gsoc2010-grumpy-ca08281c1dedd5dfe026048a32641a29d1f013cb.tar.gz gsoc2010-grumpy-ca08281c1dedd5dfe026048a32641a29d1f013cb.tar.bz2 gsoc2010-grumpy-ca08281c1dedd5dfe026048a32641a29d1f013cb.zip |
Added OpenID login support
-rw-r--r-- | grumpy/models.py | 14 | ||||
-rw-r--r-- | grumpy/templates/create_profile.html | 20 | ||||
-rw-r--r-- | grumpy/templates/layout.html | 9 | ||||
-rw-r--r-- | grumpy/templates/login.html | 13 | ||||
-rw-r--r-- | grumpy/webapp.py | 63 |
5 files changed, 116 insertions, 3 deletions
diff --git a/grumpy/models.py b/grumpy/models.py index 807557f..55019f0 100644 --- a/grumpy/models.py +++ b/grumpy/models.py @@ -187,3 +187,17 @@ class PkgIssue(db.Model): def __repr__(self): return '<%s> - %s : %s' % \ (self.__class__.__name__, self.plugin, self.type) + +class User(db.Model): + """User model""" + __tablename__ = 'users' + + id = db.Column('id', db.Integer, primary_key=True) + regtoken = db.Column('token', db.String) + openid = db.Column('openid', db.String) + email = db.Column('user', db.String, unique=True) + + def __init__(self, email, openid): + self.email = email + self.openid = openid + # TODO, generate token diff --git a/grumpy/templates/create_profile.html b/grumpy/templates/create_profile.html new file mode 100644 index 0000000..37f562d --- /dev/null +++ b/grumpy/templates/create_profile.html @@ -0,0 +1,20 @@ +{% extends "layout.html" %} +{% block title %}Create profile{% endblock %} +{% block body %} + <h2>Create profile</h2> + <p> + Hey! This is a first time you signed in on this website. In order to proceed + we need some extra information from you: + <form action="" method=post> + <dl> + <dt>Gentoo developer email: + <dd><input type=text name=email size=30 value="{{ request.values.email }}"> + </dl> + <p> + <input type=submit value="Create profile"> + <input type=hidden name=next value="{{ next }}"> + </form> + <p> + If you don't want to proceed, you can + <a href="{{ url_for('logout') }}">sign out</a> again. +{% endblock %} diff --git a/grumpy/templates/layout.html b/grumpy/templates/layout.html index abd3001..e3d8ff2 100644 --- a/grumpy/templates/layout.html +++ b/grumpy/templates/layout.html @@ -2,6 +2,15 @@ <head> <title>{% block title %}Welcome{% endblock %} | Grumpy</title> </head> +<div class=menu> + <ul> + {% if g.user %} + <li><a href="{{ url_for('logout') }}">Log out</a></li> + {% else %} + <li><a href="{{ url_for('login') }}">Login</a></li> + {% endif %} + </ul> +</div> <div class=page> {% with flashes = get_flashed_messages() %} {% if flashes %} diff --git a/grumpy/templates/login.html b/grumpy/templates/login.html new file mode 100644 index 0000000..cca3842 --- /dev/null +++ b/grumpy/templates/login.html @@ -0,0 +1,13 @@ +{% extends "layout.html" %} +{% block title %}Sign in{% endblock %} +{% block body %} + <h2>Sign in</h2> + <form action="" method=post> + {% if error %}<p class=error><strong>Error:</strong> {{ error }}</p>{% endif %} + <p> + OpenID: + <input type=text name=openid size=30> + <input type=submit value="Sign in"> + <input type=hidden name=next value="{{ next }}"> + </form> +{% endblock %} diff --git a/grumpy/webapp.py b/grumpy/webapp.py index b33156b..b426cc8 100644 --- a/grumpy/webapp.py +++ b/grumpy/webapp.py @@ -9,10 +9,21 @@ :license: BSD, see LICENSE for details. """ from . import app -from .models import Category, Package +from .models import db, Category, Package, User from .utils import requires_auth_basic -from flask import flash, jsonify, redirect, render_template, url_for +from flask import (flash, g, jsonify, redirect, render_template, request, \ + session, url_for) +from flaskext.openid import OpenID + +# OpenID support +oid = OpenID(app) + +@app.before_request +def before_request(): + g.user = None + if 'openid' in session: + g.user = User.query.filter_by(openid=session['openid']).first() @app.route('/') @app.route('/browse/') @@ -20,7 +31,6 @@ def index(): cats = Category.query.order_by(Category.cat.asc()).all() return render_template('index.html', cats=cats) - @app.route('/browse/<cat>/') def browse_cat(cat): if cat: @@ -42,6 +52,53 @@ def browse_pkg(cat, pkg): flash('Package "%s/%s" does not exist' % (cat, pkg)) return redirect(url_for('browse_cat', cat=cat)) +@app.route('/login', methods=['GET', 'POST']) +@oid.loginhandler +def login(): + if g.user is not None: + return redirect(oid.get_next_url()) + if request.method == 'POST': + openid = request.form.get('openid') + if openid: + return oid.try_login(openid, ask_for=['email']) + return render_template('login.html', next=oid.get_next_url(), + error=oid.fetch_error()) + +@app.route('/logout') +def logout(): + session.pop('openid', None) + flash(u'You have been signed out') + return redirect(oid.get_next_url()) + +@oid.after_login +def create_or_login(resp): + session['openid'] = resp.identity_url + user = User.query.filter_by(openid=resp.identity_url).first() + if user is not None: + flash(u'Successfully logged in') + g.user = user + return redirect(oid.get_next_url()) + return redirect(url_for('create_profile', next=oid.get_next_url(), + email=resp.email)) + +@app.route('/create-profile', methods=['GET', 'POST']) +def create_profile(): + if g.user is not None or 'openid' not in session: + return redirect(url_for('index')) + if request.method == 'POST': + email = request.form['email'].strip() + if not email: + flash(u'Error: you need to provide @gentoo.org email') + # XXX: remove plaes.org, that's for testing purposes ;) + elif not email.endswith(('@gentoo.org', '@plaes.org')): + flash(u'You need to be a valid Gentoo developer to sign up') + else: + flash(u'Profile successfully created') + db.session.add(User(email, session['openid'])) + # TODO: send confirmation token with email + db.session.commit() + return render_template('create_profile.html', next=oid.get_next_url()) + @app.route('/_api/1.0/tinderbox/') @requires_auth_basic def tinderbox_api(): |