2018-02-26 20:41:52 +11:00
#!/usr/bin/env python
# -*- coding: utf-8
# Required modules
import os
import inspect
import random
import binascii
import bcrypt
2018-03-06 08:12:02 +11: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 20:41:52 +11:00
from functools import wraps
2018-03-06 08:12:02 +11:00
import cStringIO
from flask_mail import Mail , Message
2018-02-26 20:41:52 +11:00
# Optionnal modules
import psycopg2
from flask_sqlalchemy import SQLAlchemy
########################################################################
# App settings
########################################################################
app = Flask ( __name__ )
2018-03-06 08:12:02 +11:00
mail = Mail ( app )
# Jinja2 loopcontrols extension
app . jinja_env . add_extension ( ' jinja2.ext.loopcontrols ' )
2018-02-26 20:41:52 +11: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-27 05:53:06 +11:00
app . secret_key = ' 9ac80548e3a8d8dfd1aefcd9a3a73473 '
2018-02-26 20:41:52 +11:00
# Feel free to use SQLAlchemy (or not)
db = SQLAlchemy ( app )
2018-03-06 08:12:02 +11:00
2018-02-26 20:41:52 +11:00
########################################################################
# Sample user database
########################################################################
class Tetawebapp_users ( db . Model ) :
2018-02-27 05:53:06 +11:00
__tablename__ = ' participer_thsf_users '
2018-02-26 20:41:52 +11: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-27 05:53:06 +11:00
name = db . Column ( db . Text , nullable = True )
phone = db . Column ( db . Text , nullable = True )
diet = db . Column ( db . Text , nullable = True )
2018-02-28 05:51:43 +11:00
is_admin = db . Column ( db . Integer , nullable = False , default = 0 )
2018-03-06 08:12:02 +11:00
link_id = db . Column ( db . Text , nullable = True )
2018-02-26 20:41:52 +11:00
2018-02-27 05:53:06 +11: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 20:41:52 +11:00
2018-02-28 05:51:43 +11: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-06 08:12:02 +11: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-28 05:51:43 +11:00
2018-02-26 20:41:52 +11: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-27 05:53:06 +11:00
menu = [ [ u ' Accueil ' , { u ' / ' : [ u ' / ' ] } , 0 ] ,
2018-02-28 05:51:43 +11:00
[ u ' Mon compte ' , { u ' /account ' : [ u ' /account ' , u ' /account/update ' ] } , 0 ] ,
2018-03-06 08:12:02 +11: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-28 05:51:43 +11:00
[ u ' Déconnexion ' , { u ' /logout ' : [ u ' /logout ' ] } , 0 ] ,
]
if session [ ' is_admin ' ] :
menu = [ [ u ' Accueil ' , { u ' / ' : [ u ' / ' ] } , 0 ] ,
2018-02-28 20:25:08 +11: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-06 08:12:02 +11: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 20:25:08 +11:00
[ u ' Liste des staffers ' , { u ' /users ' : [ u ' /users ' , u ' /account/<ID> ' , u ' /account/delete/<ID> ' ] } , 0 ] ,
2018-02-27 05:53:06 +11:00
[ u ' Déconnexion ' , { u ' /logout ' : [ u ' /logout ' ] } , 0 ] ,
2018-02-26 20:41:52 +11:00
]
2018-02-28 20:25:08 +11:00
#~ print '[+] Page: %s' % page
2018-02-26 20:41:52 +11:00
for item in menu :
for url in item [ 1 ] :
for route in item [ 1 ] [ url ] :
2018-02-28 20:25:08 +11:00
#~ print " [+] Route: %s" %route
2018-02-26 20:41:52 +11:00
if route == page :
2018-02-28 20:25:08 +11:00
#~ print " [+] Selected page: %s" % page
2018-02-26 20:41:52 +11: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-28 05:51:43 +11:00
# User is logged in and identified
2018-02-26 20:41:52 +11:00
return func ( * args , * * kwargs )
else :
2018-02-28 05:51:43 +11:00
# User is not logged in or session expired
2018-02-26 20:41:52 +11:00
session [ ' token ' ] = ' '
2018-02-27 05:53:06 +11:00
response = app . make_response ( render_template ( ' login_or_register.html ' , message = ' ' ) )
2018-02-26 20:41:52 +11:00
sync_cookies ( response , session )
return response
except KeyError :
2018-02-28 05:51:43 +11:00
# User is not logged in
2018-02-27 05:53:06 +11:00
return render_template ( ' login_or_register.html ' , message = ' ' )
2018-02-26 20:41:52 +11:00
return check
2018-03-09 20:33:29 +11:00
def gen_token ( size = 42 ) :
""" Generate a random token to be stored in session and cookie """
token = binascii . hexlify ( os . urandom ( size ) )
return token
########################################################################
# User management
########################################################################
2018-02-26 20:41:52 +11:00
def check_login ( login , password ) :
""" Puts the login verification code here """
hashed_password = bcrypt . hashpw ( password , bcrypt . gensalt ( ) )
2018-03-06 08:12:02 +11: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 20:41:52 +11:00
if stored_hash :
if bcrypt . checkpw ( password , stored_hash [ 0 ] . encode ( ' utf-8 ' ) ) :
2018-03-06 08:12:02 +11: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-28 05:51:43 +11:00
session [ ' is_admin ' ] = is_admin [ 0 ]
2018-03-06 08:12:02 +11: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 20:41:52 +11:00
return True
return False
2018-02-28 05:51:43 +11: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-06 08:12:02 +11:00
link_id = gen_token ( 20 )
2018-02-28 05:51:43 +11:00
hashed_password = bcrypt . hashpw ( password . encode ( ' utf-8 ' ) , bcrypt . gensalt ( ) )
2018-03-06 08:12:02 +11:00
user = Tetawebapp_users ( mail = login . encode ( ' utf8 ' ) , password = hashed_password , link_id = link_id )
2018-02-28 05:51:43 +11: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-06 08:12:02 +11:00
print " [+] Error at register_user: commit was not None "
2018-02-28 05:51:43 +11:00
return False
2018-03-06 08:12:02 +11:00
send_mail ( login , link_id )
2018-02-28 05:51:43 +11:00
return True
2018-03-06 08:12:02 +11:00
def confirm_user ( login , password , link_id ) :
2018-03-09 20:33:29 +11:00
""" Confirm user by setting link_id == None """
2018-03-06 08:12:02 +11:00
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-28 05:51:43 +11: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-06 08:12:02 +11:00
print " [+] Error at update_user_by_id: "
2018-02-28 05:51:43 +11:00
print " ------------------------------ "
print " %s " % e . message
print " ------------------------------ "
return False
if commit != None :
return False
return True
2018-04-06 20:01:39 +11:00
def reset_password ( login , password , confirm ) :
if password != confirm :
# Password does not match confirmation
print " [+] [Reset password] Password mismatch confirmation "
return False
check_user = Tetawebapp_users . query . filter_by ( mail = login ) . count ( )
if check_user == 0 :
# User does not exist
print " [+] [Reset password] 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 )
# We also ask for a new account confirmation
link_id = gen_token ( 20 )
setattr ( user , ' link_id ' , link_id )
try :
db . session . add ( user )
commit = db . session . commit ( )
send_reset_mail ( login , link_id )
except Exception as e :
db . session . rollback ( )
print " [+] Error at reset_password: "
print " ------------------------------ "
print " %s " % e . message
print " ------------------------------ "
return False
if commit != None :
return False
return True
2018-02-28 05:51:43 +11:00
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-07 02:07:47 +11:00
def get_user_name ( user_id ) :
""" Get pseudo from user ID """
try :
user = Tetawebapp_users . query . filter_by ( id = int ( user_id ) ) . first ( )
return user . name
except Exception as e :
print " [+] Error at get_pseudo: "
print " ------------------------------ "
print " %s " % e . message
print " ------------------------------ "
return False
2018-03-09 20:33:29 +11:00
def check_user_info ( ) :
""" Check user info and send appropriate message if info are not complete """
message = ' '
user = Tetawebapp_users . query . filter_by ( mail = session [ ' login ' ] ) . first ( )
name = user . name
phone = user . phone
diet = user . diet
2018-03-14 01:22:40 +11:00
if name == None or phone == None or \
len ( name ) == 0 or len ( phone ) == 0 :
2018-03-09 20:33:29 +11:00
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 ' )
########################################################################
# Turns
########################################################################
2018-03-07 02:07:47 +11:00
2018-03-06 08:12:02 +11:00
def save_turn ( role_id , day , start , end , num_slot ) :
2018-02-28 20:25:08 +11:00
""" Save a new turn """
2018-03-06 08:12:02 +11: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 20:25:08 +11: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-06 08:12:02 +11:00
num_slot = num_slot . encode ( ' utf-8 ' ) ,
2018-02-28 20:25:08 +11: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-06 08:12:02 +11: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-03-01 00:30:31 +11: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-06 08:12:02 +11:00
print " [+] Turn does not exist "
2018-03-01 00:30:31 +11:00
return False
2018-03-06 08:12:02 +11: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-03-01 00:30:31 +11: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-06 08:12:02 +11:00
setattr ( turn , ' num_slot ' , num_slot )
2018-03-01 00:30:31 +11: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 20:25:08 +11: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-06 08:12:02 +11: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 ( )
2018-03-14 01:40:23 +11:00
turns . append ( ( ' Mardi 08/05 ' , tuesday_turns ) )
turns . append ( ( ' Mercredi 09/05 ' , wenesday_turns ) )
turns . append ( ( ' Jeudi 10/05 ' , thirsday_turns ) )
turns . append ( ( ' Vendredi 11/05 ' , friday_turns ) )
turns . append ( ( ' Samedi 12/05 ' , saturday_turns ) )
turns . append ( ( ' Dimanche 13/05 ' , sunday_turns ) )
2018-03-06 08:12:02 +11:00
return turns
2018-03-09 20:33:29 +11:00
########################################################################
# Staffs
########################################################################
2018-03-06 08:12:02 +11:00
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 """
2018-03-06 11:56:10 +11:00
slot = Tetawebapp_staffs . query . filter ( Tetawebapp_staffs . turn_id == turn_id , Tetawebapp_staffs . slot_num == slot_id ) . count ( )
if slot == 0 :
2018-03-10 10:13:54 +11:00
slot = Tetawebapp_staffs . query . filter ( Tetawebapp_staffs . turn_id == turn_id , Tetawebapp_staffs . user_id == user_id ) . count ( )
if slot == 0 :
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
2018-03-08 01:43:20 +11:00
return False
2018-03-06 08:12:02 +11:00
2018-03-14 23:16:13 +11:00
def check_user_availability ( turn_id , user_id ) :
""" Check if user is available for this turn """
turn_start , turn_end = Tetawebapp_turns . query . filter ( Tetawebapp_turns . id == turn_id ) . with_entities ( Tetawebapp_turns . start_time , Tetawebapp_turns . end_time ) . first ( )
user_turns = Tetawebapp_staffs . query . filter ( Tetawebapp_staffs . user_id == user_id ) . with_entities ( Tetawebapp_staffs . turn_id ) . all ( )
for turn in user_turns :
t_start , t_end = Tetawebapp_staffs . query . filter ( Tetawebapp_turns . id == turn [ 0 ] ) . with_entities ( Tetawebapp_turns . start_time , Tetawebapp_turns . end_time ) . first ( )
if t_start < = turn_start and t_end > turn_start :
return False
if t_start > = turn_start and t_start < turn_end :
return False
return True
2018-03-09 20:33:29 +11:00
########################################################################
# Role
########################################################################
2018-03-06 08:12:02 +11:00
def get_roles ( ) :
""" Get full roles list """
try :
roles = Tetawebapp_roles . query . filter ( Tetawebapp_roles . id > 3 ) . all ( )
return roles
except Exception as e :
2018-03-08 01:43:20 +11:00
print " [+] Error at get_roles: "
2018-03-06 08:12:02 +11:00
print " ------------------------------ "
print " %s " % e . message
print " ------------------------------ "
return False
2018-03-09 20:33:29 +11:00
########################################################################
# Mail
########################################################################
2018-02-26 20:41:52 +11:00
2018-03-06 08:12:02 +11:00
def send_mail ( email , link_id ) :
2018-04-06 20:01:39 +11:00
msg = Message ( " [THSF] Confirmation d ' inscription au staff THSF " ,
2018-03-06 08:12:02 +11:00
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 "
2018-03-06 08:25:19 +11:00
msg . body + = " %s /confirm/ %s \n \n " % ( str ( app . config [ ' DOMAIN_URL ' ] ) , str ( link_id ) )
2018-03-06 08:12:02 +11:00
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-04-06 20:01:39 +11:00
def send_reset_mail ( email , link_id ) :
msg = Message ( " [THSF] Confirmation de réinitialisation de votre mot de passe " ,
sender = " dave.null@tetalab.org " ,
recipients = [ email ] )
msg . body = " Bonjour, \n Vous recevez ce courriel car vous avez demandé la réinitialisation de votre mot de passe. \n \n "
msg . body + = " Pour confirmer votre noueau mot de passe, rendez vous à la page suivante: \n "
msg . body + = " %s /confirm/ %s \n \n " % ( str ( app . config [ ' DOMAIN_URL ' ] ) , str ( link_id ) )
msg . body + = " Si vous n ' êtes pas à l ' origine de cette demande de réinitialisation, envoyez un email à contact@tetalab.org afin que soient prises les dispositions nécessaires. \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 20:41:52 +11: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
2018-03-09 20:33:29 +11:00
########################################################################
# Entry
########################################################################
@app.route ( " / " , methods = [ ' GET ' , ' POST ' ] )
@check_session
def index ( ) :
""" Index page """
page = str ( request . url_rule )
menu = get_menu ( page )
message = check_user_info ( )
return render_template ( ' index.html ' , menu = menu , message = message , login = session [ ' login ' ] )
########################################################################
# Session
########################################################################
2018-02-26 20:41:52 +11:00
@app.route ( " /login " , methods = [ ' GET ' , ' POST ' ] )
def login ( ) :
2018-02-28 20:25:08 +11:00
""" Login """
2018-02-28 05:51:43 +11: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-06 08:12:02 +11:00
session [ ' login ' ] = ' '
session [ ' is_admin ' ] = 0
2018-02-27 05:53:06 +11:00
sync_cookies ( response , session )
return response
2018-02-28 05:51:43 +11:00
except AttributeError :
return render_template ( ' login_or_register.html ' , message = " Utilisateur ou mot de passe invalide " )
2018-02-27 05:53:06 +11:00
2018-03-09 20:33:29 +11:00
########################################################################
# User
########################################################################
2018-03-06 08:12:02 +11: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 """
2018-02-28 05:51:43 +11:00
try :
2018-03-06 08:12:02 +11:00
link_id = LINK_ID . encode ( ' utf-8 ' )
2018-02-28 05:51:43 +11:00
login = request . form . get ( ' login ' ) . encode ( ' utf-8 ' )
password = request . form . get ( ' password ' ) . encode ( ' utf-8 ' )
2018-03-06 08:12:02 +11:00
if check_confirm ( login , password , link_id ) and confirm_user ( login , password , link_id ) :
2018-02-28 05:51:43 +11:00
# 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 ( )
2018-03-06 08:12:02 +11:00
response = app . make_response ( render_template ( ' index.html ' , menu = menu , message = message , login = login ) )
2018-02-28 05:51:43 +11:00
# Push token to cookie
sync_cookies ( response , session )
return response
2018-03-06 08:12:02 +11:00
# Credentials are not valid
response = app . make_response ( render_template ( ' confirm.html ' , message = " Utilisateur ou mot de passe invalide " , link_id = link_id ) )
2018-02-28 05:51:43 +11:00
session [ ' token ' ] = ' '
2018-03-06 08:12:02 +11:00
session [ ' login ' ] = ' '
session [ ' is_admin ' ] = 0
2018-02-26 20:41:52 +11:00
sync_cookies ( response , session )
return response
2018-03-06 08:12:02 +11:00
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 """
try :
2018-04-23 19:54:04 +11:00
login = request . form . get ( ' login ' ) . lower ( ) . encode ( ' utf-8 ' )
2018-03-06 08:12:02 +11:00
password = request . form . get ( ' password ' ) . encode ( ' utf-8 ' )
confirm = request . form . get ( ' confirm ' ) . encode ( ' utf-8 ' )
2018-05-03 18:05:54 +11:00
message = " Erreur lors de l ' enregsitrement: L ' utilisateur existe t-il déjà ? "
2018-03-06 08:12:02 +11: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-28 05:51:43 +11:00
except AttributeError :
return render_template ( ' login_or_register.html ' , message = " Utilisateur ou mot de passe invalide " )
2018-02-26 20:41:52 +11:00
2018-02-27 05:53:06 +11:00
@app.route ( " /account " , methods = [ ' GET ' , ' POST ' ] )
2018-02-26 20:41:52 +11:00
@check_session
2018-02-27 05:53:06 +11:00
def account ( ) :
2018-02-28 05:51:43 +11:00
""" Account page """
2018-02-26 20:41:52 +11:00
page = str ( request . url_rule )
menu = get_menu ( page )
2018-02-28 05:51:43 +11: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-04-06 20:01:39 +11:00
@app.route ( " /account/reset/ask " , methods = [ ' GET ' , ' POST ' ] )
def ask_reset ( ) :
""" Ask for password reset page """
return render_template ( ' reset_password.html ' )
@app.route ( " /account/reset " , methods = [ ' GET ' , ' POST ' ] )
def reset_account ( ) :
""" Password reset """
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 ' )
if reset_password ( login , password , confirm ) :
message = " Une confirmation de la réinitialisation de votre mot de passe vous a été envoyé par email "
return render_template ( ' login_or_register.html ' , message = message . decode ( ' utf-8 ' ) )
message = " Erreur lors de la réinitialisation du mot de passe "
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 " )
2018-02-28 20:25:08 +11: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
2018-03-09 20:33:29 +11:00
########################################################################
# Staffsheet
########################################################################
@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 ' ]
if ( drop_staff_slot ( turn_id , slot_id , user_id ) ) :
return " "
return " KO "
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 ' ]
user_name = get_user_name ( user_id )
if user_name != None :
2018-03-14 23:16:13 +11:00
if check_user_availability ( turn_id , user_id ) :
if ( save_staff_slot ( turn_id , slot_id , user_id ) ) :
return user_name
2018-03-09 20:33:29 +11:00
return " KO "
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-28 20:25:08 +11:00
########################################################################
# Admin zone
########################################################################
2018-02-28 05:51:43 +11: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 ( )
2018-04-08 22:41:50 +11:00
staffers = Tetawebapp_users . query . filter ( Tetawebapp_users . is_admin == 0 , Tetawebapp_users . link_id == None ) . order_by ( Tetawebapp_users . name ) . all ( )
2018-02-28 05:51:43 +11:00
return render_template ( ' list_users.html ' , menu = menu , staffers = staffers , message = message )
2018-02-26 20:41:52 +11:00
2018-02-27 05:53:06 +11:00
@app.route ( " /account/<ID> " , methods = [ ' GET ' , ' POST ' ] )
2018-02-26 20:41:52 +11:00
@check_session
2018-02-27 05:53:06 +11:00
def account_by_id ( ID ) :
2018-02-26 20:41:52 +11:00
""" Arcticles page """
2018-02-28 05:51:43 +11:00
try :
if session [ ' is_admin ' ] :
page = str ( request . url_rule )
menu = get_menu ( page )
2018-03-01 00:30:31 +11: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-28 05:51:43 +11: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-03-01 00:30:31 +11:00
except ValueError :
# ID is not an integer
return render_template ( ' list_users.html ' , menu = menu , staffers = staffers , message = message )
2018-02-28 05:51:43 +11: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-03-01 00:30:31 +11: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-28 05:51:43 +11: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-03-01 00:30:31 +11:00
return render_template ( ' account_by_id.html ' , menu = menu , user = user , message = message )
2018-02-28 05:51:43 +11: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-03-01 00:30:31 +11:00
except ValueError :
# ID is not an integer
return render_template ( ' list_users.html ' , menu = menu , staffers = staffers , message = message )
2018-02-28 05:51:43 +11: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-03-01 00:30:31 +11: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-28 05:51:43 +11: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-03-01 00:30:31 +11:00
except ValueError :
# ID is not an integer
return render_template ( ' list_users.html ' , menu = menu , staffers = staffers , message = message )
2018-02-27 05:53:06 +11:00
2018-03-09 20:33:29 +11:00
########################################################################
# Turns
########################################################################
2018-02-28 20:25:08 +11:00
@app.route ( " /turns " , methods = [ ' GET ' , ' POST ' ] )
2018-02-27 05:53:06 +11:00
@check_session
2018-03-06 08:12:02 +11:00
def list_turns ( ) :
2018-02-28 20:25:08 +11:00
""" List staff turns """
try :
2018-03-06 08:12:02 +11:00
page = str ( request . url_rule )
menu = get_menu ( page )
message = ' '
2018-02-28 20:25:08 +11:00
if session [ ' is_admin ' ] :
page = str ( request . url_rule )
menu = get_menu ( page )
2018-03-06 08:12:02 +11:00
turns = turns_list ( )
2018-02-28 20:25:08 +11:00
message = ' '
return render_template ( ' list_turns.html ' , menu = menu , page = page , turns = turns , message = message )
2018-03-06 08:12:02 +11:00
# TODO:
# Here comes the list_turns_by_user_id code
2018-02-28 20:25:08 +11:00
except AttributeError :
# User is not logged in
return render_template ( ' login_or_register.html ' , message = " Utilisateur ou mot de passe invalide " )
2018-02-27 05:53:06 +11:00
2018-02-28 20:25:08 +11:00
@app.route ( " /turn/new " , methods = [ ' GET ' , ' POST ' ] )
@check_session
def new_turn ( ) :
""" New turn form """
2018-03-06 08:12:02 +11: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 20:25:08 +11: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-06 08:12:02 +11:00
days = [ ( ' Mardi ' , tuesday ) , ( ' Mercredi ' , wenesday ) , ( ' Jeudi ' , thirsday ) , ( ' Vendredi ' , friday ) , ( ' Samedi ' , saturday ) , ( ' Dimanche ' , sunday ) ]
2018-02-28 20:25:08 +11: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 " )
2018-02-27 05:53:06 +11:00
2018-02-28 20:25:08 +11:00
@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-06 08:12:02 +11:00
num_slot = request . form . get ( ' num_slot ' ) . encode ( ' utf-8 ' )
2018-02-28 20:25:08 +11:00
page = str ( request . url_rule )
menu = get_menu ( page )
2018-03-06 08:12:02 +11:00
turns = turns_list ( )
2018-02-28 20:25:08 +11:00
message = " Erreur lors de l ' enregistrement. " . decode ( ' utf-8 ' )
2018-03-06 08:12:02 +11:00
if save_turn ( role_id , day , start , end , num_slot ) :
turns = turns_list ( )
2018-02-28 20:25:08 +11: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 " )
2018-02-27 05:53:06 +11:00
2018-02-28 20:25:08 +11:00
@app.route ( " /turn/<ID> " , methods = [ ' GET ' , ' POST ' ] )
@check_session
2018-03-01 00:30:31 +11:00
def turn_by_id ( ID ) :
try :
if session [ ' is_admin ' ] :
2018-03-06 08:12:02 +11: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-03-01 00:30:31 +11: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-06 08:12:02 +11:00
turns = turns_list ( )
2018-03-01 00:30:31 +11:00
turn_id = int ( ID . encode ( ' utf-8 ' ) )
2018-03-06 08:12:02 +11:00
turn = get_turn_by_id ( turn_id )
2018-03-01 00:30:31 +11: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 )
@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-06 08:12:02 +11:00
num_slot = request . form . get ( ' num_slot ' ) . encode ( ' utf-8 ' )
day = request . form . get ( ' day ' ) . encode ( ' utf-8 ' )
2018-03-01 00:30:31 +11:00
if session [ ' is_admin ' ] :
page = str ( request . url_rule )
menu = get_menu ( page )
2018-03-06 08:12:02 +11:00
turns = turns_list ( )
2018-03-01 00:30:31 +11:00
message = " Erreur lors de l ' enregistrement. " . decode ( ' utf-8 ' )
turn_id = int ( ID . encode ( ' utf-8 ' ) )
2018-03-06 08:12:02 +11:00
if update_turn_by_id ( turn_id , role_id , day , start , end , num_slot ) :
turns = turns_list ( )
2018-03-01 00:30:31 +11: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-28 20:25:08 +11: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-06 08:12:02 +11:00
turns = turns_list ( )
2018-03-01 00:30:31 +11:00
turn_id = int ( ID . encode ( ' utf-8 ' ) )
if drop_turn ( turn_id ) :
2018-02-28 20:25:08 +11:00
message = ' '
2018-03-06 08:12:02 +11:00
turns = turns_list ( )
2018-02-28 20:25:08 +11: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-03-01 00:30:31 +11: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 20:41:52 +11:00
########################################################################
# Main
########################################################################
if __name__ == ' __main__ ' :
app . run ( host = ' 0.0.0.0 ' )