Browse Source

Added users table in database.

Users are connected from database.
Users can be connected without password, using key field. Usefull in
case of password loss.
Added some new templates.
Guillaume Subiron 13 years ago
parent
commit
16118385bb
6 changed files with 103 additions and 32 deletions
  1. 52 19
      main.py
  2. 18 3
      schema.sql
  3. 6 5
      templates/layout.html
  4. 5 5
      templates/login.html
  5. 17 0
      templates/password_lost.html
  6. 5 0
      templates/user_settings.html

+ 52 - 19
main.py

@@ -12,8 +12,6 @@ locale.setlocale(locale.LC_ALL, '')
 DATABASE = '/tmp/cavote.db'
 SECRET_KEY = '{J@uRKO,xO-PK7B,jF?>iHbxLasF9s#zjOoy=+:'
 DEBUG = True
-USERNAME = 'admin'
-PASSWORD = 'admin'
 
 app = Flask(__name__)
 app.config.from_object(__name__)
@@ -49,36 +47,71 @@ def init_db():
 # Login / Logout
 
 def valid_login(username, password):
-    return username == app.config['USERNAME'] and password == app.config['PASSWORD']
+    return query_db('select * from users where email = ? and password = ?', [username, password], one=True)
+
+def connect_user(user):
+    session['userid'] = user['id']
+    session['username'] = user['name']
+    session['email'] = user['email']
+    session['organization'] = user['organization']
+    if user['is_admin'] == 1:
+        session['is_admin'] = True
+
+def disconnect_user():
+    session.pop('username', None)
+    session.pop('is_admin', None)
 
 @app.route('/login', methods=['GET', 'POST'])
 def login():
-    error = None
     if request.method == 'POST':
-        if valid_login(request.form['username'], request.form['password']):
-            session['username'] = request.form['username']
-            if session['username'] == 'admin':
-                session['is_admin'] = True
-            flash('You were logged in')
-            return redirect(url_for('home'))
+        user = valid_login(request.form['username'], request.form['password'])
+        if user is None:
+            flash('Invalid username/password', 'error')
         else:
-            error = "Invalid username/password"
-    return render_template('login.html', error=error)
+            connect_user(user)
+            flash('You were logged in', 'success')
+            return redirect(url_for('home'))
+    return render_template('login.html')
 
 @app.route('/logout')
 def logout():
-    session.pop('username', None)
-    session.pop('is_admin', None)
-    flash('You were logged out')
+    disconnect_user()
+    flash('You were logged out', 'info')
     return redirect(url_for('home'))
 
+#-----------------
+# Change password
+
+@app.route('/password/lost', methods=['GET', 'POST'])
+def password_lost():
+    info = None
+    if request.method == 'POST':
+        user = query_db('select * from users where email = ?', [request.form['email']], one=True)
+        if user is None:
+            flash('Cet utilisateur n\'existe pas !', 'error')
+        else:
+            # :TODO:maethor:120528: Générer la clé, la mettre dans la base de données et envoyer le mail
+            flash(u"Un mail a été envoyé à " + user['email'], 'info')
+    return render_template('password_lost.html')
+
+@app.route('/login/<username>/<key>')
+def login_key(username, key):
+    user = query_db('select * from users where email = ? and key = ?', [username, key], one=True)
+    if user is None:
+        abort(404)
+    else:
+        connect_user(user)
+        # :TODO:maethor:120528: Remplacer la clé pour qu'elle ne puisse plus être utilisée
+        return redirect(url_for('home'))
+
 #---------------
 # User settings
+
 @app.route('/user/settings/<username>')
-def show_settings(username):
-    if username != session['username']:
+def show_user(username):
+    if username != session.get('username'):
         abort(401)
-
+    return render_template('user_settings.html')
 
 #------------
 # User admin
@@ -127,7 +160,7 @@ def add_vote():
     g.db.execute('insert into votes (title, description, date_begin, date_end, is_transparent, is_public, is_multiplechoice) values (?, ?, ?, ?, ?, ?, ?)',
             [request.form['title'], request.form['description'], date_begin, date_end, transparent, public, multiplechoice])
     g.db.commit()
-    flash('New entry was successfully posted')
+    flash('New entry was successfully posted', 'info')
     return redirect(url_for('home'))
 
 #------

+ 18 - 3
schema.sql

@@ -1,4 +1,16 @@
 drop table if exists votes;
