"Firt release"

This commit is contained in:
2018-03-05 22:12:02 +01:00
parent f1ec84ef16
commit ec8b53c3e5
22 changed files with 7205 additions and 128 deletions
+504 -55
View File
@@ -7,8 +7,18 @@ import inspect
import random
import binascii
import bcrypt
from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash
import datetime
import ast
from reportlab.lib import colors
from reportlab.lib.enums import TA_LEFT, TA_CENTER
from reportlab.lib.pagesizes import A4, cm, portrait
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, PageBreak, Indenter
from reportlab.lib.colors import black, white, orange, bisque, lightsalmon
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash, send_file
from functools import wraps
import cStringIO
from flask_mail import Mail, Message
# Optionnal modules
import psycopg2
@@ -18,6 +28,9 @@ from flask_sqlalchemy import SQLAlchemy
# App settings
########################################################################
app = Flask(__name__)
mail = Mail(app)
# Jinja2 loopcontrols extension
app.jinja_env.add_extension('jinja2.ext.loopcontrols')
# Path to static files
app.static_url_path='/static'
# Set debug mode to False for production
@@ -30,6 +43,7 @@ app.secret_key = '9ac80548e3a8d8dfd1aefcd9a3a73473'
db = SQLAlchemy(app)
########################################################################
# Sample user database
########################################################################
@@ -42,6 +56,7 @@ class Tetawebapp_users(db.Model):
phone = db.Column(db.Text, nullable=True)
diet = db.Column(db.Text, nullable=True)
is_admin = db.Column(db.Integer, nullable=False, default=0)
link_id = db.Column(db.Text, nullable=True)
class Tetawebapp_roles(db.Model):
__tablename__ = 'participer_thsf_roles'
@@ -53,10 +68,16 @@ class Tetawebapp_turns(db.Model):
__tablename__ = 'participer_thsf_turns'
id = db.Column(db.Integer, primary_key=True)
role_id = db.Column(db.Integer, db.ForeignKey('participer_thsf_roles.id'), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('participer_thsf_users.id'), nullable=True)
wday = db.Column(db.Enum('Jeudi', 'Vendredi', 'Samedi', 'Dimanche'), nullable=False)
start_time = db.Column(db.Time, nullable=False)
end_time = db.Column(db.Time, nullable=False)
start_time = db.Column(db.DateTime, nullable=False)
end_time = db.Column(db.DateTime, nullable=False)
num_slot = db.Column(db.Integer, nullable=False, default=2)
class Tetawebapp_staffs(db.Model):
__tablename__ = 'participer_thsf_staffs'
id = db.Column(db.Integer, primary_key=True)
turn_id = db.Column(db.Integer, db.ForeignKey('participer_thsf_turns.id'), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('participer_thsf_users.id'), default=0, nullable=False)
slot_num = db.Column(db.Integer, nullable=False)
########################################################################
# Menu and navigation management
@@ -73,14 +94,13 @@ def get_menu(page):
The value MUST be 0."""
menu = [[u'Accueil', {u'/': [u'/']}, 0],
[u'Mon compte', {u'/account': [u'/account', u'/account/update']}, 0],
[u'Mes tours de staff', {u'/turns': [u'/turns']}, 0],
[u'Feuilles de staff', {u'/staff_sheets': [u'/staff_sheet']}, 0],
[u'Feuille de staff', {u'/staffsheet': [u'/staffsheet', u'/staffsheet/clear/<TURN_ID>/<SLOT_ID>', u'/staffsheet/update/<TURN_ID>/<SLOT_ID>']}, 0],
[u'Déconnexion', {u'/logout': [u'/logout']}, 0],
]
if session['is_admin']:
menu = [[u'Accueil', {u'/': [u'/']}, 0],
[u'Tours de staff', {u'/turns': [u'/turns', u'/turn/<ID>', u'/turn/new', u'/turn/add', u'/turn/delete/<ID>', u'/turn/update/<ID>']}, 0],
[u'Feuilles de staff', {u'/staff_sheets': [u'/staff_sheet']}, 0],
[u'Feuille de staff', {u'/staffsheet': [u'/staffsheet', u'/staffsheet/clear/<TURN_ID>/<SLOT_ID>', u'/staffsheet/update/<TURN_ID>/<SLOT_ID>', u'/staffsheet/pdf']}, 0],
[u'Liste des staffers', {u'/users': [u'/users', u'/account/<ID>', u'/account/delete/<ID>']}, 0],
[u'Déconnexion', {u'/logout': [u'/logout']}, 0],
]
@@ -154,11 +174,27 @@ def check_session(func):
def check_login(login, password):
""" Puts the login verification code here """
hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
stored_hash = Tetawebapp_users.query.filter_by(mail=login).with_entities(Tetawebapp_users.password).first()
is_admin = Tetawebapp_users.query.filter_by(mail=login).with_entities(Tetawebapp_users.is_admin).first()
stored_hash = Tetawebapp_users.query.filter(Tetawebapp_users.mail==login, Tetawebapp_users.link_id==None).with_entities(Tetawebapp_users.password).first()
if stored_hash:
if bcrypt.checkpw(password, stored_hash[0].encode('utf-8')):
is_admin = Tetawebapp_users.query.filter_by(mail=login).with_entities(Tetawebapp_users.is_admin).first()
user_id = Tetawebapp_users.query.filter_by(mail=login).with_entities(Tetawebapp_users.id).first()
session['is_admin'] = is_admin[0]
session['user_id'] = user_id[0]
return True
print "[+] Login failed"
return False
def check_confirm(login, password, link_id):
""" Check identity when confirming email address """
hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
stored_hash = Tetawebapp_users.query.filter(Tetawebapp_users.mail==login, Tetawebapp_users.link_id==link_id).with_entities(Tetawebapp_users.password).first()
if stored_hash:
if bcrypt.checkpw(password, stored_hash[0].encode('utf-8')):
is_admin = Tetawebapp_users.query.filter_by(mail=login).with_entities(Tetawebapp_users.is_admin).first()
user_id = Tetawebapp_users.query.filter_by(mail=login).with_entities(Tetawebapp_users.id).first()
session['is_admin'] = is_admin[0]
session['user_id'] = user_id[0]
return True
return False
@@ -173,8 +209,9 @@ def register_user(login, password, confirm):
# User already exists
print "[+] User already exists"
return False
link_id = gen_token(20)
hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
user = Tetawebapp_users(mail=login.encode('utf8'), password=hashed_password)
user = Tetawebapp_users(mail=login.encode('utf8'), password=hashed_password, link_id=link_id)
try:
db.session.add(user)
commit = db.session.commit()
@@ -186,9 +223,31 @@ def register_user(login, password, confirm):
print "------------------------------"
return False
if commit != None:
print "[+] Error at register_user: commit was not None"
return False
send_mail(login, link_id)
return True
def confirm_user(login, password, link_id):
""" Confirm user """
if check_confirm(login, password, link_id):
user = Tetawebapp_users.query.filter_by(mail=login).first()
setattr(user, 'link_id', None)
try:
db.session.add(user)
commit = db.session.commit()
except Exception as e:
db.session.rollback()
print "[+] Error at confirm_user:"
print "------------------------------"
print "%s" % e.message
print "------------------------------"
return False
if commit != None:
return False
return True
return False
def update_user(login, password, confirm, name, phone, diet):
""" Update user infos with provided data """
if password != confirm:
@@ -250,7 +309,7 @@ def update_user_by_id(user_id, login, password, confirm, name, phone, diet):
commit = db.session.commit()
except Exception as e:
db.session.rollback()
print "[+] Error at update_user:"
print "[+] Error at update_user_by_id:"
print "------------------------------"
print "%s" % e.message
print "------------------------------"
@@ -275,12 +334,22 @@ def delete_user(user_id):
print "------------------------------"
return False
def save_turn(role_id, day, start, end):
def save_turn(role_id, day, start, end, num_slot):
""" Save a new turn """
days = ['2018-05-08', '2018-05-09', '2018-05-10', '2018-05-11', '2018-05-12', '2018-05-13', '2018-05-14']
day_index = days.index(day)
sday = day
eday = day
if str(start[0]) == '0':
sday = days[day_index+1]
if str(end[0]) == '0':
eday = days[day_index+1]
start = '%s %s' % (sday, start)
end = '%s %s' % (eday, end)
turn = Tetawebapp_turns(role_id=role_id.encode('utf-8'),
wday=day.encode('utf-8'),
start_time=start.encode('utf-8'),
end_time=end.encode('utf-8'),
num_slot=num_slot.encode('utf-8'),
)
try:
db.session.add(turn)
@@ -296,18 +365,45 @@ def save_turn(role_id, day, start, end):
return False
return True
def update_turn_by_id(turn_id, role_id, wday, start, end):
def get_turn_by_id(turn_id):
""" Get specified stafff turn """
days = {'2018-05-08': 'Mardi',
'2018-05-09': 'Mercredi',
'2018-05-10': 'Jeudi',
'2018-05-11': 'Vendredi',
'2018-05-12': 'Samedi',
'2018-05-13': 'Dimanche',
'2018-05-14': 'Lundi'}
turn = Tetawebapp_turns.query.filter_by(id=turn_id).first()
s_day, s_time = str(turn.start_time).split(' ')
e_day, e_time = str(turn.end_time).split(' ')
if s_time[0] == '0':
s_day = (datetime.datetime.strptime(s_day, '%Y-%m-%d')-datetime.timedelta(1)).strftime("%Y-%m-%d")
day = days[s_day]
return {'id': turn_id, 'role_id': turn.role_id, 'day': day, 'start_time': s_time, 'end_time': e_time, 'num_slot': turn.num_slot}
def update_turn_by_id(turn_id, role_id, day, start, end, num_slot):
""" Update turn with provided data """
check_turn = Tetawebapp_turns.query.filter_by(id=turn_id).count()
if check_turn == 0:
# User does not exist
print "[+] User does not exist"
print "[+] Turn does not exist"
return False
days = ['2018-05-08', '2018-05-09', '2018-05-10', '2018-05-11', '2018-05-12', '2018-05-13', '2018-05-14']
day_index = days.index(day)
sday = day
eday = day
if str(start[0]) == '0':
sday = days[day_index +1]
if str(end[0]) == '0':
eday = days[day_index +1]
start = '%s %s' % (sday, start)
end = '%s %s' % (eday, end)
turn = Tetawebapp_turns.query.filter_by(id=turn_id).first()
setattr(turn, 'role_id', role_id)
setattr(turn, 'wday', wday)
setattr(turn, 'start_time', start)
setattr(turn, 'end_time', end)
setattr(turn, 'num_slot', num_slot)
try:
db.session.add(turn)
commit = db.session.commit()
@@ -339,6 +435,104 @@ def drop_turn(turn_id):
print "------------------------------"
return False
def turns_list():
""" List staff turns """
turns = []
tuesday = '2018-05-08 06:00:00'
wenesday = '2018-05-09 06:00:00'
thirsday = '2018-05-10 06:00:00'
friday = '2018-05-11 06:00:00'
saturday = '2018-05-12 06:00:00'
sunday = '2018-05-13 06:00:00'
monday = '2018-05-14 06:00:00'
tuesday_turns = Tetawebapp_turns.query.filter(Tetawebapp_turns.start_time > tuesday, Tetawebapp_turns.start_time < wenesday)
tuesday_turns = tuesday_turns.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id)
tuesday_turns = tuesday_turns.add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id, Tetawebapp_turns.start_time).all()
wenesday_turns = Tetawebapp_turns.query.filter(Tetawebapp_turns.start_time > wenesday, Tetawebapp_turns.start_time < thirsday)
wenesday_turns = wenesday_turns.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id)
wenesday_turns = wenesday_turns.add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id, Tetawebapp_turns.start_time).all()
thirsday_turns = Tetawebapp_turns.query.filter(Tetawebapp_turns.start_time > thirsday, Tetawebapp_turns.start_time < friday)
thirsday_turns = thirsday_turns.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id)
thirsday_turns = thirsday_turns.add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id, Tetawebapp_turns.start_time).all()
friday_turns = Tetawebapp_turns.query.filter(Tetawebapp_turns.start_time > friday, Tetawebapp_turns.start_time < saturday)
friday_turns = friday_turns.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id)
friday_turns = friday_turns.add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id, Tetawebapp_turns.start_time).all()
saturday_turns = Tetawebapp_turns.query.filter(Tetawebapp_turns.start_time > saturday, Tetawebapp_turns.start_time < sunday)
saturday_turns = saturday_turns.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id)
saturday_turns = saturday_turns.add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id, Tetawebapp_turns.start_time).all()
sunday_turns = Tetawebapp_turns.query.filter(Tetawebapp_turns.start_time > sunday, Tetawebapp_turns.start_time < monday)
sunday_turns = sunday_turns.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id)
sunday_turns = sunday_turns.add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id, Tetawebapp_turns.start_time).all()
turns.append(('Mardi', tuesday_turns))
turns.append(('Mercredi', wenesday_turns))
turns.append(('Jeudi', thirsday_turns))
turns.append(('Vendredi', friday_turns))
turns.append(('Samedi', saturday_turns))
turns.append(('Dimanche', sunday_turns))
return turns
def get_staffs():
""" """
try:
staffs = Tetawebapp_staffs.query.join(Tetawebapp_users, Tetawebapp_staffs.user_id==Tetawebapp_users.id)
staffs = staffs.add_columns(Tetawebapp_users.name).all()
return staffs
except Exception as e:
print "[+] Error at get_staffs:"
print "------------------------------"
print "%s" % e.message
print "------------------------------"
return False
def drop_staff_slot(turn_id, slot_num, user_id):
""" Drop staff given slot """
slot = Tetawebapp_staffs.query.filter_by(turn_id=turn_id, slot_num=slot_num).first()
if slot.user_id == user_id:
try:
Tetawebapp_staffs.query.filter_by(turn_id=turn_id, slot_num=slot_num).delete()
db.session.commit()
return True
except Exception as e:
db.session.rollback()
print "[+] Error at drop_staff_slot:"
print "------------------------------"
print "%s" % e.message
print "------------------------------"
return False
return False
def save_staff_slot(turn_id, slot_id, user_id):
""" Save staff given slot """
slot = Tetawebapp_staffs(user_id=user_id,
turn_id=turn_id,
slot_num=slot_id)
try:
db.session.add(slot)
commit = db.session.commit()
except Exception as e:
db.session.rollback()
print "[+] Error at save_staff_slot:"
print "------------------------------"
print "%s" % e.message
print "------------------------------"
return False
if commit != None:
return False
return True
def get_roles():
""" Get full roles list """
try:
roles = Tetawebapp_roles.query.filter(Tetawebapp_roles.id > 3).all()
return roles
except Exception as e:
print "[+] Error at get_staffs:"
print "------------------------------"
print "%s" % e.message
print "------------------------------"
return False
def check_user_info():
""" Check user info and send appropriate message if info are not complete"""
message = ''
@@ -351,11 +545,28 @@ def check_user_info():
message = "Vos informations personnelles ne sont pas complètement renseignées. N'oubliez pas de remplir votre fiche située dans la section 'Mon compte'"
return message.decode('utf-8')
def gen_token():
def gen_token(size=42):
""" Generate a random token to be stored in session and cookie """
token = binascii.hexlify(os.urandom(42))
token = binascii.hexlify(os.urandom(size))
return token
def send_mail(email, link_id):
msg = Message("Confirmation d'inscription au staff THSF",
sender="dave.null@tetalab.org",
recipients=[email])
msg.body = "Bonjour,\nVous recevez ce courriel car vous avez souhaité faire partie de l'équipe du staff du THSF.\n\n"
msg.body += "Pour confirmer votre inscription, rendez vous à la page suivante:\n"
msg.body += "https://wemake.thsf.net/confirm/%s\n\n" % str(link_id)
msg.body += "Si vous n'êtes pas à l'origine de cette inscription, ignorez simplement ce courriel.\n"
msg.body += "Votre compte sera automatiquement supprimé dans les 24 heures.\n\n"
msg.body += "Si vous désirez vous désinscrire, faites simplement une demande sur https://bofh.tetalab.org\n\n"
msg.body += "Dans tous les cas la base de données sera totalement réinitialisée à la fin du THSF.\n\n"
msg.body += "Votre aide nous est précieuse.\nMerci et bravo à vous.\n"
msg.body += "-- \n"
msg.body += "L'équipe d'organisation du THSF\n"
msg.body += "(Ce mail vous est envoyé par un robot qui n' a pas réussi le test de Turing, inutile de lui répondre)"
mail.send(msg)
########################################################################
# Routes:
# -------
@@ -388,11 +599,50 @@ def login():
# Credentials are not valid
response = app.make_response(render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide"))
session['token'] = ''
session['login'] = ''
session['is_admin'] = 0
sync_cookies(response, session)
return response
except AttributeError:
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
@app.route("/confirm/<LINK_ID>", methods=['GET', 'POST'])
def confirm(LINK_ID):
""" Index page """
link_id = LINK_ID.encode('utf-8')
return render_template('confirm.html', message="Merci de confirmer votre enregistrement", link_id=link_id)
@app.route("/confirm/link/<LINK_ID>", methods=['GET', 'POST'])
def confirm_link(LINK_ID):
""" Index page """
try:
link_id = LINK_ID.encode('utf-8')
login = request.form.get('login').encode('utf-8')
password = request.form.get('password').encode('utf-8')
if check_confirm(login, password, link_id) and confirm_user(login, password, link_id):
# Generate and store a token in session
session['token'] = gen_token()
session['login'] = login
# Return user to index page
page = '/'
menu = get_menu(page)
message = check_user_info()
response = app.make_response(render_template('index.html', menu=menu, message=message, login=login))
# Push token to cookie
sync_cookies(response, session)
return response
# Credentials are not valid
response = app.make_response(render_template('confirm.html', message="Utilisateur ou mot de passe invalide", link_id=link_id))
session['token'] = ''
session['login'] = ''
session['is_admin'] = 0
sync_cookies(response, session)
return response
except AttributeError:
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
link_id = LINK_ID.encode('utf-8')
return render_template('confirm.html', message="Merci de confirmer votre enregistrement", link_id=link_id)
@app.route("/register", methods=['GET', 'POST'])
def register():
""" Allow self registration """
@@ -400,24 +650,11 @@ def register():
login = request.form.get('login').encode('utf-8')
password = request.form.get('password').encode('utf-8')
confirm = request.form.get('confirm').encode('utf-8')
if register_user(login, password, confirm):
# Generate and store a token in session
session['token'] = gen_token()
session['login'] = login
# Return user to index page
page = '/'
menu = get_menu(page)
message = check_user_info()
response = app.make_response(render_template('index.html', menu=menu, login=login, message=message))
# Push token to cookie
sync_cookies(response, session)
return response
# Error while registering user
message = "Erreur lors de l'enregsitrement: L'utilisateur existe t-il déjà ?".decode('utf-8')
response = app.make_response(render_template('login_or_register.html', message=message))
session['token'] = ''
sync_cookies(response, session)
return response
if register_user(login, password, confirm):
message = "Merci de votre engagement. Un courriel contenant les instructions de confirmation votre inscription vient de vous être envoyé."
# Error while registering user
return render_template('login_or_register.html', message=message.decode('utf-8'))
except AttributeError:
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
@@ -578,15 +815,20 @@ def delete_account(ID):
@app.route("/turns", methods=['GET', 'POST'])
@check_session
def list_turn():
def list_turns():
""" List staff turns """
try:
page = str(request.url_rule)
menu = get_menu(page)
message = ''
if session['is_admin']:
page = str(request.url_rule)
menu = get_menu(page)
turns = Tetawebapp_turns.query.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id).add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id).all()
turns = turns_list()
message = ''
return render_template('list_turns.html', menu=menu, page=page, turns=turns, message=message)
# TODO:
# Here comes the list_turns_by_user_id code
except AttributeError:
# User is not logged in
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
@@ -595,12 +837,19 @@ def list_turn():
@check_session
def new_turn():
""" New turn form """
tuesday = '2018-05-08'
wenesday = '2018-05-09'
thirsday = '2018-05-10'
friday = '2018-05-11'
saturday = '2018-05-12'
sunday = '2018-05-13'
monday = '2018-05-14'
try:
if session['is_admin']:
page = str(request.url_rule)
menu = get_menu(page)
roles = Tetawebapp_roles.query.order_by(Tetawebapp_roles.id).all()
days = ['Jeudi', 'Vendredi', 'Samedi', 'Dimanche']
days = [('Mardi', tuesday), ('Mercredi', wenesday), ('Jeudi', thirsday), ('Vendredi', friday), ('Samedi', saturday), ('Dimanche', sunday)]
return render_template('new_turn.html', menu=menu, page=page, roles=roles, days=days)
except AttributeError:
# User is not logged in
@@ -616,18 +865,15 @@ def add_turn():
day = request.form.get('day').encode('utf-8')
start = request.form.get('start').encode('utf-8')
end = request.form.get('end').encode('utf-8')
num_slot = request.form.get('num_slot').encode('utf-8')
page = str(request.url_rule)
menu = get_menu(page)
turns = Tetawebapp_turns.query.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id).add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id).all()
turns = turns_list()
message = "Erreur lors de l'enregistrement.".decode('utf-8')
if save_turn(role_id, day, start, end):
turns = Tetawebapp_turns.query.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id).add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id).all()
if save_turn(role_id, day, start, end, num_slot):
turns = turns_list()
message=''
return render_template('list_turns.html', menu=menu, page=page, turns=turns, message=message)
# Error while saving turn
roles = Tetawebapp_roles.query.order_by(Tetawebapp_roles.id).all()
days = ['Jeudi', 'Vendredi', 'Samedi', 'Dimanche']
return render_template('new_turn.html', menu=menu, page=page, roles=roles, days=days, message=message)
# User is not admin
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
except AttributeError as e:
@@ -639,14 +885,21 @@ def add_turn():
def turn_by_id(ID):
try:
if session['is_admin']:
tuesday = '2018-05-08'
wenesday = '2018-05-09'
thirsday = '2018-05-10'
friday = '2018-05-11'
saturday = '2018-05-12'
sunday = '2018-05-13'
monday = '2018-05-14'
days = [('Mardi', tuesday), ('Mercredi', wenesday), ('Jeudi', thirsday), ('Vendredi', friday), ('Samedi', saturday), ('Dimanche', sunday)]
page = str(request.url_rule)
menu = get_menu(page)
roles = Tetawebapp_roles.query.order_by(Tetawebapp_roles.id).all()
days = ['Jeudi', 'Vendredi', 'Samedi', 'Dimanche']
message = 'ID du tour de staff non conforme'
turns = Tetawebapp_turns.query.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id).add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id).all()
turns = turns_list()
turn_id = int(ID.encode('utf-8'))
turn = Tetawebapp_turns.query.filter_by(id=ID).first()
turn = get_turn_by_id(turn_id)
return render_template('turn_by_id.html', menu=menu, page=page, turn=turn, roles=roles, days=days)
except AttributeError:
# User is not logged in
@@ -661,17 +914,18 @@ def update_turn(ID):
""" Update given staff turn """
try:
role_id = request.form.get('role_id').encode('utf-8')
day = request.form.get('day').encode('utf-8')
start = request.form.get('start').encode('utf-8')
end = request.form.get('end').encode('utf-8')
num_slot = request.form.get('num_slot').encode('utf-8')
day = request.form.get('day').encode('utf-8')
if session['is_admin']:
page = str(request.url_rule)
menu = get_menu(page)
turns = Tetawebapp_turns.query.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id).add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id).all()
turns = turns_list()
message = "Erreur lors de l'enregistrement.".decode('utf-8')
turn_id = int(ID.encode('utf-8'))
if update_turn_by_id(turn_id, role_id, day, start, end):
turns = Tetawebapp_turns.query.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id).add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id).all()
if update_turn_by_id(turn_id, role_id, day, start, end, num_slot):
turns = turns_list()
message = ''
return render_template('list_turns.html', menu=menu, page=page, turns=turns, message=message)
# User is not admin
@@ -692,11 +946,11 @@ def delete_turn(ID):
message = 'Erreur lors de la suppression.'
page = str(request.url_rule)
menu = get_menu(page)
turns = Tetawebapp_turns.query.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id).add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id).all()
turns = turns_list()
turn_id = int(ID.encode('utf-8'))
if drop_turn(turn_id):
message = ''
turns = Tetawebapp_turns.query.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id).add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id).all()
turns = turns_list()
return render_template('list_turns.html', menu=menu, turns=turns, message=message)
return render_template('list_turns.html', menu=menu, turns=turns, message=message)
# User is not admin
@@ -708,6 +962,201 @@ def delete_turn(ID):
# ID is not an integer
return render_template('list_turns.html', menu=menu, page=page, turns=turns, message=message)
@app.route("/staffsheet", methods=['GET', 'POST'])
@check_session
def staffsheet():
try:
user_id = session['user_id']
if len(check_user_info()) == 0:
page = str(request.url_rule)
menu = get_menu(page)
turns = turns_list()
staffs = get_staffs()
roles = get_roles()
return render_template('staffsheet.html', menu=menu, turns=turns, staffs=staffs, user_id=user_id, roles=roles, message='')
else:
return account()
except AttributeError as e:
# User is not logged in
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
@app.route("/staffsheet/pdf", methods=['GET', 'POST'])
def staffsheet_pdf():
turns = turns_list()
staffs = get_staffs()
roles = get_roles()
data = render_template('staffsheet_txt.html', turns=turns, staffs=staffs, roles=roles)
data = [line for line in data.split('\n') if len(line) > 0]
data = '\n'.join(data)
data = [line for line in data.split('",\n') if len(line) > 0]
data = '", '.join(data)
ddata = [ast.literal_eval(line) for line in data.split('\n')]
pdf = cStringIO.StringIO()
doc = SimpleDocTemplate(pdf, pagesize=A4, rightMargin=3,leftMargin=3, topMargin=3,bottomMargin=3)
elements = []
styles = getSampleStyleSheet()
styles.add(ParagraphStyle(name='master_title',
alignment=TA_LEFT,
fontSize=20,
leading=25,
spaceBefore=10,
spaceAfter=10,
))
styles.add(ParagraphStyle(name='day_title',
alignment=TA_LEFT,
backColor=orange,
borderWidth=1,
borderColor=black,
borderPadding=5,
spaceBefore=10,
spaceAfter=10
))
styles.add(ParagraphStyle(name='role_title',
alignment=TA_LEFT,
backColor=lightsalmon,
borderWidth=1,
borderColor=black,
borderPadding=5,
spaceBefore=10,
spaceAfter=10
))
styles.add(ParagraphStyle(name='turn',
alignment=TA_LEFT,
backColor=white,
borderWidth=1,
borderColor=black,
borderPadding=5,
spaceBefore=10,
spaceAfter=0
))
styles.add(ParagraphStyle(name='basic_text',
alignment=TA_LEFT,
spaceBefore=5,
spaceAfter=5
))
styles.add(ParagraphStyle(name='row1',
alignment=TA_LEFT,
backColor=white,
spaceBefore=10,
spaceAfter=10
))
styles.add(ParagraphStyle(name='row2',
alignment=TA_CENTER,
backColor=white,
spaceBefore=10,
spaceAfter=10
))
elements.append(Paragraph("<b>Fiches de poste</b>", styles['master_title']))
elements.append(Paragraph("Les postes de référents (référent staff, référent bar, référent run) sont réservés à des personnes ayant une bonne connaissance du lieu et de l'évènement.",
styles['basic_text']))
for role in roles:
elements.append(Paragraph("<b>%s</b>" % role.role, styles['day_title']))
desc = role.description.split('|')
for point in desc:
elements.append(Paragraph(point, styles['basic_text'], bulletText='-'))
elements.append(PageBreak())
elements.append(Paragraph("<b>Feuilles de staff</b>", styles['master_title']))
elements.append(Paragraph("<b>Ménage le soir même pour tous les derniers créneaux du jour</b>", styles['basic_text'], bulletText='-'))
elements.append(Paragraph("Tâches dévolues <b>à tous et à tous moments</b>:", styles['basic_text'], bulletText='-'))
elements.append(Indenter(left=20, right=0) )
elements.append(Paragraph("Veiller à la sécurité générale du lieu", styles['basic_text'], bulletText='-'))
elements.append(Paragraph("Ramassage bouteilles ou objets en verre", styles['basic_text'], bulletText='-'))
elements.append(Paragraph("Séparation des bagarres (rarissime)", styles['basic_text'], bulletText='-'))
elements.append(Paragraph("Sécurisation des personnes en difficulté (ou trop alcoolisées), etc...", styles['basic_text'], bulletText='-'))
elements.append(Paragraph("<b>Sourire et bonne humeur</b> quel que soit le niveau de fatigue ;)", styles['basic_text'], bulletText='-'))
elements.append(Indenter(left=-20, right=0) )
for day in turns:
wday = day[0]
day_turns = day[1]
cur_role = ''
if wday not in ['Mardi', 'Mercredi']:
elements.append(PageBreak())
elements.append(Paragraph("<b>%s</b>" % wday, styles['day_title']))
for turn in day_turns:
rows = []
role = turn[1]
start_time = turn[0].start_time
end_time = turn[0].end_time
num_slot = turn[0].num_slot
role_id = turn[0].role_id
turn_id = turn[0].id
if role != cur_role:
cur_role = role
elements.append(Paragraph("<b>%s</b>" % role, styles['role_title']))
row = (Paragraph("<b>%s / %s</b>" % (start_time.strftime('%HH%M'), end_time.strftime('%HH%M')), styles['row1']),)
for slot in range(0, num_slot):
cols_width = [100] + [485/num_slot] * num_slot
allocated_slot = []
for sslot in staffs:
if sslot[0].turn_id == turn_id and sslot[0].slot_num == slot:
allocated_slot.append(sslot[0].slot_num)
row += (Paragraph(sslot[1], styles['row2']),)
if slot not in allocated_slot:
row += (Paragraph("&nbsp;", styles['row2']),)
rows.append(row)
table = Table(rows, colWidths=cols_width, rowHeights=23)
table.setStyle(TableStyle( [('GRID', (0,0), (-1,-1), 0.25, colors.black),
('ALIGN', (1,1), (-1,-1), 'RIGHT')]))
elements.append(table)
styles.wordWrap = 'CJK'
doc.build(elements)
pdf_out = pdf.getvalue()
pdf.close()
response = app.make_response(pdf_out)
response.headers['Content-Disposition'] = "attachment; filename=feuille_staff_thsf.pdf"
response.mimetype = 'application/pdf'
return response
@app.route("/staffsheet/clear/<TURN_ID>/<SLOT_ID>", methods=['GET', 'POST'])
@check_session
def clear_staff_slot(TURN_ID, SLOT_ID):
try:
turn_id = int(TURN_ID.encode('utf-8'))
slot_id = int(SLOT_ID.encode('utf-8'))
user_id = session['user_id']
message = "Erreur lors de l'enregistrement des données"
if (drop_staff_slot(turn_id, slot_id, user_id)):
message = ''
page = str(request.url_rule)
menu = get_menu(page)
turns = turns_list()
staffs = get_staffs()
roles = get_roles()
user_id = session['user_id']
return render_template('staffsheet.html', menu=menu, turns=turns, staffs=staffs, user_id=user_id, roles=roles, message=message.decode('utf-8'))
except AttributeError:
# User is not logged in
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
except ValueError:
# At least one ID is not integer
return render_template('login_or_register.html', message="Identifiants non conformes")
@app.route("/staffsheet/update/<TURN_ID>/<SLOT_ID>", methods=['GET', 'POST'])
@check_session
def update_staff_slot(TURN_ID, SLOT_ID):
try:
turn_id = int(TURN_ID.encode('utf-8'))
slot_id = int(SLOT_ID.encode('utf-8'))
user_id = session['user_id']
message = "Erreur lors de l'enregistrement des données"
if (save_staff_slot(turn_id, slot_id, user_id)):
message = ''
page = str(request.url_rule)
menu = get_menu(page)
turns = turns_list()
staffs = get_staffs()
roles = get_roles()
user_id = session['user_id']
return render_template('staffsheet.html', menu=menu, turns=turns, staffs=staffs, user_id=user_id, roles=roles, message=message.decode('utf-8'))
except AttributeError as e:
# User is not logged in
print e
return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
except ValueError:
# At least one ID is not integer
return render_template('login_or_register.html', message="Identifiants non conformes")
########################################################################
# Main
########################################################################