Add OpenID authentication in parallel with casual one
authorArnaud Delcasse <arnaud@delcasse.fr>
Thu, 30 Aug 2012 20:59:43 +0000 (22:59 +0200)
committerArnaud Delcasse <arnaud@delcasse.fr>
Thu, 30 Aug 2012 20:59:43 +0000 (22:59 +0200)
main.py
schema.sql
templates/admin_user_edit.html
templates/admin_user_new.html
templates/login.html

diff --git a/main.py b/main.py
index 50a8452..b460113 100755 (executable)
--- a/main.py
+++ b/main.py
@@ -3,6 +3,7 @@
 
 from flask import Flask, request, session, g, redirect, url_for, abort, \
     render_template, flash
+from flaskext.openid import OpenID
 import sqlite3
 from datetime import date, time, timedelta, datetime
 import time
@@ -21,12 +22,14 @@ DEBUG = True
 TITLE = u"Cavote FFDN"
 EMAIL = '"' + TITLE + '"' + ' <' + u"cavote@ffdn.org" + '>'
 VERSION = "cavote 0.1.1"
-SMTP_SERVER = "10.33.33.30"
+SMTP_SERVER = "127.0.0.1"
 PATTERNS = {u'Oui/Non': [u'Oui', u'Non'], u'Oui/Non/Blanc': [u'Oui', u'Non', u'Blanc'], u'Oui/Non/Peut-être': [u'Oui', u'Non', u'Peut-être']}
 
 app = Flask(__name__)
 app.config.from_object(__name__)
 
+oid = OpenID(app)
+
 def connect_db():
     return sqlite3.connect(app.config['DATABASE'])
 
@@ -98,11 +101,15 @@ def get_userid():
         return user.get('id')
 
 @app.route('/login', methods=['GET', 'POST'])
+@oid.loginhandler
 def login():
     if request.method == 'POST':
         user = valid_login(request.form['username'], request.form['password'])
         if user is None:
-            flash(u'Email ou mot de passe invalide.', 'error')
+            if request.form['openid']:
+                return oid.try_login(request.form['openid'], ask_for=['email', 'fullname', 'nickname'])
+            else:
+                flash(u'Email ou mot de passe invalide.', 'error')
         else:
             connect_user(user)
             flash(u'Vous êtes connecté. Bienvenue, %s !' % user['name'], 'success')
@@ -111,6 +118,16 @@ def login():
             return redirect(url_for('home'))
     return render_template('login.html')
 
+@oid.after_login
+def create_or_login(resp):
+    openid_url = resp.identity_url
+    user = query_db('select * from users where openid = ?', [openid_url], one=True)
+    if user is not None:
+        flash(u'Successfully signed in')
+        connect_user(user)
+        return redirect(oid.get_next_url())
+    return redirect(url_for('home'))
+
 @app.route('/logout')
 def logout():
     disconnect_user()
@@ -252,8 +269,9 @@ def admin_user_add():
                         if 'admin' in request.form.keys():
                             admin = 1
                         key = 'v%s' % keygen()
-                        g.db.execute('insert into users (email, name, organization, password, is_admin, key) values (?, ?, ?, ?, ?, ?)',
+                        g.db.execute('insert into users (email, openid, name, organization, password, is_admin, key) values (?, ?, ?, ?, ?, ?, ?)',
                                 [request.form['email'],
+                                    request.form['openid'],
                                     request.form['username'],
                                     request.form['organization'],
                                     '', admin, key])
index 88a542b..95ee9e3 100644 (file)
@@ -12,6 +12,7 @@ create table users (
     id INTEGER PRIMARY KEY AUTOINCREMENT,
     email TEXT UNIQUE NOT NULL,
     password TEXT NOT NULL,
+    openid TEXT NOT NULL,
     name TEXT UNIQUE NOT NULL, 
     organization TEXT,
     is_admin BOOLEAN DEFAULT 0 NOT NULL,
@@ -83,8 +84,8 @@ create table user_choice (
 
 -- Test data
 
-INSERT INTO users (id, email, password, name, organization, is_admin, key)
-VALUES (1, "admin@admin.fr", "", "Toto (admin) Tata", "World corp", 1, "victory");
+INSERT INTO users (id, email, password, openid, name, organization, is_admin, key)
+VALUES (1, "admin@admin.fr", "", "", "Toto (admin) Tata", "World corp", 1, "victory");
 -- to login, go to /login/1/victory
 INSERT INTO groups (id, name, system) VALUES (1, "Tous", 1);
 INSERT INTO groups (name) VALUES ("CA");
index 5c13396..6781def 100644 (file)
             <input type="text" name="email" id="email" value="{{ user.email }}"/>
         </div>
       </div>
+      <div class="control-group">
+        <label class="control-label" for="openid">OpenID</label>
+        <div class="controls">
+          <input type="text" name="openid" id="openid" value="{{ user.openid }}" />
+        </div>
+      </div>
       <div class="control-group">
           <label class="control-label" for="name">Nom</label>
           <div class="controls">
index 2b1d50d..8db2711 100644 (file)
       <span class="help-inline"><font color="red">*</font></span>
     </div>
   </div>
+  <div class="control-group">
+    <label class="control-label" for="openid">OpenID</label>
+    <div class="controls">
+      <input type="text" name="openid" id="openid" value="{{ request.form.openid }}" />
+    </div>
+  </div>
   <div class="control-group">
     <label class="control-label" for="organization">Association</label>
     <div class="controls">
-      <input type="text" data-provide="typeahead" data-source='["FDN","Ilico","Aquilenet"]' size=30 name="organization" id="organization" value="{{ request.form.organization }}" />
+      <input type="text" data-provide="typeahead" data-source='["NDN","FDN","Ilico","Aquilenet"]' size=30 name="organization" id="organization" value="{{ request.form.organization }}" />
     </div>
   </div>
   <div class="control-group">
index b00dc72..70985cf 100644 (file)
@@ -2,18 +2,22 @@
 {% block body %}
 <div class="row">
   <div class="span3 well offset1">
+    <p><a href="{{ url_for("password_lost") }}">Mot de passe perdu ?</a></p>
     <form action="{{ url_for('login', continue=request.args.continue) }}" method="post">
     <fieldset><legend>Connexion</legend>
       <label for="username">E-mail</label>
       <input type="text" name="username" id="username" value="{{ request.form.username }}"/>
       <label for="password">Mot de passe</label>
       <input type="password" name="password" id="password" />
+    </fieldset>
+    <fieldset><legend>OpenID</legend>
+      <label for="openid">OpenID</label>
+      <input type="text" name="openid" id="openid" value="{{ request.form.openid }}"/>
       <div class="form-actions">
         <input type="submit" class="btn btn-primary" value="Connexion" />
       </div>
     </fieldset>
     </form>
-    <p><a href="{{ url_for("password_lost") }}">Mot de passe perdu ?</a></p>
   </div>
 </div>
 {% endblock %}