+drop table if exists users;
+
+create table users (
+    id INTEGER primary key autoincrement,
+    email TEXT unique not null,
+    password TEXT not null,
+    name TEXT,
+    organization TEXT,
+    is_admin INTEGER default 0 not null,
+    key TEXT
+);
+
 create table votes (
     id INTEGER primary key autoincrement,
     title TEXT not null,
@@ -10,11 +22,14 @@ create table votes (
     is_public INTEGER default 1 not null,
     is_multiplechoice INTEGER default 1 not null,
     is_weighted INTEGER default 0 not null,
-    is_closed INTEGER default 0 not null
-    --id_author INTEGER not null,
+    is_closed INTEGER default 0 not null,
+    id_author INTEGER, -- :COMMENT:maethor:120528: not null ?
     --id_role INTEGER,
-    --FOREIGN KEY(id_author) REFERENCES user(id),
+    FOREIGN KEY(id_author) REFERENCES users(id)
     --FOREIGN KEY(id_role) REFERENCES role(id)
 );
 
+-- Test data
+
+insert into users (email, password, name, organization, is_admin, key) values ("admin@admin.fr", "admin", "Toto (admin) Tata", "World corp", 1, "test");
 

+ 6 - 5
templates/layout.html

@@ -31,11 +31,11 @@
     </div>
     <div class="btn-group pull-right">
       {% if 'username' in session %}
-      <a href="#" class="btn"><i class="icon-user"></i> {{ session.username }}</a>
+      <a href="{{ url_for('show_user', username=session.username) }}" class="btn"><i class="icon-user"></i> {{ session.username }}</a>
       <a href="#" class="btn dropdown-toggle" data-toggle="dropdown"><b class="caret"></b></a>
       <ul class="dropdown-menu pull-right">
         <li><a href=""><i class="icon-comment"></i> Votes en attente</a></li>
-        <li><a href=""><i class="icon-cog"></i> Paramètres</a></li>
+        <li><a href="{{ url_for('show_user', username=session.username) }}"><i class="icon-cog"></i> Paramètres</a></li>
         <li class="divider"></li>
         <li><a href="{{ url_for('logout') }}"><i class="icon-off"></i> Déconnexion</a></li>
       </ul>
@@ -47,16 +47,17 @@
 </header>
 
 <h1 class="page-header">Outil de vote du CA FFDN</h1>
-{% with messages = get_flashed_messages() %}
+{% with messages = get_flashed_messages(with_categories="true") %}
   {% if messages %}
-    {% for message in messages %}
-    <div class="alert alert-info fade in">
+    {% for category, message in messages %}
+    <div class="alert alert-{{ category }} fade in">
       <button class="close" data-dismiss="alert">×</button>
       {{ message }}
     </div>
     {% endfor %}
   {% endif %}
 {% endwith %}
+
 {% block body %}{% endblock %}
 
 </div> <!-- container -->   

+ 5 - 5
templates/login.html

@@ -2,18 +2,18 @@
 {% block body %}
 <div class="row">
   <div class="span3 well">
-    {% if error %}<div class="alert alert-error"><strong>Error:</strong> {{ error }}</div>{% endif %}
     <form action="{{ url_for('login') }}" method="post">
     <fieldset><legend>Connexion</legend>
       <label for="username">E-mail</label>
-      <input type="text" name="username" id="username" />
+      <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" />
-      <br />
-      <input type="submit" class="btn btn-primary" value="Connexion" />
+      <div class="form-actions">
+        <input type="submit" class="btn btn-primary" value="Connexion" />
+      </div>
     </fieldset>
     </form>
-    <p><a href="">Mot de passe perdu ?</a></p>
+    <p><a href="{{ url_for("password_lost") }}">Mot de passe perdu ?</a></p>
   </div>
 </div>
 {% endblock %}

+ 17 - 0
templates/password_lost.html

@@ -0,0 +1,17 @@
+{% extends "layout.html" %}
+{% block body %}
+<div class="row">
+  <div class="span3 well">
+    <form action="{{ url_for('password_lost') }}" method="post">
+    <fieldset><legend>Oubli de mot de passe</legend>
+      <label for="email">E-mail</label>
+      <input type="text" name="email" id="email" />
+      <br />
+      <div class="form-actions">
+        <input type="submit" class="btn btn-primary" value="Je reconnais être tête en l'air" />
+      </div>
+    </fieldset>
+    </form>
+  </div>
+</div>
+{% endblock %}

+ 5 - 0
templates/user_settings.html

@@ -0,0 +1,5 @@
+{% extends "layout.html" %}
+{% block body %}
+<h2>{{ session.username }}</h2>
+{% endblock %}
+