L'application de gestion du staff du THSF: https://participer.thsf.net
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

participate.py 54KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8
  3. # Required modules
  4. import os
  5. import inspect
  6. import random
  7. import binascii
  8. import bcrypt
  9. import datetime
  10. import ast
  11. from reportlab.lib import colors
  12. from reportlab.lib.enums import TA_LEFT, TA_CENTER
  13. from reportlab.lib.pagesizes import A4, cm, portrait
  14. from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, PageBreak, Indenter
  15. from reportlab.lib.colors import black, white, orange, bisque, lightsalmon
  16. from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
  17. from flask import Flask, request, session, g, redirect, url_for, abort, render_template, flash, send_file
  18. from functools import wraps
  19. import cStringIO
  20. from flask_mail import Mail, Message
  21. # Optionnal modules
  22. import psycopg2
  23. from flask_sqlalchemy import SQLAlchemy
  24. ########################################################################
  25. # App settings
  26. ########################################################################
  27. app = Flask(__name__)
  28. mail = Mail(app)
  29. # Jinja2 loopcontrols extension
  30. app.jinja_env.add_extension('jinja2.ext.loopcontrols')
  31. # Path to static files
  32. app.static_url_path='/static'
  33. # Set debug mode to False for production
  34. app.debug = True
  35. # Various configuration settings belong here (optionnal)
  36. app.config.from_pyfile('config.local.py')
  37. # Generate a new key: head -n 40 /dev/urandom | md5sum | cut -d' ' -f1
  38. app.secret_key = '9ac80548e3a8d8dfd1aefcd9a3a73473'
  39. # Feel free to use SQLAlchemy (or not)
  40. db = SQLAlchemy(app)
  41. ########################################################################
  42. # Sample user database
  43. ########################################################################
  44. class Tetawebapp_users(db.Model):
  45. __tablename__ = 'participer_thsf_users'
  46. id = db.Column(db.Integer, primary_key=True)
  47. mail = db.Column(db.Text, nullable=False)
  48. password = db.Column(db.Text, nullable=False)
  49. name = db.Column(db.Text, nullable=True)
  50. phone = db.Column(db.Text, nullable=True)
  51. diet = db.Column(db.Text, nullable=True)
  52. is_admin = db.Column(db.Integer, nullable=False, default=0)
  53. link_id = db.Column(db.Text, nullable=True)
  54. class Tetawebapp_roles(db.Model):
  55. __tablename__ = 'participer_thsf_roles'
  56. id = db.Column(db.Integer, primary_key=True)
  57. role = db.Column(db.Text, nullable=False)
  58. description = db.Column(db.Text, nullable=False)
  59. class Tetawebapp_turns(db.Model):
  60. __tablename__ = 'participer_thsf_turns'
  61. id = db.Column(db.Integer, primary_key=True)
  62. role_id = db.Column(db.Integer, db.ForeignKey('participer_thsf_roles.id'), nullable=False)
  63. start_time = db.Column(db.DateTime, nullable=False)
  64. end_time = db.Column(db.DateTime, nullable=False)
  65. num_slot = db.Column(db.Integer, nullable=False, default=2)
  66. class Tetawebapp_staffs(db.Model):
  67. __tablename__ = 'participer_thsf_staffs'
  68. id = db.Column(db.Integer, primary_key=True)
  69. turn_id = db.Column(db.Integer, db.ForeignKey('participer_thsf_turns.id'), nullable=False)
  70. user_id = db.Column(db.Integer, db.ForeignKey('participer_thsf_users.id'), default=0, nullable=False)
  71. slot_num = db.Column(db.Integer, nullable=False)
  72. ########################################################################
  73. # Menu and navigation management
  74. ########################################################################
  75. def get_menu(page):
  76. """ The main menu is a list of lists in the followin format:
  77. [unicode caption,
  78. {unicode URL endpoint: [unicode route, ...]},
  79. int 0]
  80. - The URL end point is the URL where to point to (href)
  81. - One of the routes MUST match the route called by request
  82. - The int 0 is used to determine which menu entry is actally called.
  83. The value MUST be 0."""
  84. menu = [[u'Accueil', {u'/': [u'/']}, 0],
  85. [u'Mon compte', {u'/account': [u'/account', u'/account/update']}, 0],
  86. [u'Feuille de staff', {u'/staffsheet': [u'/staffsheet', u'/staffsheet/clear/<TURN_ID>/<SLOT_ID>', u'/staffsheet/update/<TURN_ID>/<SLOT_ID>']}, 0],
  87. [u'Déconnexion', {u'/logout': [u'/logout']}, 0],
  88. ]
  89. if session['is_admin']:
  90. menu = [[u'Accueil', {u'/': [u'/']}, 0],
  91. [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],
  92. [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],
  93. [u'Liste des staffers', {u'/users': [u'/users', u'/account/<ID>', u'/account/delete/<ID>']}, 0],
  94. [u'Déconnexion', {u'/logout': [u'/logout']}, 0],
  95. ]
  96. #~ print '[+] Page: %s' % page
  97. for item in menu:
  98. for url in item[1]:
  99. for route in item[1][url]:
  100. #~ print " [+] Route: %s" %route
  101. if route == page:
  102. #~ print " [+] Selected page: %s" % page
  103. item[2] = 1
  104. return menu
  105. # This should never happen
  106. return menu
  107. def get_navbar(page, selected):
  108. """ The horizontal navbar is a list of lists in the followin format:
  109. [unicode caption, {unicode URL endpoint: [unicode route, ...]}, int 0]
  110. - The URL end point is the URL where to point to (href)
  111. - One of the routes MUST match the route called by request
  112. - The int 0 is used to de """
  113. navbars = [[u'First article', {u'/articles/1': [u'/articles', u'/articles/<ID>']}, 0, 0],
  114. [u'Second article', {u'/articles/2': [u'/articles', u'/articles/<ID>']}, 0, 0],
  115. [u'Third article', {u'/articles/3': [u'/articles', u'/articles/<ID>']}, 0, 0]
  116. ]
  117. navbar = []
  118. for item in navbars:
  119. for url in item[1]:
  120. if url == selected:
  121. item[2] = 1
  122. for route in item[1][url]:
  123. if route == page:
  124. navbar.append(item)
  125. navbar[len(navbar) - 1][3] = 1
  126. return navbar
  127. ########################################################################
  128. # Session management
  129. ########################################################################
  130. def sync_session(request, session):
  131. """ Synchronize cookies with session """
  132. for key in request.cookies:
  133. session[key] = request.cookies[key].encode('utf8')
  134. def sync_cookies(response, session):
  135. """ Synchronize session with cookies """
  136. for key in session:
  137. response.set_cookie(key, value=str(session[key]))
  138. def check_session(func):
  139. """ Check if the session has required token cookie set.
  140. If not, redirects to the login page. """
  141. @wraps(func)
  142. def check(*args, **kwargs):
  143. try:
  144. if session['token'] == request.cookies['token'] and len(session['token']) > 0:
  145. # User is logged in and identified
  146. return func(*args, **kwargs)
  147. else:
  148. # User is not logged in or session expired
  149. session['token'] = ''
  150. response = app.make_response(render_template('login_or_register.html', message=''))
  151. sync_cookies(response, session)
  152. return response
  153. except KeyError:
  154. # User is not logged in
  155. return render_template('login_or_register.html', message='')
  156. return check
  157. def gen_token(size=42):
  158. """ Generate a random token to be stored in session and cookie """
  159. token = binascii.hexlify(os.urandom(size))
  160. return token
  161. ########################################################################
  162. # User management
  163. ########################################################################
  164. def check_login(login, password):
  165. """ Puts the login verification code here """
  166. hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
  167. stored_hash = Tetawebapp_users.query.filter(Tetawebapp_users.mail==login, Tetawebapp_users.link_id==None).with_entities(Tetawebapp_users.password).first()
  168. if stored_hash:
  169. if bcrypt.checkpw(password, stored_hash[0].encode('utf-8')):
  170. is_admin = Tetawebapp_users.query.filter_by(mail=login).with_entities(Tetawebapp_users.is_admin).first()
  171. user_id = Tetawebapp_users.query.filter_by(mail=login).with_entities(Tetawebapp_users.id).first()
  172. session['is_admin'] = is_admin[0]
  173. session['user_id'] = user_id[0]
  174. return True
  175. print "[+] Login failed"
  176. return False
  177. def check_confirm(login, password, link_id):
  178. """ Check identity when confirming email address """
  179. hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
  180. stored_hash = Tetawebapp_users.query.filter(Tetawebapp_users.mail==login, Tetawebapp_users.link_id==link_id).with_entities(Tetawebapp_users.password).first()
  181. if stored_hash:
  182. if bcrypt.checkpw(password, stored_hash[0].encode('utf-8')):
  183. is_admin = Tetawebapp_users.query.filter_by(mail=login).with_entities(Tetawebapp_users.is_admin).first()
  184. user_id = Tetawebapp_users.query.filter_by(mail=login).with_entities(Tetawebapp_users.id).first()
  185. session['is_admin'] = is_admin[0]
  186. session['user_id'] = user_id[0]
  187. return True
  188. return False
  189. def register_user(login, password, confirm):
  190. """ Register new user """
  191. if password != confirm:
  192. # Password does not match confirmation
  193. print "[+] Password mismatch confirmation"
  194. return False
  195. check_user = Tetawebapp_users.query.filter_by(mail=login).count()
  196. if check_user != 0:
  197. # User already exists
  198. print "[+] User already exists"
  199. return False
  200. link_id = gen_token(20)
  201. hashed_password = bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt())
  202. user = Tetawebapp_users(mail=login.encode('utf8'), password=hashed_password, link_id=link_id)
  203. try:
  204. db.session.add(user)
  205. commit = db.session.commit()
  206. except Exception as e:
  207. db.session.rollback()
  208. print "[+] Error at register_user:"
  209. print "------------------------------"
  210. print "%s" % e.message
  211. print "------------------------------"
  212. return False
  213. if commit != None:
  214. print "[+] Error at register_user: commit was not None"
  215. return False
  216. send_mail(login, link_id)
  217. return True
  218. def confirm_user(login, password, link_id):
  219. """ Confirm user by setting link_id == None """
  220. if check_confirm(login, password, link_id):
  221. user = Tetawebapp_users.query.filter_by(mail=login).first()
  222. setattr(user, 'link_id', None)
  223. try:
  224. db.session.add(user)
  225. commit = db.session.commit()
  226. except Exception as e:
  227. db.session.rollback()
  228. print "[+] Error at confirm_user:"
  229. print "------------------------------"
  230. print "%s" % e.message
  231. print "------------------------------"
  232. return False
  233. if commit != None:
  234. return False
  235. return True
  236. return False
  237. def update_user(login, password, confirm, name, phone, diet):
  238. """ Update user infos with provided data """
  239. if password != confirm:
  240. # Password does not match confirmation
  241. print "[+] Password mismatch confirmation"
  242. return False
  243. check_user = Tetawebapp_users.query.filter_by(mail=login).count()
  244. if check_user == 0:
  245. # User does not exist
  246. print "[+] User does not exist"
  247. return False
  248. user = Tetawebapp_users.query.filter_by(mail=login).first()
  249. if len(password) > 0:
  250. # User requested password modification
  251. hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
  252. setattr(user, 'password', hashed_password)
  253. # Password has been updated if necessary
  254. # Now let's update other data
  255. setattr(user, 'name', name)
  256. setattr(user, 'phone', phone)
  257. setattr(user, 'diet', diet)
  258. try:
  259. db.session.add(user)
  260. commit = db.session.commit()
  261. except Exception as e:
  262. db.session.rollback()
  263. print "[+] Error at update_user:"
  264. print "------------------------------"
  265. print "%s" % e.message
  266. print "------------------------------"
  267. return False
  268. if commit != None:
  269. return False
  270. return True
  271. def update_user_by_id(user_id, login, password, confirm, name, phone, diet):
  272. """ Update user infos with provided data """
  273. if password != confirm:
  274. # Password does not match confirmation
  275. print "[+] Password mismatch confirmation"
  276. return False
  277. check_user = Tetawebapp_users.query.filter_by(id=user_id).count()
  278. if check_user == 0:
  279. # User does not exist
  280. print "[+] User does not exist"
  281. return False
  282. user = Tetawebapp_users.query.filter_by(id=user_id).first()
  283. if len(password) > 0:
  284. # User requested password modification
  285. hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
  286. setattr(user, 'password', hashed_password)
  287. # Password has been updated if necessary
  288. # Now let's update other data
  289. setattr(user, 'name', name)
  290. setattr(user, 'phone', phone)
  291. setattr(user, 'diet', diet)
  292. try:
  293. db.session.add(user)
  294. commit = db.session.commit()
  295. except Exception as e:
  296. db.session.rollback()
  297. print "[+] Error at update_user_by_id:"
  298. print "------------------------------"
  299. print "%s" % e.message
  300. print "------------------------------"
  301. return False
  302. if commit != None:
  303. return False
  304. return True
  305. def reset_password(login, password, confirm):
  306. if password != confirm:
  307. # Password does not match confirmation
  308. print "[+] [Reset password] Password mismatch confirmation"
  309. return False
  310. check_user = Tetawebapp_users.query.filter_by(mail=login).count()
  311. if check_user == 0:
  312. # User does not exist
  313. print "[+] [Reset password] User does not exist"
  314. return False
  315. user = Tetawebapp_users.query.filter_by(mail=login).first()
  316. if len(password) > 0:
  317. # User requested password modification
  318. hashed_password = bcrypt.hashpw(password, bcrypt.gensalt())
  319. setattr(user, 'password', hashed_password)
  320. # We also ask for a new account confirmation
  321. link_id = gen_token(20)
  322. setattr(user, 'link_id', link_id)
  323. try:
  324. db.session.add(user)
  325. commit = db.session.commit()
  326. send_reset_mail(login, link_id)
  327. except Exception as e:
  328. db.session.rollback()
  329. print "[+] Error at reset_password:"
  330. print "------------------------------"
  331. print "%s" % e.message
  332. print "------------------------------"
  333. return False
  334. if commit != None:
  335. return False
  336. return True
  337. def delete_user(user_id):
  338. """ Delete user """
  339. try:
  340. Tetawebapp_users.query.filter_by(id=int(user_id)).delete()
  341. db.session.commit()
  342. return True
  343. except ValueError as e:
  344. return False
  345. except Exception as e:
  346. db.session.rollback()
  347. print "[+] Error at delete_user:"
  348. print "------------------------------"
  349. print "%s" % e.message
  350. print "------------------------------"
  351. return False
  352. def get_user_name(user_id):
  353. """ Get pseudo from user ID """
  354. try:
  355. user = Tetawebapp_users.query.filter_by(id=int(user_id)).first()
  356. return user.name
  357. except Exception as e:
  358. print "[+] Error at get_pseudo:"
  359. print "------------------------------"
  360. print "%s" % e.message
  361. print "------------------------------"
  362. return False
  363. def check_user_info():
  364. """ Check user info and send appropriate message if info are not complete"""
  365. message = ''
  366. user = Tetawebapp_users.query.filter_by(mail=session['login']).first()
  367. name = user.name
  368. phone = user.phone
  369. diet = user.diet
  370. if name == None or phone == None or \
  371. len(name) == 0 or len(phone) == 0:
  372. 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'"
  373. return message.decode('utf-8')
  374. ########################################################################
  375. # Turns
  376. ########################################################################
  377. def save_turn(role_id, day, start, end, num_slot):
  378. """ Save a new turn """
  379. days = ['2018-05-08', '2018-05-09', '2018-05-10', '2018-05-11', '2018-05-12', '2018-05-13', '2018-05-14']
  380. day_index = days.index(day)
  381. sday = day
  382. eday = day
  383. if str(start[0]) == '0':
  384. sday = days[day_index+1]
  385. if str(end[0]) == '0':
  386. eday = days[day_index+1]
  387. start = '%s %s' % (sday, start)
  388. end = '%s %s' % (eday, end)
  389. turn = Tetawebapp_turns(role_id=role_id.encode('utf-8'),
  390. start_time=start.encode('utf-8'),
  391. end_time=end.encode('utf-8'),
  392. num_slot=num_slot.encode('utf-8'),
  393. )
  394. try:
  395. db.session.add(turn)
  396. commit = db.session.commit()
  397. except Exception as e:
  398. db.session.rollback()
  399. print "[+] Error at save_turn:"
  400. print "------------------------------"
  401. print "%s" % e.message
  402. print "------------------------------"
  403. return False
  404. if commit != None:
  405. return False
  406. return True
  407. def get_turn_by_id(turn_id):
  408. """ Get specified stafff turn """
  409. days = {'2018-05-08': 'Mardi',
  410. '2018-05-09': 'Mercredi',
  411. '2018-05-10': 'Jeudi',
  412. '2018-05-11': 'Vendredi',
  413. '2018-05-12': 'Samedi',
  414. '2018-05-13': 'Dimanche',
  415. '2018-05-14': 'Lundi'}
  416. turn = Tetawebapp_turns.query.filter_by(id=turn_id).first()
  417. s_day, s_time = str(turn.start_time).split(' ')
  418. e_day, e_time = str(turn.end_time).split(' ')
  419. if s_time[0] == '0':
  420. s_day = (datetime.datetime.strptime(s_day, '%Y-%m-%d')-datetime.timedelta(1)).strftime("%Y-%m-%d")
  421. day = days[s_day]
  422. return {'id': turn_id, 'role_id': turn.role_id, 'day': day, 'start_time': s_time, 'end_time': e_time, 'num_slot': turn.num_slot}
  423. def update_turn_by_id(turn_id, role_id, day, start, end, num_slot):
  424. """ Update turn with provided data """
  425. check_turn = Tetawebapp_turns.query.filter_by(id=turn_id).count()
  426. if check_turn == 0:
  427. # User does not exist
  428. print "[+] Turn does not exist"
  429. return False
  430. days = ['2018-05-08', '2018-05-09', '2018-05-10', '2018-05-11', '2018-05-12', '2018-05-13', '2018-05-14']
  431. day_index = days.index(day)
  432. sday = day
  433. eday = day
  434. if str(start[0]) == '0':
  435. sday = days[day_index +1]
  436. if str(end[0]) == '0':
  437. eday = days[day_index +1]
  438. start = '%s %s' % (sday, start)
  439. end = '%s %s' % (eday, end)
  440. turn = Tetawebapp_turns.query.filter_by(id=turn_id).first()
  441. setattr(turn, 'role_id', role_id)
  442. setattr(turn, 'start_time', start)
  443. setattr(turn, 'end_time', end)
  444. setattr(turn, 'num_slot', num_slot)
  445. try:
  446. db.session.add(turn)
  447. commit = db.session.commit()
  448. except Exception as e:
  449. db.session.rollback()
  450. print "[+] Error at update_turn:"
  451. print "------------------------------"
  452. print "%s" % e.message
  453. print "------------------------------"
  454. return False
  455. if commit != None:
  456. return False
  457. return True
  458. def drop_turn(turn_id):
  459. """ Delete staff turn """
  460. try:
  461. Tetawebapp_turns.query.filter_by(id=int(turn_id)).delete()
  462. db.session.commit()
  463. return True
  464. except ValueError as e:
  465. print e
  466. return False
  467. except Exception as e:
  468. db.session.rollback()
  469. print "[+] Error at drop_turn:"
  470. print "------------------------------"
  471. print "%s" % e.message
  472. print "------------------------------"
  473. return False
  474. def turns_list():
  475. """ List staff turns """
  476. turns = []
  477. tuesday = '2018-05-08 06:00:00'
  478. wenesday = '2018-05-09 06:00:00'
  479. thirsday = '2018-05-10 06:00:00'
  480. friday = '2018-05-11 06:00:00'
  481. saturday = '2018-05-12 06:00:00'
  482. sunday = '2018-05-13 06:00:00'
  483. monday = '2018-05-14 06:00:00'
  484. tuesday_turns = Tetawebapp_turns.query.filter(Tetawebapp_turns.start_time > tuesday, Tetawebapp_turns.start_time < wenesday)
  485. tuesday_turns = tuesday_turns.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id)
  486. tuesday_turns = tuesday_turns.add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id, Tetawebapp_turns.start_time).all()
  487. wenesday_turns = Tetawebapp_turns.query.filter(Tetawebapp_turns.start_time > wenesday, Tetawebapp_turns.start_time < thirsday)
  488. wenesday_turns = wenesday_turns.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id)
  489. wenesday_turns = wenesday_turns.add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id, Tetawebapp_turns.start_time).all()
  490. thirsday_turns = Tetawebapp_turns.query.filter(Tetawebapp_turns.start_time > thirsday, Tetawebapp_turns.start_time < friday)
  491. thirsday_turns = thirsday_turns.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id)
  492. thirsday_turns = thirsday_turns.add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id, Tetawebapp_turns.start_time).all()
  493. friday_turns = Tetawebapp_turns.query.filter(Tetawebapp_turns.start_time > friday, Tetawebapp_turns.start_time < saturday)
  494. friday_turns = friday_turns.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id)
  495. friday_turns = friday_turns.add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id, Tetawebapp_turns.start_time).all()
  496. saturday_turns = Tetawebapp_turns.query.filter(Tetawebapp_turns.start_time > saturday, Tetawebapp_turns.start_time < sunday)
  497. saturday_turns = saturday_turns.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id)
  498. saturday_turns = saturday_turns.add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id, Tetawebapp_turns.start_time).all()
  499. sunday_turns = Tetawebapp_turns.query.filter(Tetawebapp_turns.start_time > sunday, Tetawebapp_turns.start_time < monday)
  500. sunday_turns = sunday_turns.join(Tetawebapp_roles, Tetawebapp_turns.role_id==Tetawebapp_roles.id)
  501. sunday_turns = sunday_turns.add_columns(Tetawebapp_roles.role).order_by(Tetawebapp_turns.role_id, Tetawebapp_turns.start_time).all()
  502. turns.append(('Mardi 08/05', tuesday_turns))
  503. turns.append(('Mercredi 09/05', wenesday_turns))
  504. turns.append(('Jeudi 10/05', thirsday_turns))
  505. turns.append(('Vendredi 11/05', friday_turns))
  506. turns.append(('Samedi 12/05', saturday_turns))
  507. turns.append(('Dimanche 13/05', sunday_turns))
  508. return turns
  509. ########################################################################
  510. # Staffs
  511. ########################################################################
  512. def get_staffers():
  513. try:
  514. staffers = Tetawebapp_users.query(Tetawebapp_users.id > 1).all()
  515. return staffers
  516. except Exception as e:
  517. print "[+] Error at get_staffers:"
  518. print "------------------------------"
  519. print "%s" % e.message
  520. print "------------------------------"
  521. return False
  522. def get_staffs():
  523. """ """
  524. try:
  525. staffs = Tetawebapp_staffs.query.join(Tetawebapp_users, Tetawebapp_staffs.user_id==Tetawebapp_users.id)
  526. staffs = staffs.add_columns(Tetawebapp_users.name).all()
  527. return staffs
  528. except Exception as e:
  529. print "[+] Error at get_staffs:"
  530. print "------------------------------"
  531. print "%s" % e.message
  532. print "------------------------------"
  533. return False
  534. def drop_staff_slot(turn_id, slot_num, user_id):
  535. """ Drop staff given slot """
  536. slot = Tetawebapp_staffs.query.filter_by(turn_id=turn_id, slot_num=slot_num).first()
  537. if slot.user_id == user_id:
  538. try:
  539. Tetawebapp_staffs.query.filter_by(turn_id=turn_id, slot_num=slot_num).delete()
  540. db.session.commit()
  541. return True
  542. except Exception as e:
  543. db.session.rollback()
  544. print "[+] Error at drop_staff_slot:"
  545. print "------------------------------"
  546. print "%s" % e.message
  547. print "------------------------------"
  548. return False
  549. return False
  550. def save_staff_slot(turn_id, slot_id, user_id):
  551. """ Save staff given slot """
  552. slot = Tetawebapp_staffs.query.filter(Tetawebapp_staffs.turn_id==turn_id, Tetawebapp_staffs.slot_num==slot_id).count()
  553. if slot == 0:
  554. slot = Tetawebapp_staffs.query.filter(Tetawebapp_staffs.turn_id==turn_id, Tetawebapp_staffs.user_id==user_id).count()
  555. if slot == 0:
  556. slot = Tetawebapp_staffs(user_id=user_id,
  557. turn_id=turn_id,
  558. slot_num=slot_id)
  559. try:
  560. db.session.add(slot)
  561. commit = db.session.commit()
  562. except Exception as e:
  563. db.session.rollback()
  564. print "[+] Error at save_staff_slot:"
  565. print "------------------------------"
  566. print "%s" % e.message
  567. print "------------------------------"
  568. return False
  569. if commit != None:
  570. return False
  571. return True
  572. return False
  573. def check_user_availability(turn_id, user_id):
  574. """ Check if user is available for this turn """
  575. turn_start, turn_end = Tetawebapp_turns.query.filter(Tetawebapp_turns.id==turn_id).with_entities(Tetawebapp_turns.start_time, Tetawebapp_turns.end_time).first()
  576. user_turns = Tetawebapp_staffs.query.filter(Tetawebapp_staffs.user_id==user_id).with_entities(Tetawebapp_staffs.turn_id).all()
  577. for turn in user_turns:
  578. t_start, t_end = Tetawebapp_staffs.query.filter(Tetawebapp_turns.id==turn[0]).with_entities(Tetawebapp_turns.start_time, Tetawebapp_turns.end_time).first()
  579. if t_start <= turn_start and t_end > turn_start:
  580. return False
  581. if t_start >= turn_start and t_start < turn_end:
  582. return False
  583. return True
  584. ########################################################################
  585. # Role
  586. ########################################################################
  587. def get_roles():
  588. """ Get full roles list """
  589. try:
  590. roles = Tetawebapp_roles.query.filter(Tetawebapp_roles.id > 3).all()
  591. return roles
  592. except Exception as e:
  593. print "[+] Error at get_roles:"
  594. print "------------------------------"
  595. print "%s" % e.message
  596. print "------------------------------"
  597. return False
  598. ########################################################################
  599. # Mail
  600. ########################################################################
  601. def send_mail(email, link_id):
  602. msg = Message("[THSF] Confirmation d'inscription au staff THSF",
  603. sender="dave.null@tetalab.org",
  604. recipients=[email])
  605. msg.body = "Bonjour,\nVous recevez ce courriel car vous avez souhaité faire partie de l'équipe du staff du THSF.\n\n"
  606. msg.body += "Pour confirmer votre inscription, rendez vous à la page suivante:\n"
  607. msg.body += "%s/confirm/%s\n\n" % (str(app.config['DOMAIN_URL']), str(link_id))
  608. msg.body += "Si vous n'êtes pas à l'origine de cette inscription, ignorez simplement ce courriel.\n"
  609. msg.body += "Votre compte sera automatiquement supprimé dans les 24 heures.\n\n"
  610. msg.body += "Si vous désirez vous désinscrire, faites simplement une demande sur https://bofh.tetalab.org\n\n"
  611. msg.body += "Dans tous les cas la base de données sera totalement réinitialisée à la fin du THSF.\n\n"
  612. msg.body += "Votre aide nous est précieuse.\nMerci et bravo à vous.\n"
  613. msg.body += "-- \n"
  614. msg.body += "L'équipe d'organisation du THSF\n"
  615. 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)"
  616. mail.send(msg)
  617. def send_reset_mail(email, link_id):
  618. msg = Message("[THSF] Confirmation de réinitialisation de votre mot de passe",
  619. sender="dave.null@tetalab.org",
  620. recipients=[email])
  621. msg.body = "Bonjour,\nVous recevez ce courriel car vous avez demandé la réinitialisation de votre mot de passe.\n\n"
  622. msg.body += "Pour confirmer votre noueau mot de passe, rendez vous à la page suivante:\n"
  623. msg.body += "%s/confirm/%s\n\n" % (str(app.config['DOMAIN_URL']), str(link_id))
  624. 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"
  625. msg.body += "-- \n"
  626. msg.body += "L'équipe d'organisation du THSF\n"
  627. 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)"
  628. mail.send(msg)
  629. ########################################################################
  630. # Routes:
  631. # -------
  632. # Except for the index function, the function name MUST have the same
  633. # name than the URL endpoint to make the menu work properly
  634. ########################################################################
  635. @app.errorhandler(404)
  636. def page_not_found(e):
  637. """ 404 not found """
  638. return render_template('error.html'), 404
  639. ########################################################################
  640. # Entry
  641. ########################################################################
  642. @app.route("/", methods=['GET', 'POST'])
  643. @check_session
  644. def index():
  645. """ Index page """
  646. page = str(request.url_rule)
  647. menu = get_menu(page)
  648. message = check_user_info()
  649. return render_template('index.html', menu=menu, message=message, login=session['login'])
  650. ########################################################################
  651. # Session
  652. ########################################################################
  653. @app.route("/login", methods=['GET', 'POST'])
  654. def login():
  655. """ Login """
  656. try:
  657. login = request.form.get('login').encode('utf-8')
  658. password = request.form.get('password').encode('utf-8')
  659. if check_login(login, password):
  660. # Generate and store a token in session
  661. session['token'] = gen_token()
  662. session['login'] = login
  663. # Return user to index page
  664. page = '/'
  665. menu = get_menu(page)
  666. message = check_user_info()
  667. response = app.make_response(render_template('index.html', menu=menu, message=message, login=login))
  668. # Push token to cookie
  669. sync_cookies(response, session)
  670. return response
  671. # Credentials are not valid
  672. response = app.make_response(render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide"))
  673. session['token'] = ''
  674. session['login'] = ''
  675. session['is_admin'] = 0
  676. sync_cookies(response, session)
  677. return response
  678. except AttributeError:
  679. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  680. ########################################################################
  681. # User
  682. ########################################################################
  683. @app.route("/confirm/<LINK_ID>", methods=['GET', 'POST'])
  684. def confirm(LINK_ID):
  685. """ Index page """
  686. link_id = LINK_ID.encode('utf-8')
  687. return render_template('confirm.html', message="Merci de confirmer votre enregistrement", link_id=link_id)
  688. @app.route("/confirm/link/<LINK_ID>", methods=['GET', 'POST'])
  689. def confirm_link(LINK_ID):
  690. """ Index page """
  691. try:
  692. link_id = LINK_ID.encode('utf-8')
  693. login = request.form.get('login').encode('utf-8')
  694. password = request.form.get('password').encode('utf-8')
  695. if check_confirm(login, password, link_id) and confirm_user(login, password, link_id):
  696. # Generate and store a token in session
  697. session['token'] = gen_token()
  698. session['login'] = login
  699. # Return user to index page
  700. page = '/'
  701. menu = get_menu(page)
  702. message = check_user_info()
  703. response = app.make_response(render_template('index.html', menu=menu, message=message, login=login))
  704. # Push token to cookie
  705. sync_cookies(response, session)
  706. return response
  707. # Credentials are not valid
  708. response = app.make_response(render_template('confirm.html', message="Utilisateur ou mot de passe invalide", link_id=link_id))
  709. session['token'] = ''
  710. session['login'] = ''
  711. session['is_admin'] = 0
  712. sync_cookies(response, session)
  713. return response
  714. except AttributeError:
  715. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  716. link_id = LINK_ID.encode('utf-8')
  717. return render_template('confirm.html', message="Merci de confirmer votre enregistrement", link_id=link_id)
  718. @app.route("/register", methods=['GET', 'POST'])
  719. def register():
  720. """ Allow self registration """
  721. try:
  722. login = request.form.get('login').lower().encode('utf-8')
  723. password = request.form.get('password').encode('utf-8')
  724. confirm = request.form.get('confirm').encode('utf-8')
  725. message = "Erreur lors de l'enregsitrement: L'utilisateur existe t-il déjà ?"
  726. if register_user(login, password, confirm):
  727. message = "Merci de votre engagement. Un courriel contenant les instructions de confirmation votre inscription vient de vous être envoyé."
  728. # Error while registering user
  729. return render_template('login_or_register.html', message=message.decode('utf-8'))
  730. except AttributeError:
  731. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  732. @app.route("/account", methods=['GET', 'POST'])
  733. @check_session
  734. def account():
  735. """ Account page """
  736. page = str(request.url_rule)
  737. menu = get_menu(page)
  738. user = Tetawebapp_users.query.filter_by(mail=session['login']).first()
  739. mail = '' if user.mail == None else user.mail
  740. name = '' if user.name == None else user.name
  741. phone = '' if user.phone == None else user.phone
  742. diet = '' if user.diet == None else user.diet
  743. message = check_user_info()
  744. return render_template('account.html', menu=menu, mail=mail, name=name, phone=phone, diet=diet, message=message)
  745. @app.route("/account/update", methods=['GET', 'POST'])
  746. @check_session
  747. def update_account():
  748. """ Update current account """
  749. try:
  750. page = str(request.url_rule)
  751. menu = get_menu(page)
  752. login = session['login']
  753. password = request.form.get('password').encode('utf-8')
  754. confirm = request.form.get('confirm').encode('utf-8')
  755. name = request.form.get('name').encode('utf-8')
  756. phone = request.form.get('phone').encode('utf-8')
  757. diet = request.form.get('diet').encode('utf-8')
  758. if update_user(login, password, confirm, name, phone, diet):
  759. message = check_user_info()
  760. else:
  761. message = "Erreur lors de l'enregistrement des données."
  762. return render_template('account.html',
  763. menu=menu,
  764. mail=login.decode('utf-8'),
  765. name=name.decode('utf-8'),
  766. phone=phone.decode('utf-8'),
  767. diet=diet.decode('utf-8'),
  768. message=message)
  769. except AttributeError:
  770. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  771. @app.route("/account/reset/ask", methods=['GET', 'POST'])
  772. def ask_reset():
  773. """ Ask for password reset page """
  774. return render_template('reset_password.html')
  775. @app.route("/account/reset", methods=['GET', 'POST'])
  776. def reset_account():
  777. """ Password reset """
  778. try:
  779. login = request.form.get('login').encode('utf-8')
  780. password = request.form.get('password').encode('utf-8')
  781. confirm = request.form.get('confirm').encode('utf-8')
  782. if reset_password(login, password, confirm):
  783. message = "Une confirmation de la réinitialisation de votre mot de passe vous a été envoyé par email"
  784. return render_template('login_or_register.html', message=message.decode('utf-8'))
  785. message="Erreur lors de la réinitialisation du mot de passe"
  786. return render_template('login_or_register.html', message=message.decode('utf-8'))
  787. except AttributeError:
  788. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  789. @app.route("/logout", methods=['GET', 'POST'])
  790. @check_session
  791. def logout():
  792. """ Logout user """
  793. # Remove session token
  794. session['token'] = None
  795. session['login'] = None
  796. session['is_admin'] = 0
  797. # Return user to index page
  798. response = app.make_response(render_template('login_or_register.html', message=''))
  799. # Push token to cookie
  800. sync_cookies(response, session)
  801. return response
  802. ########################################################################
  803. # Staffsheet
  804. ########################################################################
  805. @app.route("/staffsheet", methods=['GET', 'POST'])
  806. @check_session
  807. def staffsheet():
  808. try:
  809. is_admin = session['is_admin']
  810. user_id = session['user_id']
  811. if len(check_user_info()) == 0:
  812. page = str(request.url_rule)
  813. menu = get_menu(page)
  814. turns = turns_list()
  815. staffs = get_staffs()
  816. staffers = get_staffers()
  817. roles = get_roles()
  818. return render_template('staffsheet.html', menu=menu, turns=turns, staffs=staffs, staffers=staffers, user_id=user_id, is_admin=is_admin, roles=roles, message='')
  819. else:
  820. return account()
  821. except AttributeError as e:
  822. # User is not logged in
  823. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  824. @app.route("/staffsheet/pdf", methods=['GET', 'POST'])
  825. def staffsheet_pdf():
  826. turns = turns_list()
  827. staffs = get_staffs()
  828. roles = get_roles()
  829. data = render_template('staffsheet_txt.html', turns=turns, staffs=staffs, roles=roles)
  830. data = [line for line in data.split('\n') if len(line) > 0]
  831. data = '\n'.join(data)
  832. data = [line for line in data.split('",\n') if len(line) > 0]
  833. data = '", '.join(data)
  834. ddata = [ast.literal_eval(line) for line in data.split('\n')]
  835. pdf = cStringIO.StringIO()
  836. doc = SimpleDocTemplate(pdf, pagesize=A4, rightMargin=3,leftMargin=3, topMargin=3,bottomMargin=3)
  837. elements = []
  838. styles = getSampleStyleSheet()
  839. styles.add(ParagraphStyle(name='master_title',
  840. alignment=TA_LEFT,
  841. fontSize=20,
  842. leading=25,
  843. spaceBefore=10,
  844. spaceAfter=10,
  845. ))
  846. styles.add(ParagraphStyle(name='day_title',
  847. alignment=TA_LEFT,
  848. backColor=orange,
  849. borderWidth=1,
  850. borderColor=black,
  851. borderPadding=5,
  852. spaceBefore=10,
  853. spaceAfter=10
  854. ))
  855. styles.add(ParagraphStyle(name='role_title',
  856. alignment=TA_LEFT,
  857. backColor=lightsalmon,
  858. borderWidth=1,
  859. borderColor=black,
  860. borderPadding=5,
  861. spaceBefore=10,
  862. spaceAfter=10
  863. ))
  864. styles.add(ParagraphStyle(name='turn',
  865. alignment=TA_LEFT,
  866. backColor=white,
  867. borderWidth=1,
  868. borderColor=black,
  869. borderPadding=5,
  870. spaceBefore=10,
  871. spaceAfter=0
  872. ))
  873. styles.add(ParagraphStyle(name='basic_text',
  874. alignment=TA_LEFT,
  875. spaceBefore=5,
  876. spaceAfter=5
  877. ))
  878. styles.add(ParagraphStyle(name='row1',
  879. alignment=TA_LEFT,
  880. backColor=white,
  881. spaceBefore=10,
  882. spaceAfter=10
  883. ))
  884. styles.add(ParagraphStyle(name='row2',
  885. alignment=TA_CENTER,
  886. backColor=white,
  887. spaceBefore=10,
  888. spaceAfter=10
  889. ))
  890. elements.append(Paragraph("<b>Fiches de poste</b>", styles['master_title']))
  891. 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.",
  892. styles['basic_text']))
  893. for role in roles:
  894. elements.append(Paragraph("<b>%s</b>" % role.role, styles['day_title']))
  895. desc = role.description.split('|')
  896. for point in desc:
  897. elements.append(Paragraph(point, styles['basic_text'], bulletText='-'))
  898. elements.append(PageBreak())
  899. elements.append(Paragraph("<b>Feuilles de staff</b>", styles['master_title']))
  900. elements.append(Paragraph("<b>Ménage le soir même pour tous les derniers créneaux du jour</b>", styles['basic_text'], bulletText='-'))
  901. elements.append(Paragraph("Tâches dévolues <b>à tous et à tous moments</b>:", styles['basic_text'], bulletText='-'))
  902. elements.append(Indenter(left=20, right=0) )
  903. elements.append(Paragraph("Veiller à la sécurité générale du lieu", styles['basic_text'], bulletText='-'))
  904. elements.append(Paragraph("Ramassage bouteilles ou objets en verre", styles['basic_text'], bulletText='-'))
  905. elements.append(Paragraph("Séparation des bagarres (rarissime)", styles['basic_text'], bulletText='-'))
  906. elements.append(Paragraph("Sécurisation des personnes en difficulté (ou trop alcoolisées), etc...", styles['basic_text'], bulletText='-'))
  907. elements.append(Paragraph("<b>Sourire et bonne humeur</b> quel que soit le niveau de fatigue ;)", styles['basic_text'], bulletText='-'))
  908. elements.append(Indenter(left=-20, right=0) )
  909. for day in turns:
  910. wday = day[0]
  911. day_turns = day[1]
  912. cur_role = ''
  913. if wday not in ['Mardi', 'Mercredi']:
  914. elements.append(PageBreak())
  915. elements.append(Paragraph("<b>%s</b>" % wday, styles['day_title']))
  916. for turn in day_turns:
  917. rows = []
  918. role = turn[1]
  919. start_time = turn[0].start_time
  920. end_time = turn[0].end_time
  921. num_slot = turn[0].num_slot
  922. role_id = turn[0].role_id
  923. turn_id = turn[0].id
  924. if role != cur_role:
  925. cur_role = role
  926. elements.append(Paragraph("<b>%s</b>" % role, styles['role_title']))
  927. row = (Paragraph("<b>%s / %s</b>" % (start_time.strftime('%HH%M'), end_time.strftime('%HH%M')), styles['row1']),)
  928. for slot in range(0, num_slot):
  929. cols_width = [100] + [485/num_slot] * num_slot
  930. allocated_slot = []
  931. for sslot in staffs:
  932. if sslot[0].turn_id == turn_id and sslot[0].slot_num == slot:
  933. allocated_slot.append(sslot[0].slot_num)
  934. row += (Paragraph(sslot[1], styles['row2']),)
  935. if slot not in allocated_slot:
  936. row += (Paragraph("&nbsp;", styles['row2']),)
  937. rows.append(row)
  938. table = Table(rows, colWidths=cols_width, rowHeights=23)
  939. table.setStyle(TableStyle( [('GRID', (0,0), (-1,-1), 0.25, colors.black),
  940. ('ALIGN', (1,1), (-1,-1), 'RIGHT')]))
  941. elements.append(table)
  942. styles.wordWrap = 'CJK'
  943. doc.build(elements)
  944. pdf_out = pdf.getvalue()
  945. pdf.close()
  946. response = app.make_response(pdf_out)
  947. response.headers['Content-Disposition'] = "attachment; filename=feuille_staff_thsf.pdf"
  948. response.mimetype = 'application/pdf'
  949. return response
  950. @app.route("/staffsheet/clear/<TURN_ID>/<SLOT_ID>", methods=['GET', 'POST'])
  951. @check_session
  952. def clear_staff_slot(TURN_ID, SLOT_ID):
  953. try:
  954. turn_id = int(TURN_ID.encode('utf-8'))
  955. slot_id = int(SLOT_ID.encode('utf-8'))
  956. user_id = session['user_id']
  957. if (drop_staff_slot(turn_id, slot_id, user_id)):
  958. return "&nbsp;"
  959. return "KO"
  960. except AttributeError:
  961. # User is not logged in
  962. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  963. except ValueError:
  964. # At least one ID is not integer
  965. return render_template('login_or_register.html', message="Identifiants non conformes")
  966. @app.route("/staffsheet/update/<TURN_ID>/<SLOT_ID>", methods=['GET', 'POST'])
  967. @check_session
  968. def update_staff_slot(TURN_ID, SLOT_ID):
  969. try:
  970. turn_id = int(TURN_ID.encode('utf-8'))
  971. slot_id = int(SLOT_ID.encode('utf-8'))
  972. user_id = session['user_id']
  973. user_name = get_user_name(user_id)
  974. if user_name != None:
  975. if check_user_availability(turn_id, user_id):
  976. if (save_staff_slot(turn_id, slot_id, user_id)):
  977. return user_name
  978. return "KO"
  979. except AttributeError as e:
  980. # User is not logged in
  981. print e
  982. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  983. except ValueError:
  984. # At least one ID is not integer
  985. return render_template('login_or_register.html', message="Identifiants non conformes")
  986. ########################################################################
  987. # Admin zone
  988. ########################################################################
  989. @app.route("/users", methods=['GET', 'POST'])
  990. @check_session
  991. def list_users():
  992. """ Users list """
  993. message = check_user_info()
  994. try:
  995. if session['is_admin']:
  996. page = str(request.url_rule)
  997. menu = get_menu(page)
  998. staffers = Tetawebapp_users.query.filter(Tetawebapp_users.is_admin==0, Tetawebapp_users.link_id==None).order_by(Tetawebapp_users.name).all()
  999. return render_template('list_users.html', menu=menu, staffers=staffers, message=message)
  1000. # User is not admin
  1001. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1002. except:
  1003. # User is not logged in
  1004. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1005. @app.route("/users/print", methods=['GET', 'POST'])
  1006. @check_session
  1007. def print_users():
  1008. """ Print user list """
  1009. message = check_user_info()
  1010. try:
  1011. if session['is_admin']:
  1012. staffers = Tetawebapp_users.query.filter(Tetawebapp_users.is_admin==0, Tetawebapp_users.link_id==None).order_by(Tetawebapp_users.name).all()
  1013. return render_template('list_users_txt.html', staffers=staffers)
  1014. # User is not admin
  1015. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1016. except Exception as e:
  1017. raise e
  1018. # User is not logged in
  1019. return render_template('login_or_register.html', message="%s" % e)
  1020. @app.route("/account/<ID>", methods=['GET', 'POST'])
  1021. @check_session
  1022. def account_by_id(ID):
  1023. """ Arcticles page """
  1024. try:
  1025. if session['is_admin']:
  1026. page = str(request.url_rule)
  1027. menu = get_menu(page)
  1028. message = "ID de l'utilisateur non conforme"
  1029. staffers = Tetawebapp_users.query.filter_by(is_admin=0).order_by(Tetawebapp_users.name).all()
  1030. user_id = int(ID.encode('utf-8'))
  1031. user = Tetawebapp_users.query.filter_by(id=user_id).first()
  1032. return render_template('account_by_id.html', menu=menu, user=user)
  1033. # User is not admin
  1034. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1035. except AttributeError:
  1036. # User is not logged in
  1037. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1038. except ValueError:
  1039. # ID is not an integer
  1040. return render_template('list_users.html', menu=menu, staffers=staffers, message=message)
  1041. @app.route("/account/update/<ID>", methods=['GET', 'POST'])
  1042. @check_session
  1043. def update_account_by_id(ID):
  1044. """ Update given account """
  1045. try:
  1046. if session['is_admin']:
  1047. page = str(request.url_rule)
  1048. menu = get_menu(page)
  1049. login = session['login']
  1050. password = request.form.get('password').encode('utf-8')
  1051. confirm = request.form.get('confirm').encode('utf-8')
  1052. name = request.form.get('name').encode('utf-8')
  1053. phone = request.form.get('phone').encode('utf-8')
  1054. diet = request.form.get('diet').encode('utf-8')
  1055. message = "ID de l'utilisateur non conforme"
  1056. staffers = Tetawebapp_users.query.filter_by(is_admin=0).order_by(Tetawebapp_users.name).all()
  1057. user_id = int(ID.encode('utf-8'))
  1058. if update_user_by_id(user_id, login, password, confirm, name, phone, diet):
  1059. user = Tetawebapp_users.query.filter_by(id=ID).first()
  1060. message = check_user_info()
  1061. else:
  1062. message = "Erreur lors de l'enregistrement des données."
  1063. return render_template('account_by_id.html', menu=menu, user=user,message=message)
  1064. # User is not admin
  1065. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1066. except AttributeError:
  1067. # User is not logged in
  1068. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1069. except ValueError:
  1070. # ID is not an integer
  1071. return render_template('list_users.html', menu=menu, staffers=staffers, message=message)
  1072. @app.route("/account/delete/<ID>", methods=['GET', 'POST'])
  1073. @check_session
  1074. def delete_account(ID):
  1075. """ Delete given account """
  1076. try:
  1077. if session['is_admin']:
  1078. message = "Erreur lors de la suppression.".decode('utf-8')
  1079. page = str(request.url_rule)
  1080. menu = get_menu(page)
  1081. staffers = Tetawebapp_users.query.filter_by(is_admin=0).order_by(Tetawebapp_users.name).all()
  1082. user_id = int(ID.encode('utf-8'))
  1083. if delete_user(user_id):
  1084. message = ''
  1085. staffers = Tetawebapp_users.query.filter_by(is_admin=0).order_by(Tetawebapp_users.name).all()
  1086. return render_template('list_users.html', menu=menu, staffers=staffers, message=message)
  1087. # User is not admin
  1088. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1089. except AttributeError:
  1090. # User is not logged in
  1091. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1092. except ValueError:
  1093. # ID is not an integer
  1094. return render_template('list_users.html', menu=menu, staffers=staffers, message=message)
  1095. ########################################################################
  1096. # Turns
  1097. ########################################################################
  1098. @app.route("/turns", methods=['GET', 'POST'])
  1099. @check_session
  1100. def list_turns():
  1101. """ List staff turns """
  1102. try:
  1103. page = str(request.url_rule)
  1104. menu = get_menu(page)
  1105. message = ''
  1106. if session['is_admin']:
  1107. page = str(request.url_rule)
  1108. menu = get_menu(page)
  1109. turns = turns_list()
  1110. message = ''
  1111. return render_template('list_turns.html', menu=menu, page=page, turns=turns, message=message)
  1112. # TODO:
  1113. # Here comes the list_turns_by_user_id code
  1114. except AttributeError:
  1115. # User is not logged in
  1116. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1117. @app.route("/turn/new", methods=['GET', 'POST'])
  1118. @check_session
  1119. def new_turn():
  1120. """ New turn form """
  1121. tuesday = '2018-05-08'
  1122. wenesday = '2018-05-09'
  1123. thirsday = '2018-05-10'
  1124. friday = '2018-05-11'
  1125. saturday = '2018-05-12'
  1126. sunday = '2018-05-13'
  1127. monday = '2018-05-14'
  1128. try:
  1129. if session['is_admin']:
  1130. page = str(request.url_rule)
  1131. menu = get_menu(page)
  1132. roles = Tetawebapp_roles.query.order_by(Tetawebapp_roles.id).all()
  1133. days = [('Mardi', tuesday), ('Mercredi', wenesday), ('Jeudi', thirsday), ('Vendredi', friday), ('Samedi', saturday), ('Dimanche', sunday)]
  1134. return render_template('new_turn.html', menu=menu, page=page, roles=roles, days=days)
  1135. except AttributeError:
  1136. # User is not logged in
  1137. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1138. @app.route("/turn/add", methods=['GET', 'POST'])
  1139. @check_session
  1140. def add_turn():
  1141. """ Add staff turn """
  1142. try:
  1143. if session['is_admin']:
  1144. role_id = request.form.get('role_id').encode('utf-8')
  1145. day = request.form.get('day').encode('utf-8')
  1146. start = request.form.get('start').encode('utf-8')
  1147. end = request.form.get('end').encode('utf-8')
  1148. num_slot = request.form.get('num_slot').encode('utf-8')
  1149. page = str(request.url_rule)
  1150. menu = get_menu(page)
  1151. turns = turns_list()
  1152. message = "Erreur lors de l'enregistrement.".decode('utf-8')
  1153. if save_turn(role_id, day, start, end, num_slot):
  1154. turns = turns_list()
  1155. message=''
  1156. return render_template('list_turns.html', menu=menu, page=page, turns=turns, message=message)
  1157. # User is not admin
  1158. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1159. except AttributeError as e:
  1160. # User is not logged in
  1161. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1162. @app.route("/turn/<ID>", methods=['GET', 'POST'])
  1163. @check_session
  1164. def turn_by_id(ID):
  1165. try:
  1166. if session['is_admin']:
  1167. tuesday = '2018-05-08'
  1168. wenesday = '2018-05-09'
  1169. thirsday = '2018-05-10'
  1170. friday = '2018-05-11'
  1171. saturday = '2018-05-12'
  1172. sunday = '2018-05-13'
  1173. monday = '2018-05-14'
  1174. days = [('Mardi', tuesday), ('Mercredi', wenesday), ('Jeudi', thirsday), ('Vendredi', friday), ('Samedi', saturday), ('Dimanche', sunday)]
  1175. page = str(request.url_rule)
  1176. menu = get_menu(page)
  1177. roles = Tetawebapp_roles.query.order_by(Tetawebapp_roles.id).all()
  1178. message = 'ID du tour de staff non conforme'
  1179. turns = turns_list()
  1180. turn_id = int(ID.encode('utf-8'))
  1181. turn = get_turn_by_id(turn_id)
  1182. return render_template('turn_by_id.html', menu=menu, page=page, turn=turn, roles=roles, days=days)
  1183. except AttributeError:
  1184. # User is not logged in
  1185. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1186. except ValueError:
  1187. # ID is not an integer
  1188. return render_template('list_turns.html', menu=menu, page=page, turns=turns, message=message)
  1189. @app.route("/turn/update/<ID>", methods=['GET', 'POST'])
  1190. @check_session
  1191. def update_turn(ID):
  1192. """ Update given staff turn """
  1193. try:
  1194. role_id = request.form.get('role_id').encode('utf-8')
  1195. start = request.form.get('start').encode('utf-8')
  1196. end = request.form.get('end').encode('utf-8')
  1197. num_slot = request.form.get('num_slot').encode('utf-8')
  1198. day = request.form.get('day').encode('utf-8')
  1199. if session['is_admin']:
  1200. page = str(request.url_rule)
  1201. menu = get_menu(page)
  1202. turns = turns_list()
  1203. message = "Erreur lors de l'enregistrement.".decode('utf-8')
  1204. turn_id = int(ID.encode('utf-8'))
  1205. if update_turn_by_id(turn_id, role_id, day, start, end, num_slot):
  1206. turns = turns_list()
  1207. message = ''
  1208. return render_template('list_turns.html', menu=menu, page=page, turns=turns, message=message)
  1209. # User is not admin
  1210. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1211. except AttributeError as e:
  1212. # User is not logged in
  1213. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1214. except ValueError:
  1215. # ID is not an integer
  1216. return render_template('list_turns.html', menu=menu, page=page, turns=turns, message=message)
  1217. @app.route("/turn/delete/<ID>", methods=['GET', 'POST'])
  1218. @check_session
  1219. def delete_turn(ID):
  1220. """ Delete given staff turn """
  1221. try:
  1222. if session['is_admin']:
  1223. message = 'Erreur lors de la suppression.'
  1224. page = str(request.url_rule)
  1225. menu = get_menu(page)
  1226. turns = turns_list()
  1227. turn_id = int(ID.encode('utf-8'))
  1228. if drop_turn(turn_id):
  1229. message = ''
  1230. turns = turns_list()
  1231. return render_template('list_turns.html', menu=menu, turns=turns, message=message)
  1232. return render_template('list_turns.html', menu=menu, turns=turns, message=message)
  1233. # User is not admin
  1234. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1235. except AttributeError:
  1236. # User is not logged in
  1237. return render_template('login_or_register.html', message="Utilisateur ou mot de passe invalide")
  1238. except ValueError:
  1239. # ID is not an integer
  1240. return render_template('list_turns.html', menu=menu, page=page, turns=turns, message=message)
  1241. ########################################################################
  1242. # Main
  1243. ########################################################################
  1244. if __name__ == '__main__':
  1245. app.run(host='0.0.0.0')