2018-02-26 10:41:52 +01:00
#!/usr/bin/env python
# -*- coding: utf-8
# Required modules
import os
import inspect
import random
import binascii
import bcrypt
2018-03-05 22:12:02 +01:00
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
2018-02-26 10:41:52 +01:00
from functools import wraps
2018-03-05 22:12:02 +01:00
import cStringIO
from flask_mail import Mail , Message
2018-02-26 10:41:52 +01:00
# Optionnal modules
import psycopg2
from flask_sqlalchemy import SQLAlchemy
########################################################################
# App settings
########################################################################
app = Flask ( __name__ )
2018-03-05 22:12:02 +01:00
mail = Mail ( app )
# Jinja2 loopcontrols extension
app . jinja_env . add_extension ( 'jinja2.ext.loopcontrols' )
2018-02-26 10:41:52 +01:00
# Path to static files
app . static_url_path = '/static'
# Set debug mode to False for production
app . debug = True
# Various configuration settings belong here (optionnal)
app . config . from_pyfile ( 'config.local.py' )
# Generate a new key: head -n 40 /dev/urandom | md5sum | cut -d' ' -f1
2018-02-26 19:53:06 +01:00
app . secret_key = '9ac80548e3a8d8dfd1aefcd9a3a73473'
2018-02-26 10:41:52 +01:00
# Feel free to use SQLAlchemy (or not)
db = SQLAlchemy ( app )
2018-03-05 22:12:02 +01:00
2018-02-26 10:41:52 +01:00
########################################################################
# Sample user database
########################################################################
class Tetawebapp_users ( db . Model ):
2018-02-26 19:53:06 +01:00
__tablename__ = 'participer_thsf_users'
2018-02-26 10:41:52 +01:00
id = db . Column ( db . Integer , primary_key = True )
mail = db . Column ( db . Text , nullable = False )
password = db . Column ( db . Text , nullable = False )
2018-02-26 19:53:06 +01:00
name = db . Column ( db . Text , nullable = True )
phone = db . Column ( db . Text , nullable = True )
diet = db . Column ( db . Text , nullable = True )
2018-02-27 19:51:43 +01:00
is_admin = db . Column ( db . Integer , nullable = False , default = 0 )
2018-03-05 22:12:02 +01:00
link_id = db . Column ( db . Text , nullable = True )
2018-02-26 10:41:52 +01:00
2018-02-26 19:53:06 +01:00
class Tetawebapp_roles ( db . Model ):
__tablename__ = 'participer_thsf_roles'
id = db . Column ( db . Integer , primary_key = True )
role = db . Column ( db . Text , nullable = False )
description = db . Column ( db . Text , nullable = False )
2018-02-26 10:41:52 +01:00
2018-02-27 19:51:43 +01:00
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 )
2018-03-05 22:12:02 +01:00
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 )
2018-02-27 19:51:43 +01:00
2018-02-26 10:41:52 +01:00
########################################################################
# Menu and navigation management
########################################################################
def get_menu ( page ):
""" The main menu is a list of lists in the followin format:
[unicode caption,
{unicode URL endpoint: [unicode route, ...]},
int 0]
- The URL end point is the URL where to point to (href)
- One of the routes MUST match the route called by request
- The int 0 is used to determine which menu entry is actally called.
The value MUST be 0."""
2018-02-26 19:53:06 +01:00
menu = [[ u 'Accueil' , { u '/' : [ u '/' ]}, 0 ],
2018-02-27 19:51:43 +01:00
[ u 'Mon compte' , { u '/account' : [ u '/account' , u '/account/update' ]}, 0 ],
2018-03-05 22:12:02 +01:00
[ u 'Feuille de staff' , { u '/staffsheet' : [ u '/staffsheet' , u '/staffsheet/clear/<TURN_ID>/<SLOT_ID>' , u '/staffsheet/update/<TURN_ID>/<SLOT_ID>' ]}, 0 ],
2018-02-27 19:51:43 +01:00
[ u 'Déconnexion' , { u '/logout' : [ u '/logout' ]}, 0 ],
]
if session [ 'is_admin' ]:
menu = [[ u 'Accueil' , { u '/' : [ u '/' ]}, 0 ],
2018-02-28 10:25:08 +01:00
[ 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 ],
2018-03-05 22:12:02 +01:00
[ 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 ],
2018-02-28 10:25:08 +01:00
[ u 'Liste des staffers' , { u '/users' : [ u '/users' , u '/account/<ID>' , u '/account/delete/<ID>' ]}, 0 ],
2018-02-26 19:53:06 +01:00
[ u 'Déconnexion' , { u '/logout' : [ u '/logout' ]}, 0 ],
2018-02-26 10:41:52 +01:00
]
2018-02-28 10:25:08 +01:00
#~ print '[+] Page: %s' % page
2018-02-26 10:41:52 +01:00
for item in menu :
for url in item [ 1 ]:
for route in item [ 1 ][ url ]:
2018-02-28 10:25:08 +01:00
#~ print " [+] Route: %s" %route
2018-02-26 10:41:52 +01:00
if route == page :
2018-02-28 10:25:08 +01:00
#~ print " [+] Selected page: %s" % page
2018-02-26 10:41:52 +01:00
item [ 2 ] = 1
return menu
# This should never happen
return menu
def get_navbar ( page , selected ):
""" The horizontal navbar is a list of lists in the followin format:
[unicode caption, {unicode URL endpoint: [unicode route, ...]}, int 0]
- The URL end point is the URL where to point to (href)
- One of the routes MUST match the route called by request
- The int 0 is used to de """
navbars = [[ u 'First article' , { u '/articles/1' : [ u '/articles' , u '/articles/<ID>' ]}, 0 , 0 ],
[ u 'Second article' , { u '/articles/2' : [ u '/articles' , u '/articles/<ID>' ]}, 0 , 0 ],
[ u 'Third article' , { u '/articles/3' : [ u '/articles' , u '/articles/<ID>' ]}, 0 , 0 ]
]
navbar = []
for item in navbars :
for url in item [ 1 ]:
if url == selected :
item [ 2 ] = 1
for route in item [ 1 ][ url ]:
if route == page :
navbar . append ( item )
navbar [ len ( navbar ) - 1 ][ 3 ] = 1
return navbar
########################################################################
# Session management
########################################################################
def sync_session ( request , session ):
""" Synchronize cookies with session """
for key in request . cookies :
session [ key ] = request . cookies [ key ] . encode ( 'utf8' )
def sync_cookies ( response , session ):
""" Synchronize session with cookies """
for key in session :
response . set_cookie ( key , value = str ( session [ key ]))
def check_session ( func ):
""" Check if the session has required token cookie set.
If not, redirects to the login page. """
@wraps ( func )
def check ( * args , ** kwargs ):
try :
if session [ 'token' ] == request . cookies [ 'token' ] and len ( session [ 'token' ]) > 0 :
2018-02-27 19:51:43 +01:00
# User is logged in and identified
2018-02-26 10:41:52 +01:00
return func ( * args , ** kwargs )
else :
2018-02-27 19:51:43 +01:00
# User is not logged in or session expired
2018-02-26 10:41:52 +01:00
session [ 'token' ] = ''
2018-02-26 19:53:06 +01:00
response = app . make_response ( render_template ( 'login_or_register.html' , message = '' ))
2018-02-26 10:41:52 +01:00
sync_cookies ( response , session )
return response
except KeyError :
2018-02-27 19:51:43 +01:00
# User is not logged in
2018-02-26 19:53:06 +01:00
return render_template ( 'login_or_register.html' , message = '' )
2018-02-26 10:41:52 +01:00
return check
def check_login ( login , password ):
""" Puts the login verification code here """
hashed_password = bcrypt . hashpw ( password , bcrypt . gensalt ())
2018-03-05 22:12:02 +01:00
stored_hash = Tetawebapp_users . query . filter ( Tetawebapp_users . mail == login , Tetawebapp_users . link_id == None ) . with_entities ( Tetawebapp_users . password ) . first ()
2018-02-26 10:41:52 +01:00
if stored_hash :
if bcrypt . checkpw ( password , stored_hash [ 0 ] . encode ( 'utf-8' )):
2018-03-05 22:12:02 +01:00
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 ()
2018-02-27 19:51:43 +01:00
session [ 'is_admin' ] = is_admin [ 0 ]
2018-03-05 22:12:02 +01:00
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 ]
2018-02-26 10:41:52 +01:00
return True
return False
2018-02-27 19:51:43 +01:00
def register_user ( login , password , confirm ):
""" Register new user """
if password != confirm :
# Password does not match confirmation
print "[+] Password mismatch confirmation"
return False
check_user = Tetawebapp_users . query . filter_by ( mail = login ) . count ()
if check_user != 0 :
# User already exists
print "[+] User already exists"
return False
2018-03-05 22:12:02 +01:00
link_id = gen_token ( 20 )
2018-02-27 19:51:43 +01:00
hashed_password = bcrypt . hashpw ( password . encode ( 'utf-8' ), bcrypt . gensalt ())
2018-03-05 22:12:02 +01:00
user = Tetawebapp_users ( mail = login . encode ( 'utf8' ), password = hashed_password , link_id = link_id )
2018-02-27 19:51:43 +01:00
try :
db . session . add ( user )
commit = db . session . commit ()
except Exception as e :
db . session . rollback ()
print "[+] Error at register_user:"
print "------------------------------"
print " %s " % e . message
print "------------------------------"
return False
if commit != None :
2018-03-05 22:12:02 +01:00
print "[+] Error at register_user: commit was not None"
2018-02-27 19:51:43 +01:00
return False
2018-03-05 22:12:02 +01:00
send_mail ( login , link_id )
2018-02-27 19:51:43 +01:00
return True
2018-03-05 22:12:02 +01:00
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
2018-02-27 19:51:43 +01:00
def update_user ( login , password , confirm , name , phone , diet ):
""" Update user infos with provided data """
if password != confirm :
# Password does not match confirmation
print "[+] Password mismatch confirmation"
return False
check_user = Tetawebapp_users . query . filter_by ( mail = login ) . count ()
if check_user == 0 :
# User does not exist
print "[+] User does not exist"
return False
user = Tetawebapp_users . query . filter_by ( mail = login ) . first ()
if len ( password ) > 0 :
# User requested password modification
hashed_password = bcrypt . hashpw ( password , bcrypt . gensalt ())
setattr ( user , 'password' , hashed_password )
# Password has been updated if necessary
# Now let's update other data
setattr ( user , 'name' , name )
setattr ( user , 'phone' , phone )
setattr ( user , 'diet' , diet )
try :
db . session . add ( user )
commit = db . session . commit ()
except Exception as e :
db . session . rollback ()
print "[+] Error at update_user:"
print "------------------------------"
print " %s " % e . message
print "------------------------------"
return False
if commit != None :
return False
return True
def update_user_by_id ( user_id , login , password , confirm , name , phone , diet ):
""" Update user infos with provided data """
if password != confirm :
# Password does not match confirmation
print "[+] Password mismatch confirmation"
return False
check_user = Tetawebapp_users . query . filter_by ( id = user_id ) . count ()
if check_user == 0 :
# User does not exist
print "[+] User does not exist"
return False
user = Tetawebapp_users . query . filter_by ( id = user_id ) . first ()
if len ( password ) > 0 :
# User requested password modification
hashed_password = bcrypt . hashpw ( password , bcrypt . gensalt ())
setattr ( user , 'password' , hashed_password )
# Password has been updated if necessary
# Now let's update other data
setattr ( user , 'name' , name )
setattr ( user , 'phone' , phone )
setattr ( user , 'diet' , diet )
try :
db . session . add ( user )
commit = db . session . commit ()
except Exception as e :
db . session . rollback ()
2018-03-05 22:12:02 +01:00
print "[+] Error at update_user_by_id:"
2018-02-27 19:51:43 +01:00
print "------------------------------"
print " %s " % e . message
print "------------------------------"
return False
if commit != None :
return False
return True
def delete_user ( user_id ):
""" Delete user """
try :
Tetawebapp_users . query . filter_by ( id = int ( user_id )) . delete ()
db . session . commit ()
return True
except ValueError as e :
return False
except Exception as e :
db . session . rollback ()
print "[+] Error at delete_user:"
print "------------------------------"
print " %s " % e . message
print "------------------------------"
return False
2018-03-05 22:12:02 +01:00
def save_turn ( role_id , day , start , end , num_slot ):
2018-02-28 10:25:08 +01:00
""" Save a new turn """
2018-03-05 22:12:02 +01:00
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 )
2018-02-28 10:25:08 +01:00
turn = Tetawebapp_turns ( role_id = role_id . encode ( 'utf-8' ),
start_time = start . encode ( 'utf-8' ),
end_time = end . encode ( 'utf-8' ),
2018-03-05 22:12:02 +01:00
num_slot = num_slot . encode ( 'utf-8' ),
2018-02-28 10:25:08 +01:00
)
try :
db . session . add ( turn )
commit = db . session . commit ()
except Exception as e :
db . session . rollback ()
print "[+] Error at save_turn:"
print "------------------------------"
print " %s " % e . message
print "------------------------------"
return False
if commit != None :
return False
return True
2018-03-05 22:12:02 +01:00
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 ):
2018-02-28 14:30:31 +01:00
""" Update turn with provided data """
check_turn = Tetawebapp_turns . query . filter_by ( id = turn_id ) . count ()
if check_turn == 0 :
# User does not exist
2018-03-05 22:12:02 +01:00
print "[+] Turn does not exist"
2018-02-28 14:30:31 +01:00
return False
2018-03-05 22:12:02 +01:00
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 )
2018-02-28 14:30:31 +01:00
turn = Tetawebapp_turns . query . filter_by ( id = turn_id ) . first ()
setattr ( turn , 'role_id' , role_id )
setattr ( turn , 'start_time' , start )
setattr ( turn , 'end_time' , end )
2018-03-05 22:12:02 +01:00
setattr ( turn , 'num_slot' , num_slot )
2018-02-28 14:30:31 +01:00
try :
db . session . add ( turn )
commit = db . session . commit ()
except Exception as e :
db . session . rollback ()
print "[+] Error at update_turn:"
print "------------------------------"
print " %s " % e . message
print "------------------------------"
return False
if commit != None :
return False
return True
2018-02-28 10:25:08 +01:00
def drop_turn ( turn_id ):
""" Delete staff turn """
try :
Tetawebapp_turns . query . filter_by ( id = int ( turn_id )) . delete ()
db . session . commit ()
return True
except ValueError as e :
print e
return False
except Exception as e :
db . session . rollback ()
print "[+] Error at drop_turn:"
print "------------------------------"
print " %s " % e . message
print "------------------------------"
return False
2018-03-05 22:12:02 +01:00
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
2018-02-26 19:53:06 +01:00
def check_user_info ():
""" Check user info and send appropriate message if info are not complete"""
2018-02-27 19:51:43 +01:00
message = ''
user = Tetawebapp_users . query . filter_by ( mail = session [ 'login' ]) . first ()
name = user . name
phone = user . phone
diet = user . diet
if name == None or phone == None or diet == None or \
len ( name ) == 0 or len ( phone ) == 0 or len ( diet ) == 0 :
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'"
2018-02-26 19:53:06 +01:00
return message . decode ( 'utf-8' )
2018-03-05 22:12:02 +01:00
def gen_token ( size = 42 ):
2018-02-26 10:41:52 +01:00
""" Generate a random token to be stored in session and cookie """
2018-03-05 22:12:02 +01:00
token = binascii . hexlify ( os . urandom ( size ))
2018-02-26 10:41:52 +01:00
return token
2018-03-05 22:12:02 +01:00
def send_mail ( email , link_id ):
msg = Message ( "Confirmation d'inscription au staff THSF" ,
sender = "dave.null@tetalab.org" ,
recipients = [ email ])
msg . body = "Bonjour, \n Vous 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. \n Merci 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 )
2018-02-26 10:41:52 +01:00
########################################################################
# Routes:
# -------
# Except for the index function, the function name MUST have the same
# name than the URL endpoint to make the menu work properly
########################################################################
@app.errorhandler ( 404 )
def page_not_found ( e ):
""" 404 not found """
return render_template ( 'error.html' ), 404
@app.route ( "/login" , methods = [ 'GET' , 'POST' ])
def login ():
2018-02-28 10:25:08 +01:00
""" Login """
2018-02-27 19:51:43 +01:00
try :
login = request . form . get ( 'login' ) . encode ( 'utf-8' )
password = request . form . get ( 'password' ) . encode ( 'utf-8' )
if check_login ( login , password ):
# 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 ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" ))
session [ 'token' ] = ''
2018-03-05 22:12:02 +01:00
session [ 'login' ] = ''
session [ 'is_admin' ] = 0
2018-02-26 19:53:06 +01:00
sync_cookies ( response , session )
return response
2018-02-27 19:51:43 +01:00
except AttributeError :
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
2018-02-26 19:53:06 +01:00
2018-03-05 22:12:02 +01:00
@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 )
2018-02-26 19:53:06 +01:00
@app.route ( "/register" , methods = [ 'GET' , 'POST' ])
def register ():
2018-02-28 10:25:08 +01:00
""" Allow self registration """
2018-02-27 19:51:43 +01:00
try :
login = request . form . get ( 'login' ) . encode ( 'utf-8' )
password = request . form . get ( 'password' ) . encode ( 'utf-8' )
confirm = request . form . get ( 'confirm' ) . encode ( 'utf-8' )
message = "Erreur lors de l'enregsitrement: L'utilisateur existe t-il déjà ?" . decode ( 'utf-8' )
2018-03-05 22:12:02 +01:00
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' ))
2018-02-27 19:51:43 +01:00
except AttributeError :
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
2018-02-26 10:41:52 +01:00
@app.route ( "/" , methods = [ 'GET' , 'POST' ])
@check_session
def index ():
""" Index page """
page = str ( request . url_rule )
menu = get_menu ( page )
2018-02-26 19:53:06 +01:00
message = check_user_info ()
2018-02-27 19:51:43 +01:00
return render_template ( 'index.html' , menu = menu , message = message , login = session [ 'login' ])
2018-02-26 10:41:52 +01:00
2018-02-26 19:53:06 +01:00
@app.route ( "/account" , methods = [ 'GET' , 'POST' ])
2018-02-26 10:41:52 +01:00
@check_session
2018-02-26 19:53:06 +01:00
def account ():
2018-02-27 19:51:43 +01:00
""" Account page """
2018-02-26 10:41:52 +01:00
page = str ( request . url_rule )
menu = get_menu ( page )
2018-02-27 19:51:43 +01:00
user = Tetawebapp_users . query . filter_by ( mail = session [ 'login' ]) . first ()
mail = '' if user . mail == None else user . mail
name = '' if user . name == None else user . name
phone = '' if user . phone == None else user . phone
diet = '' if user . diet == None else user . diet
message = check_user_info ()
return render_template ( 'account.html' , menu = menu , mail = mail , name = name , phone = phone , diet = diet , message = message )
@app.route ( "/account/update" , methods = [ 'GET' , 'POST' ])
@check_session
def update_account ():
""" Update current account """
try :
page = str ( request . url_rule )
menu = get_menu ( page )
login = session [ 'login' ]
password = request . form . get ( 'password' ) . encode ( 'utf-8' )
confirm = request . form . get ( 'confirm' ) . encode ( 'utf-8' )
name = request . form . get ( 'name' ) . encode ( 'utf-8' )
phone = request . form . get ( 'phone' ) . encode ( 'utf-8' )
diet = request . form . get ( 'diet' ) . encode ( 'utf-8' )
if update_user ( login , password , confirm , name , phone , diet ):
message = check_user_info ()
else :
message = "Erreur lors de l'enregistrement des données."
return render_template ( 'account.html' ,
menu = menu ,
mail = login . decode ( 'utf-8' ),
name = name . decode ( 'utf-8' ),
phone = phone . decode ( 'utf-8' ),
diet = diet . decode ( 'utf-8' ),
message = message )
except AttributeError :
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
2018-02-28 10:25:08 +01:00
@app.route ( "/logout" , methods = [ 'GET' , 'POST' ])
@check_session
def logout ():
""" Logout user """
# Remove session token
session [ 'token' ] = None
session [ 'login' ] = None
session [ 'is_admin' ] = 0
# Return user to index page
response = app . make_response ( render_template ( 'login_or_register.html' , message = '' ))
# Push token to cookie
sync_cookies ( response , session )
return response
########################################################################
# Admin zone
########################################################################
2018-02-27 19:51:43 +01:00
@app.route ( "/users" , methods = [ 'GET' , 'POST' ])
@check_session
def list_users ():
""" Users list """
page = str ( request . url_rule )
menu = get_menu ( page )
message = check_user_info ()
staffers = Tetawebapp_users . query . filter_by ( is_admin = 0 ) . order_by ( Tetawebapp_users . name ) . all ()
return render_template ( 'list_users.html' , menu = menu , staffers = staffers , message = message )
2018-02-26 10:41:52 +01:00
2018-02-26 19:53:06 +01:00
@app.route ( "/account/<ID>" , methods = [ 'GET' , 'POST' ])
2018-02-26 10:41:52 +01:00
@check_session
2018-02-26 19:53:06 +01:00
def account_by_id ( ID ):
2018-02-26 10:41:52 +01:00
""" Arcticles page """
2018-02-27 19:51:43 +01:00
try :
if session [ 'is_admin' ]:
page = str ( request . url_rule )
menu = get_menu ( page )
2018-02-28 14:30:31 +01:00
message = "ID de l'utilisateur non conforme"
staffers = Tetawebapp_users . query . filter_by ( is_admin = 0 ) . order_by ( Tetawebapp_users . name ) . all ()
user_id = int ( ID . encode ( 'utf-8' ))
user = Tetawebapp_users . query . filter_by ( id = user_id ) . first ()
2018-02-27 19:51:43 +01:00
return render_template ( 'account_by_id.html' , menu = menu , user = user )
# User is not admin
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
except AttributeError :
# User is not logged in
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
2018-02-28 14:30:31 +01:00
except ValueError :
# ID is not an integer
return render_template ( 'list_users.html' , menu = menu , staffers = staffers , message = message )
2018-02-27 19:51:43 +01:00
@app.route ( "/account/update/<ID>" , methods = [ 'GET' , 'POST' ])
@check_session
def update_account_by_id ( ID ):
""" Update given account """
try :
if session [ 'is_admin' ]:
page = str ( request . url_rule )
menu = get_menu ( page )
login = session [ 'login' ]
password = request . form . get ( 'password' ) . encode ( 'utf-8' )
confirm = request . form . get ( 'confirm' ) . encode ( 'utf-8' )
name = request . form . get ( 'name' ) . encode ( 'utf-8' )
phone = request . form . get ( 'phone' ) . encode ( 'utf-8' )
diet = request . form . get ( 'diet' ) . encode ( 'utf-8' )
2018-02-28 14:30:31 +01:00
message = "ID de l'utilisateur non conforme"
staffers = Tetawebapp_users . query . filter_by ( is_admin = 0 ) . order_by ( Tetawebapp_users . name ) . all ()
user_id = int ( ID . encode ( 'utf-8' ))
if update_user_by_id ( user_id , login , password , confirm , name , phone , diet ):
2018-02-27 19:51:43 +01:00
user = Tetawebapp_users . query . filter_by ( id = ID ) . first ()
message = check_user_info ()
else :
message = "Erreur lors de l'enregistrement des données."
2018-02-28 14:30:31 +01:00
return render_template ( 'account_by_id.html' , menu = menu , user = user , message = message )
2018-02-27 19:51:43 +01:00
# User is not admin
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
except AttributeError :
# User is not logged in
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
2018-02-28 14:30:31 +01:00
except ValueError :
# ID is not an integer
return render_template ( 'list_users.html' , menu = menu , staffers = staffers , message = message )
2018-02-27 19:51:43 +01:00
@app.route ( "/account/delete/<ID>" , methods = [ 'GET' , 'POST' ])
@check_session
def delete_account ( ID ):
""" Delete given account """
try :
if session [ 'is_admin' ]:
message = "Erreur lors de la suppression." . decode ( 'utf-8' )
page = str ( request . url_rule )
menu = get_menu ( page )
staffers = Tetawebapp_users . query . filter_by ( is_admin = 0 ) . order_by ( Tetawebapp_users . name ) . all ()
2018-02-28 14:30:31 +01:00
user_id = int ( ID . encode ( 'utf-8' ))
if delete_user ( user_id ):
message = ''
staffers = Tetawebapp_users . query . filter_by ( is_admin = 0 ) . order_by ( Tetawebapp_users . name ) . all ()
2018-02-27 19:51:43 +01:00
return render_template ( 'list_users.html' , menu = menu , staffers = staffers , message = message )
# User is not admin
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
except AttributeError :
# User is not logged in
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
2018-02-28 14:30:31 +01:00
except ValueError :
# ID is not an integer
return render_template ( 'list_users.html' , menu = menu , staffers = staffers , message = message )
2018-02-26 19:53:06 +01:00
2018-02-28 10:25:08 +01:00
@app.route ( "/turns" , methods = [ 'GET' , 'POST' ])
2018-02-26 19:53:06 +01:00
@check_session
2018-03-05 22:12:02 +01:00
def list_turns ():
2018-02-28 10:25:08 +01:00
""" List staff turns """
try :
2018-03-05 22:12:02 +01:00
page = str ( request . url_rule )
menu = get_menu ( page )
message = ''
2018-02-28 10:25:08 +01:00
if session [ 'is_admin' ]:
page = str ( request . url_rule )
menu = get_menu ( page )
2018-03-05 22:12:02 +01:00
turns = turns_list ()
2018-02-28 10:25:08 +01:00
message = ''
return render_template ( 'list_turns.html' , menu = menu , page = page , turns = turns , message = message )
2018-03-05 22:12:02 +01:00
# TODO:
# Here comes the list_turns_by_user_id code
2018-02-28 10:25:08 +01:00
except AttributeError :
# User is not logged in
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
@app.route ( "/turn/new" , methods = [ 'GET' , 'POST' ])
@check_session
def new_turn ():
""" New turn form """
2018-03-05 22:12:02 +01:00
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'
2018-02-28 10:25:08 +01:00
try :
if session [ 'is_admin' ]:
page = str ( request . url_rule )
menu = get_menu ( page )
roles = Tetawebapp_roles . query . order_by ( Tetawebapp_roles . id ) . all ()
2018-03-05 22:12:02 +01:00
days = [( 'Mardi' , tuesday ), ( 'Mercredi' , wenesday ), ( 'Jeudi' , thirsday ), ( 'Vendredi' , friday ), ( 'Samedi' , saturday ), ( 'Dimanche' , sunday )]
2018-02-28 10:25:08 +01:00
return render_template ( 'new_turn.html' , menu = menu , page = page , roles = roles , days = days )
except AttributeError :
# User is not logged in
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
@app.route ( "/turn/add" , methods = [ 'GET' , 'POST' ])
@check_session
def add_turn ():
""" Add staff turn """
try :
if session [ 'is_admin' ]:
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' )
2018-03-05 22:12:02 +01:00
num_slot = request . form . get ( 'num_slot' ) . encode ( 'utf-8' )
2018-02-28 10:25:08 +01:00
page = str ( request . url_rule )
menu = get_menu ( page )
2018-03-05 22:12:02 +01:00
turns = turns_list ()
2018-02-28 10:25:08 +01:00
message = "Erreur lors de l'enregistrement." . decode ( 'utf-8' )
2018-03-05 22:12:02 +01:00
if save_turn ( role_id , day , start , end , num_slot ):
turns = turns_list ()
2018-02-28 10:25:08 +01:00
message = ''
return render_template ( 'list_turns.html' , menu = menu , page = page , turns = turns , message = message )
# User is not admin
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
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 ( "/turn/<ID>" , methods = [ 'GET' , 'POST' ])
@check_session
2018-02-28 14:30:31 +01:00
def turn_by_id ( ID ):
try :
if session [ 'is_admin' ]:
2018-03-05 22:12:02 +01:00
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 )]
2018-02-28 14:30:31 +01:00
page = str ( request . url_rule )
menu = get_menu ( page )
roles = Tetawebapp_roles . query . order_by ( Tetawebapp_roles . id ) . all ()
message = 'ID du tour de staff non conforme'
2018-03-05 22:12:02 +01:00
turns = turns_list ()
2018-02-28 14:30:31 +01:00
turn_id = int ( ID . encode ( 'utf-8' ))
2018-03-05 22:12:02 +01:00
turn = get_turn_by_id ( turn_id )
2018-02-28 14:30:31 +01:00
return render_template ( 'turn_by_id.html' , menu = menu , page = page , turn = turn , roles = roles , days = days )
except AttributeError :
# User is not logged in
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
except ValueError :
# ID is not an integer
return render_template ( 'list_turns.html' , menu = menu , page = page , turns = turns , message = message )
2018-02-26 19:53:06 +01:00
2018-02-28 14:30:31 +01:00
@app.route ( "/turn/update/<ID>" , methods = [ 'GET' , 'POST' ])
@check_session
def update_turn ( ID ):
""" Update given staff turn """
try :
role_id = request . form . get ( 'role_id' ) . encode ( 'utf-8' )
start = request . form . get ( 'start' ) . encode ( 'utf-8' )
end = request . form . get ( 'end' ) . encode ( 'utf-8' )
2018-03-05 22:12:02 +01:00
num_slot = request . form . get ( 'num_slot' ) . encode ( 'utf-8' )
day = request . form . get ( 'day' ) . encode ( 'utf-8' )
2018-02-28 14:30:31 +01:00
if session [ 'is_admin' ]:
page = str ( request . url_rule )
menu = get_menu ( page )
2018-03-05 22:12:02 +01:00
turns = turns_list ()
2018-02-28 14:30:31 +01:00
message = "Erreur lors de l'enregistrement." . decode ( 'utf-8' )
turn_id = int ( ID . encode ( 'utf-8' ))
2018-03-05 22:12:02 +01:00
if update_turn_by_id ( turn_id , role_id , day , start , end , num_slot ):
turns = turns_list ()
2018-02-28 14:30:31 +01:00
message = ''
return render_template ( 'list_turns.html' , menu = menu , page = page , turns = turns , message = message )
# User is not admin
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
except AttributeError as e :
# User is not logged in
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
except ValueError :
# ID is not an integer
return render_template ( 'list_turns.html' , menu = menu , page = page , turns = turns , message = message )
2018-02-26 19:53:06 +01:00
2018-02-28 10:25:08 +01:00
@app.route ( "/turn/delete/<ID>" , methods = [ 'GET' , 'POST' ])
@check_session
def delete_turn ( ID ):
""" Delete given staff turn """
try :
if session [ 'is_admin' ]:
message = 'Erreur lors de la suppression.'
page = str ( request . url_rule )
menu = get_menu ( page )
2018-03-05 22:12:02 +01:00
turns = turns_list ()
2018-02-28 14:30:31 +01:00
turn_id = int ( ID . encode ( 'utf-8' ))
if drop_turn ( turn_id ):
2018-02-28 10:25:08 +01:00
message = ''
2018-03-05 22:12:02 +01:00
turns = turns_list ()
2018-02-28 10:25:08 +01:00
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
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
except AttributeError :
# User is not logged in
return render_template ( 'login_or_register.html' , message = "Utilisateur ou mot de passe invalide" )
2018-02-28 14:30:31 +01:00
except ValueError :
# ID is not an integer
return render_template ( 'list_turns.html' , menu = menu , page = page , turns = turns , message = message )
2018-02-26 10:41:52 +01:00
2018-03-05 22:12:02 +01:00
@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 ( " " , 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" )
2018-02-26 10:41:52 +01:00
########################################################################
# Main
########################################################################
if __name__ == '__main__' :
app . run ( host = '0.0.0.0' )