Commit f951b660 authored by Nicolas Joyard's avatar Nicolas Joyard

Utilisation d'un modèle db pour les users

parent 7ba1706d
......@@ -3,3 +3,4 @@
from .database import db # noqa
from .parlementaire import Groupe, Parlementaire # noqa
from .procedure import Action, Etape # noqa
from .user import User # noqa
......@@ -97,7 +97,7 @@ ETAPES = [
},
{
'ordre': ETAPE_A_CONFIRMER,
'label': 'À confirmer',
'label': 'Pris en charge',
'description': """
Un utilisateur a souhaité se charger de l'envoi de la demande, mais
nous n'avons pas encore confirmation de cet envoi.
......
......@@ -23,8 +23,6 @@ class Action(db.Model):
id = db.Column(db.Integer, primary_key=True)
date = db.Column(db.DateTime)
nick = db.Column(db.Unicode)
email = db.Column(db.Unicode)
ip = db.Column(db.Unicode)
suivi = db.Column(db.Unicode)
......@@ -36,3 +34,6 @@ class Action(db.Model):
parlementaire_id = db.Column(db.Integer,
db.ForeignKey('parlementaires.id'))
parlementaire = db.relationship('Parlementaire', back_populates='actions')
user_id = db.Column(db.Integer, db.ForeignKey('users.id'))
user = db.relationship('User', back_populates='actions')
# -*- coding: utf-8 -*-
from .database import db
class User(db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key=True)
nick = db.Column(db.Unicode)
email = db.Column(db.Unicode)
admin = db.Column(db.Boolean)
abo_rc = db.Column(db.Boolean)
abo_membres = db.Column(db.Boolean)
abo_irfm = db.Column(db.Boolean)
actions = db.relationship('Action', back_populates='user',
order_by='Action.date')
......@@ -7,7 +7,7 @@ from flask import (make_response, redirect, render_template, request, session,
url_for)
from sqlalchemy.orm import joinedload
from ..models import Action, Etape, Parlementaire, db
from ..models import Action, Etape, Parlementaire, User, db
from ..models.constants import (ETAPE_A_CONFIRMER, ETAPE_A_ENVOYER,
ETAPE_COM_A_MODERER, ETAPE_COM_PUBLIE)
......@@ -26,6 +26,7 @@ def setup_routes(app):
qs = Action.query.options(joinedload(Action.parlementaire)
.joinedload(Parlementaire.etape)) \
.options(joinedload(Action.etape)) \
.options(joinedload(Action.user)) \
.order_by(Action.date.desc()) \
.limit(500) \
.all()
......@@ -47,6 +48,7 @@ def setup_routes(app):
qs = Action.query.join(Action.etape) \
.filter(Action.parlementaire_id.in_(parls)) \
.filter(Etape.ordre == ETAPE_A_CONFIRMER) \
.options(joinedload(Action.user)) \
.order_by(Action.date) \
.all()
......@@ -60,6 +62,7 @@ def setup_routes(app):
qs = Action.query.join(Action.etape) \
.filter(Etape.ordre == ETAPE_COM_A_MODERER) \
.options(joinedload(Action.parlementaire)) \
.options(joinedload(Action.user)) \
.order_by(Action.date) \
.all()
......@@ -154,8 +157,7 @@ def setup_routes(app):
action = Action(
date=datetime.now(),
nick=session['user']['nick'],
email=session['user']['email'],
user=User.query.filter(User.id == session['user']['id']).one(),
ip=remote_addr(),
parlementaire=parl,
etape=etape,
......
......@@ -9,7 +9,7 @@ from flask_mail import Mail, Message
from sqlalchemy.orm import contains_eager, joinedload
from ..models import Action, Etape, Parlementaire, db
from ..models import Action, Etape, Parlementaire, User, db
from ..models.constants import (ETAPE_A_CONFIRMER, ETAPE_A_ENVOYER,
ETAPE_COM_A_MODERER, ETAPE_COM_PUBLIE,
ETAPE_ENVOYE)
......@@ -31,8 +31,7 @@ def pris_en_charge(parl, force=False):
else:
action = [a for a in parl.actions
if a.etape.ordre == ETAPE_A_CONFIRMER and
a.nick == session.get('user')['nick'] and
a.email == session.get('user')['email']]
a.user_id == session.get('user')['id']]
if len(action):
return action[0]
......@@ -63,7 +62,8 @@ def setup_routes(app):
.filter_by(id=id) \
.options(joinedload(Parlementaire.groupe)) \
.options(joinedload(Parlementaire.etape)) \
.options(joinedload(Parlementaire.actions)) \
.options(joinedload(Parlementaire.actions)
.joinedload(Action.user)) \
.first()
if not parl:
......@@ -107,8 +107,7 @@ def setup_routes(app):
action = Action(
date=datetime.now(),
nick=session['user']['nick'],
email=session['user']['email'],
user=User.query.filter(User.id == session['user']['id']).one(),
ip=remote_addr(),
parlementaire=parl,
etape=parl.etape
......@@ -211,8 +210,7 @@ def setup_routes(app):
action = Action(
date=datetime.now(),
nick=session['user']['nick'],
email=session['user']['email'],
user=User.query.filter(User.id == session['user']['id']).one(),
ip=remote_addr(),
parlementaire=parl,
etape=parl.etape,
......@@ -247,8 +245,8 @@ def setup_routes(app):
etape = Etape.query.filter(Etape.ordre == ordre).one()
action = Action(
date=datetime.now(),
nick=session['user']['nick'] if session.get('user') else '',
email=session['user']['email'] if session.get('user') else '',
user=User.query.filter(User.id == session['user']['id'])
.one() if session.get('user') else None,
ip=remote_addr(),
parlementaire=parl,
etape=etape,
......
# -*- coding: utf-8 -*-
from flask import request, session
from flask import flash, request, session
from ..models import User, db
from ..tools.routing import redirect_back
from ..tools.text import check_email, check_password, sanitize_hard
......@@ -14,7 +16,25 @@ def setup_routes(app):
if check_password(request.form['email'],
app.config['ADMIN_PASSWORD'],
app.config['SECRET_KEY']):
# Ensure admin user exists and update its email
changed = False
admin = User.query.filter_by(admin=True).first()
if not admin:
admin = User(nick='!rc', admin=True, abo_rc=False,
abo_membres=False, abo_irfm=False)
db.session.add(admin)
changed = True
if admin.email != app.config['ADMIN_EMAIL']:
admin.email = app.config['ADMIN_EMAIL']
changed = True
if changed:
db.session.commit()
session['user'] = {
'id': admin.id,
'nick': '!rc',
'email': app.config['ADMIN_EMAIL'],
'admin': True
......@@ -33,15 +53,29 @@ def setup_routes(app):
msg = 'Veuillez saisir un pseudonyme !'
return redirect_back(error=msg)
if not check_email(request.form['email'].strip()):
email = request.form['email'].strip()
if not check_email(email):
msg = 'Veuillez saisir une adresse e-mail valide pour assurer ' \
'le suivi de l\'envoi des demandes ! Vous pouvez aussi ' \
'laisser le champ vide si vous le préférez.'
'le suivi de l\'envoi des demandes !'
return redirect_back(error=msg)
user = User.query.filter(User.nick == nick).first()
if user and user.email != email:
msg = 'L\'adresse e-mail que vous avez saisie n\'est pas la bonne.'
return redirect_back(error=msg)
if not user:
user = User(nick=nick, email=email, admin=False, abo_rc=False,
abo_membres=False, abo_irfm=False)
db.session.add(user)
db.session.commit()
flash('Bienvenue %s !' % nick, category='success')
session['user'] = {
'id': user.id,
'nick': nick,
'email': request.form['email'].strip(),
'email': email,
'admin': False
}
......
......@@ -4,6 +4,7 @@ import locale
import os
from flask import Flask
from flaskext.markdown import Markdown
from .config import get_secret_key
......
......@@ -58,6 +58,10 @@ img.rc-small {
font-weight: bold;
}
.anon {
color: #ccc;
}
/* Tableaux */
.search-vector {
......
......@@ -25,10 +25,16 @@
</td>
<td>{{ action.date.strftime('%c') }}</td>
<td>
{% if action.nick == '!rc' %}
{% if not action.user %}
<span class="anon">anonyme</span>
{% elif action.user.nick == '!rc' %}
<img class="rc-small" src="{{ url_for('static', filename='rc.png') }}">
{% else %}
{{ action.nick }} ({{ action.email }}) depuis {{ action.ip }}
{{ action.user.nick }} ({{ action.user.email }})
{% endif %}
{% if action.ip %}
depuis {{ action.ip }}
{% endif %}
</td>
<td>
......
......@@ -28,10 +28,16 @@
<td>{{ action.etape|label_etape }}</td>
<td>{{ action.date.strftime('%c') }}</td>
<td>
{% if action.nick == '!rc' %}
{% if not action.user %}
<span class="anon">anonyme</span>
{% elif action.user.nick == '!rc' %}
<img class="rc-small" src="{{ url_for('static', filename='rc.png') }}">
{% else %}
{{ action.nick }} ({{ action.email }}) depuis {{ action.ip }}
{{ action.user.nick }} ({{ action.user.email }})
{% endif %}
{% if action.ip %}
depuis {{ action.ip }}
{% endif %}
</td>
<td>
......
......@@ -57,10 +57,12 @@
<tr>
<td>{{ act.etape|label_etape }}</td>
<td>
{% if act.nick == '!rc' %}
{% if act.user.nick == '!rc' %}
<img class="rc-small" src="{{ url_for('static', filename='rc.png') }}">
{% elif act.user %}
{{ act.user.nick }}
{% else %}
{{ act.nick }}
<span class="anon">anonyme</span>
{% endif %}
</td>
<td>{{ act.date.strftime("%c") }}</td>
......
......@@ -12,12 +12,8 @@ C'est normal, nous avons décidé de commencer l'opération uniquement avec les
##### Pourquoi dois-je m'identifier et donner une adresse e-mail ?
Vous n'êtes pas obligé de saisir une adresse e-mail ; vous pouvez vous identifier en tapant simplement un pseudonyme et en laissant le second champ vide. Dans tous les cas, vos informations ne sont sauvegardées dans notre base de données que si vous prenez en charge l'envoi pour un parlementaire. Si vous vous rétractez, tout est supprimé.
L'identification nous permet de mieux répartir les efforts, en nous assurant que personne d'autre n'envoie un courrier au même parlementaire lorsque vous décidez de le faire vous-même.
Si vous saisissez une adresse e-mail, vous serez notifié de l'avancement de l'opération.
Si vous avez saisi votre adresse e-mail et que vous le regrettez, [contactez-nous](mailto:{{ config.ADMIN_EMAIL }}) ! Nous supprimerons votre adresse au plus vite, conformément à la loi informatique et libertés.
##### Que me conseillez-vous pour approfondir le sujet de l'IRFM ?
......
......@@ -3,6 +3,7 @@
from flask import flash, redirect, request, session, url_for
from .text import is_safe_url
from ..models import User
def redirect_back(fallback=None, error=None):
......@@ -27,6 +28,12 @@ def require_user(f):
return redirect_back(error='Vous devez vous identifier pour '
'accéder à cette page')
if 'id' not in session['user']:
session['user']['id'] = User.query \
.filter(User.nick == session['user']['nick']) \
.filter(User.email == session['user']['email']) \
.one().id
return f(*args, **kwargs)
return decorator
......@@ -37,6 +44,12 @@ def require_admin(f):
if not session.get('user') or not session.get('user')['admin']:
return not_found()
if 'id' not in session['user']:
session['user']['id'] = User.query \
.filter(User.nick == session['user']['nick']) \
.filter(User.email == session['user']['email']) \
.one().id
return f(*args, **kwargs)
return decorator
......
"""Migration users
Revision ID: 0f6485160e01
Revises: f7f34ea0f9c3
Create Date: 2017-05-20 11:50:46.126613
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = '0f6485160e01'
down_revision = 'f7f34ea0f9c3'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('users',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('nick', sa.Unicode(), nullable=True),
sa.Column('email', sa.Unicode(), nullable=True),
sa.Column('admin', sa.Boolean(), nullable=True),
sa.Column('abo_rc', sa.Boolean(), nullable=True),
sa.Column('abo_membres', sa.Boolean(), nullable=True),
sa.Column('abo_irfm', sa.Boolean(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.add_column('actions', sa.Column('user_id', sa.Integer(), nullable=True))
op.create_foreign_key(None, 'actions', 'users', ['user_id'], ['id'])
op.execute("""
INSERT INTO users(nick, email, admin, abo_rc, abo_membres, abo_irfm)
SELECT DISTINCT
nick, email,
CASE WHEN nick = '!rc' THEN true ELSE false END,
false, false, false
FROM actions
WHERE nick != '';
""")
op.execute("""
UPDATE actions a
SET user_id = (SELECT u.id
FROM users u
WHERE u.nick = a.nick AND u.email = a.email)
WHERE a.nick != '';
""")
# op.drop_column('actions', 'email')
# op.drop_column('actions', 'nick')
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('actions', sa.Column('nick', sa.VARCHAR(), autoincrement=False, nullable=True))
op.add_column('actions', sa.Column('email', sa.VARCHAR(), autoincrement=False, nullable=True))
op.drop_constraint(None, 'actions', type_='foreignkey')
op.drop_column('actions', 'user_id')
op.drop_table('users')
# ### end Alembic commands ###
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment