Nb votes and max votes displayed in progress bar
[cavote.git] / main.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 from flask import Flask, request, session, g, redirect, url_for, abort, \
5 render_template, flash
6 import sqlite3
7 from datetime import date, time, timedelta
8 import time
9 from contextlib import closing
10 import locale
11 locale.setlocale(locale.LC_ALL, '')
12 import os
13 import hashlib
14 import smtplib
15 import string
16
17 DATABASE = '/tmp/cavote.db'
18 SECRET_KEY = '{J@uRKO,xO-PK7B,jF?>iHbxLasF9s#zjOoy=+:'
19 DEBUG = True
20 TITLE = u"Cavote FFDN"
21 EMAIL = '"' + TITLE + '"' + ' <' + u"cavote@ffdn.org" + '>'
22 BASEURL = "http://localhost:5000" # :TODO:maethor:120605: Find a cleaner way to do this
23 VERSION = "cavote 0.0.1"
24 SMTP_SERVER = "10.33.33.30"
25 PATTERNS = {u'Oui/Non': [u'Oui', u'Non'], u'Oui/Non/Blanc': [u'Oui', u'Non', u'Blanc'], u'Oui/Non/Peut-être': [u'Oui', u'Non', u'Peut-être']}
26
27 app = Flask(__name__)
28 app.config.from_object(__name__)
29
30 def connect_db():
31 return sqlite3.connect(app.config['DATABASE'])
32
33 @app.before_request
34 def before_request():
35 g.db = connect_db()
36 g.db.execute("PRAGMA foreign_keys = ON")
37
38 @app.teardown_request
39 def teardown_request(exception):
40 g.db.close()
41
42 @app.route('/')
43 def home():
44 return render_template('index.html', active_button="home")
45
46 def query_db(query, args=(), one=False):
47 cur = g.db.execute(query, args)
48 rv = [dict((cur.description[idx][0], value)
49 for idx, value in enumerate(row)) for row in cur.fetchall()]
50 return (rv[0] if rv else None) if one else rv
51
52 def init_db():
53 with closing(connect_db()) as db:
54 with app.open_resource('schema.sql') as f:
55 db.cursor().executescript(f.read())
56 db.commit()
57
58 #----------------
59 # Login / Logout
60
61 def valid_login(username, password):
62 return query_db('select * from users where email = ? and password = ?', [username, crypt(password)], one=True)
63
64 def connect_user(user):
65 session['user'] = user
66 del session['user']['password']
67 del session['user']['key']
68
69 def disconnect_user():
70 session.pop('user', None)
71
72 def crypt(passwd):
73 return hashlib.sha1(passwd).hexdigest()
74
75 def keygen():
76 return hashlib.sha1(os.urandom(24)).hexdigest()
77
78 def get_userid():
79 user = session.get('user')
80 if user is None:
81 return -1
82 elif user.get('id') < 0:
83 return -1
84 else:
85 return user.get('id')
86
87 @app.route('/login', methods=['GET', 'POST'])
88 def login():
89 if request.method == 'POST':
90 user = valid_login(request.form['username'], request.form['password'])
91 if user is None:
92 flash(u'Email ou mot de passe invalide.', 'error')
93 else:
94 connect_user(user)
95 flash(u'Vous êtes connecté. Bienvenue, %s !' % user['name'], 'success')
96 return redirect(url_for('home'))
97 return render_template('login.html')
98
99 @app.route('/logout')
100 def logout():
101 disconnect_user()
102 flash(u'Vous avez été déconnecté.', 'info')
103 return redirect(url_for('home'))
104
105 #-----------------
106 # Change password
107
108 @app.route('/password/lost', methods=['GET', 'POST'])
109 def password_lost():
110 info = None
111 if request.method == 'POST':
112 user = query_db('select * from users where email = ?', [request.form['email']], one=True)
113 if user is None:
114 flash('Cet utilisateur n\'existe pas !', 'error')
115 else:
116 key = keygen()
117 g.db.execute('update users set key = ? where id = ?', [key, user['id']])
118 g.db.commit()
119 link = BASEURL + url_for('login_key', userid=user['id'], key=key)
120 BODY = string.join((
121 "From: %s" % EMAIL,
122 "To: %s" % user['email'],
123 "Subject: [Cavote] Password lost",
124 "Date: %s" % time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()),
125 "X-Mailer: %s" % VERSION,
126 "",
127 "You have lost your password.",
128 "This link will log you without password.",
129 "Don't forget to define a new one as soon a possible!",
130 "This link will only work one time.",
131 "",
132 link,
133 "",
134 "If you think this mail is not for you, please ignore and delete it."
135 ), "\r\n")
136 server = smtplib.SMTP(SMTP_SERVER)
137 server.sendmail(EMAIL, [user['email']], BODY)
138 server.quit()
139 flash(u"Un mail a été envoyé à " + user['email'], 'info')
140 return render_template('password_lost.html')
141
142 @app.route('/login/<userid>/<key>')
143 def login_key(userid, key):
144 user = query_db('select * from users where id = ? and key = ?', [userid, key], one=True)
145 if user is None or user['key'] == "invalid":
146 abort(404)
147 else:
148 connect_user(user)
149 g.db.execute('update users set key = "invalid" where id = ?', [user['id']])
150 g.db.commit()
151 flash(u"Veuillez mettre à jour votre mot de passe", 'info')
152 return redirect(url_for('user_password', userid=user['id']))
153
154 #---------------
155 # User settings
156
157 @app.route('/user/<userid>')
158 def user(userid):
159 if int(userid) != get_userid():
160 abort(401)
161 groups = query_db('select * from groups join user_group on id=id_group where id_user = ?', userid)
162 return render_template('user.html', groups=groups)
163
164 @app.route('/user/settings/<userid>', methods=['GET', 'POST'])
165 def user_edit(userid):
166 if int(userid) != get_userid():
167 abort(401)
168 if request.method == 'POST':
169 if query_db('select * from users where email=? and id!=?', [request.form['email'], userid], one=True) is None:
170 if query_db('select * from users where name=? and id!=?', [request.form['name'], userid], one=True) is None:
171 g.db.execute('update users set email = ?, name = ?, organization = ? where id = ?',
172 [request.form['email'], request.form['name'], request.form['organization'], session['user']['id']])
173 g.db.commit()
174 disconnect_user()
175 user = query_db('select * from users where id=?', [userid], one=True)
176 if user is None:
177 flash(u'Une erreur s\'est produite.', 'error')
178 return redirect(url_for('login'))
179 connect_user(user)
180 flash(u'Votre profil a été mis à jour !', 'success')
181 else:
182 flash(u'Le nom ' + request.form['name'] + u' est déjà pris ! Veuillez en choisir un autre.', 'error')
183 else:
184 flash(u'Il existe déjà un compte pour cette adresse e-mail : ' + request.form['email'], 'error')
185 return render_template('user_edit.html')
186
187 @app.route('/user/password/<userid>', methods=['GET', 'POST'])
188 def user_password(userid):
189 if int(userid) != get_userid():
190 abort(401)
191 if request.method == 'POST':
192 if request.form['password'] == request.form['password2']:
193 g.db.execute('update users set password = ? where id = ?', [crypt(request.form['password']), session['user']['id']])
194 g.db.commit()
195 flash(u'Votre mot de passe a été mis à jour.', 'success')
196 else:
197 flash(u'Les mots de passe sont différents.', 'error')
198 return render_template('user_edit.html')
199
200 #------------
201 # User admin
202
203 @app.route('/admin/users')
204 def admin_users():
205 if not session.get('user').get('is_admin'):
206 abort(401)
207 tuples = query_db('select *, groups.name as groupname from (select *, id as userid, name as username from users join user_group on id=id_user order by id desc) join groups on id_group=groups.id')
208 users = dict()
209 for t in tuples:
210 if t['userid'] in users:
211 users[t['userid']]['groups'].append(t["groupname"])
212 else:
213 users[t['userid']] = dict()
214 users[t['userid']]['userid'] = t['userid']
215 users[t['userid']]['email'] = t['email']
216 users[t['userid']]['username'] = t['username']
217 users[t['userid']]['is_admin'] = t['is_admin']
218 users[t['userid']]['groups'] = [t['groupname']]
219
220 return render_template('admin_users.html', users=users.values())
221
222 @app.route('/admin/users/add', methods=['GET', 'POST'])
223 def admin_user_add():
224 if not session.get('user').get('is_admin'):
225 abort(401)
226 if request.method == 'POST':
227 if request.form['email']:
228 if query_db('select * from users where email=?', [request.form['email']], one=True) is None:
229 if request.form['username']:
230 if query_db('select * from users where name=?', [request.form['username']], one=True) is None:
231 password = keygen()
232 admin = 0
233 if 'admin' in request.form.keys():
234 admin = 1
235 key = keygen()
236 g.db.execute('insert into users (email, name, organization, password, is_admin, key) values (?, ?, ?, ?, ?, ?)',
237 [request.form['email'], request.form['username'], request.form['organization'], password, admin, key])
238 g.db.commit()
239 user = query_db('select * from users where email = ?', [request.form["email"]], one=True)
240 if user:
241 groups = request.form.getlist('groups')
242 groups.append('1')
243 for group in groups:
244 if query_db('select id from groups where id = ?', group, one=True) is None:
245 flash(u'Le groupe portant l\'id %s n\'existe pas.' % group, 'warning')
246 else:
247 g.db.execute('insert into user_group values (?, ?)', [user['id'], group])
248 g.db.commit()
249 link = BASEURL + url_for('login_key', userid=user['id'], key=user['key'])
250 BODY = string.join((
251 "From: %s" % EMAIL,
252 "To: %s" % user['email'],
253 "Subject: [Cavote] Welcome",
254 "Date: %s" % time.strftime("%a, %d %b %Y %H:%M:%S +0000", time.gmtime()),
255 "X-Mailer: %s" % VERSION,
256 "",
257 "Hi %s!" % user['name'],
258 "Welcome on %s." % TITLE,
259 "Your account's adresse is : %s." % user['email'],
260 "",
261 "To log in for the first time and set your password, please follow this link :",
262 link,
263 ""
264 ), "\r\n")
265 server = smtplib.SMTP(SMTP_SERVER)
266 server.sendmail(EMAIL, [user['email']], BODY)
267 server.quit()
268 flash(u'Le nouvel utilisateur a été créé avec succès', 'success')
269 return redirect(url_for('admin_users'))
270 else:
271 flash(u'Une erreur s\'est produite.', 'error')
272 else:
273 flash(u'Le nom ' + request.form['username'] + u' est déjà pris ! Veuillez en choisir un autre.', 'error')
274 else:
275 flash(u"Vous devez spécifier un nom d'utilisateur.", 'error')
276 else:
277 flash(u'Il existe déjà un compte pour cette adresse e-mail : ' + request.form['email'], 'error')
278 else:
279 flash(u"Vous devez spécifier une adresse email.", 'error')
280 groups = query_db('select * from groups where system=0')
281 return render_template('admin_user_new.html', groups=groups)
282
283 #-------------
284 # Roles admin
285
286 @app.route('/admin/groups')
287 def admin_groups():
288 if not session.get('user').get('is_admin'):
289 abort(401)
290 groups = query_db('select * from groups')
291 return render_template('admin_groups.html', groups=groups)
292
293 @app.route('/admin/groups/add', methods=['POST'])
294 def admin_group_add():
295 if not session.get('user').get('is_admin'):
296 abort(401)
297 if request.method == 'POST':
298 if request.form['name']:
299 g.db.execute('insert into groups (name) values (?)', [request.form['name']])
300 g.db.commit()
301 else:
302 flash(u"Vous devez spécifier un nom.", "error")
303 return redirect(url_for('admin_groups'))
304
305 @app.route('/admin/groups/delete/<idgroup>')
306 def admin_group_del(idgroup):
307 if not session.get('user').get('is_admin'):
308 abort(401)
309 group = query_db('select * from groups where id = ?', [idgroup], one=True)
310 if group is None:
311 abort(404)
312 if group['system']:
313 abort(401)
314 g.db.execute('delete from groups where id = ?', [idgroup])
315 g.db.commit()
316 return redirect(url_for('admin_groups'))
317
318 #------------
319 # Votes list
320
321 @app.route('/votes/<votes>')
322 def votes(votes):
323 today = date.today()
324 active_button = votes
325 max_votes ='select id_group, count(*) as max_votes from user_group group by id_group'
326 basequery = 'select votes.*, max_votes from votes left join (' + max_votes + ') as max_votes on votes.id_group = max_votes.id_group'
327 nb_votes = 'select id_vote, count(*) as nb_votes from (select id_user, id_vote from user_choice join choices on id_choice = choices.id group by id_user, id_vote) group by id_vote'
328 basequery = 'select * from (' + basequery + ') left join (' + nb_votes + ') on id = id_vote'
329 basequery = 'select *, votes.id as voteid, groups.name as groupname from (' + basequery + ') as votes join groups on groups.id = id_group where is_open=1'
330 if votes == 'all':
331 votes = query_db(basequery + ' order by id desc')
332 elif votes == 'archive':
333 votes = query_db(basequery + ' and is_terminated=1 order by id desc')
334 elif votes == 'current':
335 votes = query_db(basequery + ' and is_terminated=0 order by id desc')
336 elif votes == 'waiting':
337 basequery = 'select votes.* from user_group join (' + basequery + ') as votes on votes.id_group = user_group.id_group where user_group.id_user = ?'
338 already_voted = 'select id_vote from user_choice join choices on user_choice.id_choice = choices.id where id_user = ?'
339 votes = query_db(basequery + ' and votes.id not in (' + already_voted + ') and is_terminated=0', [get_userid(), get_userid()])
340 else:
341 abort(404)
342 for vote in votes:
343 if not vote.get('nb_votes'):
344 vote['nb_votes'] = 0
345 if vote.get('max_votes'):
346 vote['percent'] = int((float(vote['nb_votes']) / float(vote['max_votes'])) * 100)
347 return render_template('votes.html', votes=votes, active_button=active_button)
348
349 #------
350 # Vote
351
352 def can_see_vote(idvote, iduser=-1):
353 vote = query_db('select * from votes where id=?', [idvote], one=True)
354 if vote is None:
355 return False
356 if not vote['is_public']:
357 user = query_db('select * from users where id=?', [iduser], one=True)
358 if query_db('select * from user_group where id_user = ? and id_group = ?', [iduser, vote['id']], one=True) is None:
359 return False
360 return True
361
362 def can_vote(idvote, iduser=-1):
363 vote = query_db('select * from votes where id=?', [idvote], one=True)
364 if vote is None:
365 return False
366 if vote['is_terminated'] == 0:
367 if iduser > 0:
368 if can_see_vote(idvote, iduser):
369 if not has_voted(idvote, iduser):
370 if query_db('select * from user_group where id_user = ? and id_group = ?', [iduser, vote['id_group']], one=True):
371 return True
372 return False
373
374 def has_voted(idvote, iduser=-1):
375 vote = query_db('select * from user_choice join choices on id_choice=choices.id where id_vote = ? and id_user = ?', [idvote, iduser], one=True)
376 return (vote is not None)
377
378 @app.route('/vote/<idvote>', methods=['GET', 'POST'])
379 def vote(idvote):
380 vote = query_db('select votes.*, groups.name as groupname from votes join groups on groups.id=votes.id_group where votes.id=?', [idvote], one=True)
381 if vote is None:
382 abort(404)
383 if can_see_vote(idvote, get_userid()):
384 if request.method == 'POST':
385 if can_vote(idvote, get_userid()):
386 if vote['is_multiplechoice'] == 0:
387 if query_db('select * from choices where id = ?', [request.form['choice']], one=True) is not None:
388 g.db.execute('insert into user_choice (id_user, id_choice) values (?, ?)',
389 [session.get('user').get('id'), request.form['choice']])
390 g.db.commit()
391 else:
392 choices = query_db('select name, id from choices where id_vote=?', [idvote])
393 for choice in choices:
394 if str(choice['id']) in request.form.keys():
395 g.db.execute('insert into user_choice (id_user, id_choice) values (?, ?)',
396 [session.get('user').get('id'), choice['id']])
397 g.db.commit()
398 else:
399 abort(401)
400 tuples = query_db('select choiceid, choicename, users.id as userid, users.name as username from (select choices.id as choiceid, choices.name as choicename, id_user as userid from choices join user_choice on choices.id = user_choice.id_choice where id_vote = ?) join users on userid = users.id', [idvote])
401 users = dict()
402 for t in tuples:
403 if t['userid'] in users:
404 users[t['userid']]['choices'].append(t['choiceid'])
405 else:
406 users[t['userid']] = dict()
407 users[t['userid']]['userid'] = t['userid']
408 users[t['userid']]['username'] = t['username']
409 users[t['userid']]['choices'] = [t['choiceid']]
410 choices = query_db('select choices.name, choices.id, choices.name, choices.id_vote, count(id_choice) as nb from choices left join user_choice on id_choice = choices.id where id_vote = ? group by id_choice, name, id_vote order by id', [idvote])
411 attachments = query_db('select * from attachments where id_vote=?', [idvote])
412 tmp = query_db('select id_group, count(*) as nb from user_group where id_group = ? group by id_group', [vote['id_group']], one=True)
413 if tmp is None:
414 vote['percent'] = 0
415 else:
416 vote['max_votes'] = tmp['nb']
417 tmp = query_db('select id_vote, count(*) as nb from (select id_user, id_vote from user_choice join choices on id_choice = choices.id group by id_user, id_vote) where id_vote = ? group by id_vote', [idvote], one=True)
418 if tmp is None:
419 vote['percent'] = 0
420 vote['nb_votes'] = 0
421 else:
422 vote['nb_votes'] = tmp['nb']
423 vote['percent'] = int((float(vote['nb_votes']) / float(vote['max_votes'])) * 100)
424 return render_template('vote.html', vote=vote, attachments=attachments, choices=choices, users=users.values(), can_vote=can_vote(idvote, get_userid()))
425 flash(u'Vous n\'avez pas le droit de voir ce vote, désolé.')
426 return redirect(url_for('home'))
427
428 @app.route('/vote/deletechoices/<idvote>/<iduser>')
429 def vote_deletechoices(idvote, iduser):
430 if int(iduser) != get_userid():
431 abort(401)
432 g.db.execute('delete from user_choice where id_user = ? and id_choice in (select id from choices where id_vote = ?)',
433 [iduser, idvote])
434 g.db.commit()
435 return redirect(url_for('vote', idvote=idvote))
436
437 #-------------
438 # Votes admin
439
440 @app.route('/admin/votes/list')
441 def admin_votes():
442 if not session.get('user').get('is_admin'):
443 abort(401)
444 votes = query_db('select *, votes.id as voteid, groups.name as groupname from votes join groups on groups.id=votes.id_group order by id desc')
445 return render_template('admin_votes.html', votes=votes)
446
447 @app.route('/admin/votes/add', methods=['GET', 'POST'])
448 def admin_vote_add():
449 if not session.get('user').get('is_admin'):
450 abort(401)
451 if request.method == 'POST':
452 if request.form['title']:
453 if query_db('select * from votes where title = ?', [request.form['title']], one=True) is None:
454 date_begin = date.today()
455 date_end = date.today() + timedelta(days=int(request.form['days']))
456 transparent = 0
457 public = 0
458 multiplechoice = 0
459 if 'transparent' in request.form.keys():
460 transparent = 1
461 if 'public' in request.form.keys():
462 public = 1
463 if 'multiplechoice' in request.form.keys():
464 multiplechoice = 1
465 group = query_db('select id from groups where name = ?', [request.form['group']], one=True)
466 if group is None:
467 group[id] = 1
468 g.db.execute('insert into votes (title, description, category, date_begin, date_end, is_transparent, is_public, is_multiplechoice, id_group, id_author) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
469 [request.form['title'], request.form['description'], request.form['category'], date_begin, date_end, transparent, public, multiplechoice, group['id'], session['user']['id']])
470 g.db.commit()
471 vote = query_db('select * from votes where title = ? and date_begin = ? order by id desc',
472 [request.form['title'], date_begin], one=True)
473 if vote is None:
474 flash(u'Une erreur est survenue !', 'error')
475 return redirect(url_for('home'))
476 else:
477 if request.form['pattern'] in PATTERNS.keys():
478 pattern = PATTERNS[request.form['pattern']]
479 for choice in pattern:
480 g.db.execute('insert into choices (name, id_vote) values (?, ?)', [choice, vote['id']])
481 g.db.commit()
482 flash(u"Le vote a été créé", 'info')
483 return redirect(url_for('admin_vote_edit', voteid=vote['id']))
484 else:
485 flash(u'Le titre que vous avez choisi est déjà pris.', 'error')
486 else:
487 flash(u'Vous devez spécifier un titre.', 'error')
488 groups = query_db('select * from groups')
489 return render_template('admin_vote_new.html', groups=groups, patterns=PATTERNS)
490
491 @app.route('/admin/votes/edit/<voteid>', methods=['GET', 'POST'])
492 def admin_vote_edit(voteid):
493 if not session.get('user').get('is_admin'):
494 abort(401)
495 vote = query_db('select * from votes where id = ?', [voteid], one=True)
496 if vote is None:
497 abort(404)
498 if request.method == 'POST':
499 if request.form['title']:
500 # :TODO:maethor:120529: Calculer date_begin pour pouvoir y ajouter duration et obtenir date_end
501 transparent = 0
502 public = 0
503 if 'transparent' in request.form.keys():
504 transparent = 1
505 if 'public' in request.form.keys():
506 public = 1
507 isopen = 0
508 isterminated = 0
509 if request.form['status'] == 'Ouvert':
510 choices = query_db('select id_vote, count(*) as nb from choices where id_vote = ? group by id_vote', [voteid], one=True)
511 if choices is not None and choices['nb'] >= 2:
512 isopen = 1
513 else:
514 flash(u'Vous devez proposer au moins deux choix pour ouvrir le vote.', 'error')
515 elif request.form['status'] == u'Terminé':
516 isterminated = 1
517 if vote['is_open']:
518 isopen = 1
519 g.db.execute('update votes set title = ?, description = ?, category = ?, is_transparent = ?, is_public = ?, is_open = ?, is_terminated = ? where id = ?',
520 [request.form['title'], request.form['description'], request.form['category'], transparent, public, isopen, isterminated, voteid])
521 g.db.commit()
522 vote = query_db('select * from votes where id = ?', [voteid], one=True)
523 flash(u"Le vote a bien été mis à jour.", "success")
524 else:
525 flash(u'Vous devez spécifier un titre.', 'error')
526
527 # :TODO:maethor:120529: Calculer la durée du vote (différence date_end - date_begin)
528 vote['duration'] = 15
529 group = query_db('select name from groups where id = ?', [vote['id_group']], one=True)
530 choices = query_db('select * from choices where id_vote = ?', [voteid])
531 attachments = query_db('select * from attachments where id_vote = ?', [voteid])
532 return render_template('admin_vote_edit.html', vote=vote, group=group, choices=choices, attachments=attachments)
533
534 @app.route('/admin/votes/addchoice/<voteid>', methods=['POST'])
535 def admin_vote_addchoice(voteid):
536 if not session.get('user').get('is_admin'):
537 abort(401)
538 vote = query_db('select * from votes where id = ?', [voteid], one=True)
539 if vote is None:
540 abort(404)
541 g.db.execute('insert into choices (name, id_vote) values (?, ?)', [request.form['title'], voteid])
542 g.db.commit()
543 return redirect(url_for('admin_vote_edit', voteid=voteid))
544
545 @app.route('/admin/votes/editchoice/<voteid>/<choiceid>', methods=['POST', 'DELETE'])
546 def admin_vote_editchoice(voteid, choiceid):
547 if not session.get('user').get('is_admin'):
548 abort(401)
549 choice = query_db('select * from choices where id = ? and id_vote = ?', [choiceid, voteid], one=True)
550 if choice is None:
551 abort(404)
552 if request.method == 'POST':
553 g.db.execute('update choices set name=? where id = ? and id_vote = ?', [request.form['title'], choiceid, voteid])
554 g.db.commit()
555 return redirect(url_for('admin_vote_edit', voteid=voteid))
556
557 @app.route('/admin/votes/deletechoice/<voteid>/<choiceid>')
558 def admin_vote_deletechoice(voteid, choiceid):
559 if not session.get('user').get('is_admin'):
560 abort(401)
561 choice = query_db('select * from choices where id = ? and id_vote = ?', [choiceid, voteid], one=True)
562 if choice is None:
563 abort(404)
564 g.db.execute('delete from choices where id = ? and id_vote = ?', [choiceid, voteid])
565 g.db.commit()
566 choices = query_db('select id_vote, count(*) as nb from choices where id_vote = ? group by id_vote', [voteid], one=True)
567 if choices is None or choices['nb'] < 2:
568 g.db.execute('update votes set is_open=0 where id = ?', [voteid])
569 g.db.commit()
570 flash(u'Attention ! Il y a moins de deux choix. Le vote a été fermé.', 'error')
571 return redirect(url_for('admin_vote_edit', voteid=voteid))
572
573 @app.route('/admin/votes/addattachment/<voteid>', methods=['POST'])
574 def admin_vote_addattachment(voteid):
575 if not session.get('user').get('is_admin'):
576 abort(401)
577 vote = query_db('select * from votes where id = ?', [voteid], one=True)
578 if vote is None:
579 abort(404)
580 g.db.execute('insert into attachments (url, id_vote) values (?, ?)', [request.form['url'], voteid])
581 g.db.commit()
582 return redirect(url_for('admin_vote_edit', voteid=voteid))
583
584 @app.route('/admin/votes/deleteattachment/<voteid>/<attachmentid>')
585 def admin_vote_deleteattachment(voteid, attachmentid):
586 if not session.get('user').get('is_admin'):
587 abort(401)
588 attachment = query_db('select * from attachments where id = ? and id_vote = ?', [attachmentid, voteid], one=True)
589 if attachment is None:
590 abort(404)
591 g.db.execute('delete from attachments where id = ? and id_vote = ?', [attachmentid, voteid])
592 g.db.commit()
593 return redirect(url_for('admin_vote_edit', voteid=voteid))
594
595 #------
596 # Main
597
598 if __name__ == '__main__':
599 app.run()
600