51af2a92b32dc374556422f4fc034958bb0b3668
[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"
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/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('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('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 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 vote['percent'] = int((float(vote['nb_votes']) / float(vote['max_votes'])) * 100)
346 return render_template('votes.html', votes=votes, active_button=active_button)
347
348 #------
349 # Vote
350
351 def can_see_vote(idvote, iduser=-1):
352 vote = query_db('select * from votes where id=?', [idvote], one=True)
353 if vote is None:
354 return False
355 if not vote['is_public']:
356 user = query_db('select * from users where id=?', [iduser], one=True)
357 if query_db('select * from user_group where id_user = ? and id_group = ?', [iduser, vote['id']], one=True) is None:
358 return False
359 return True
360
361 def can_vote(idvote, iduser=-1):
362 vote = query_db('select * from votes where id=?', [idvote], one=True)
363 if vote is None:
364 return False
365 if vote['is_finished'] == 0:
366 if iduser > 0:
367 if can_see_vote(idvote, iduser):
368 if not has_voted(idvote, iduser):
369 if query_db('select * from user_group where id_user = ? and id_group = ?', [iduser, vote['id_group']], one=True):
370 return True
371 return False
372
373 def has_voted(idvote, iduser=-1):
374 vote = query_db('select * from user_choice join choices on id_choice=choices.id where id_vote = ? and id_user = ?', [idvote, iduser], one=True)
375 return (vote is not None)
376
377 @app.route('/vote/<idvote>', methods=['GET', 'POST'])
378 def vote(idvote):
379 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)
380 if vote is None:
381 abort(404)
382 if can_see_vote(idvote, get_userid()):
383 if request.method == 'POST':
384 if can_vote(idvote, get_userid()):
385 choices = query_db('select name, id from choices where id_vote=?', [idvote])
386 for choice in choices:
387 if str(choice['id']) in request.form.keys():
388 g.db.execute('insert into user_choice (id_user, id_choice) values (?, ?)',
389 [session.get('user').get('id'), choice['id']])
390 g.db.commit()
391 if vote['is_multiplechoice'] == 0:
392 break
393 else:
394 abort(401)
395 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])
396 users = dict()
397 for t in tuples:
398 if t['userid'] in users:
399 users[t['userid']]['choices'].append(t['choiceid'])
400 else:
401 users[t['userid']] = dict()
402 users[t['userid']]['userid'] = t['userid']
403 users[t['userid']]['username'] = t['username']
404 users[t['userid']]['choices'] = [t['choiceid']]
405 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])
406 attachments = query_db('select * from attachments where id_vote=?', [idvote])
407 tmp = query_db('select id_group, count(*) as nb from user_group where id_group = ? group by id_group', [vote['id_group']], one=True)
408 if tmp is None:
409 vote['percent'] = 0
410 else:
411 vote['max_votes'] = tmp['nb']
412 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)
413 if tmp is None:
414 vote['percent'] = 0
415 else:
416 vote['nb_votes'] = tmp['nb']
417 vote['percent'] = int((float(vote['nb_votes']) / float(vote['max_votes'])) * 100)
418 return render_template('vote.html', vote=vote, attachments=attachments, choices=choices, users=users.values(), can_vote=can_vote(idvote, get_userid()))
419 flash(u'Vous n\'avez pas le droit de voir ce vote, désolé.')
420 return redirect(url_for('home'))
421
422 @app.route('/vote/deletechoices/<idvote>/<iduser>')
423 def vote_deletechoices(idvote, iduser):
424 if int(iduser) != get_userid():
425 abort(401)
426 g.db.execute('delete from user_choice where id_user = ? and id_choice in (select id from choices where id_vote = ?)',
427 [iduser, idvote])
428 g.db.commit()
429 return redirect(url_for('vote', idvote=idvote))
430
431 #-------------
432 # Votes admin
433
434 @app.route('/admin/votes/list')
435 def admin_votes():
436 if not session.get('user').get('is_admin'):
437 abort(401)
438 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')
439 return render_template('admin_votes.html', votes=votes)
440
441 @app.route('/admin/votes/add', methods=['GET', 'POST'])
442 def admin_vote_add():
443 if not session.get('user').get('is_admin'):
444 abort(401)
445 if request.method == 'POST':
446 if request.form['title']:
447 if query_db('select * from votes where title = ?', [request.form['title']], one=True) is None:
448 date_begin = date.today()
449 date_end = date.today() + timedelta(days=int(request.form['days']))
450 transparent = 0
451 public = 0
452 multiplechoice = 0
453 if 'transparent' in request.form.keys():
454 transparent = 1
455 if 'public' in request.form.keys():
456 public = 1
457 if 'multiplechoice' in request.form.keys():
458 multiplechoice = 1
459 group = query_db('select id from groups where name = ?', [request.form['group']], one=True)
460 if group is None:
461 group[id] = 1
462 g.db.execute('insert into votes (title, description, category, date_begin, date_end, is_transparent, is_public, is_multiplechoice, id_group, id_author) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
463 [request.form['title'], request.form['description'], request.form['category'], date_begin, date_end, transparent, public, multiplechoice, group['id'], session['user']['id']])
464 g.db.commit()
465 vote = query_db('select * from votes where title = ? and date_begin = ? order by id desc',
466 [request.form['title'], date_begin], one=True)
467 if vote is None:
468 flash(u'Une erreur est survenue !', 'error')
469 return redirect(url_for('home'))
470 else:
471 if request.form['pattern'] in PATTERNS.keys():
472 pattern = PATTERNS[request.form['pattern']]
473 for choice in pattern:
474 g.db.execute('insert into choices (name, id_vote) values (?, ?)', [choice, vote['id']])
475 g.db.commit()
476 flash(u"Le vote a été créé", 'info')
477 return redirect(url_for('admin_vote_edit', voteid=vote['id']))
478 else:
479 flash(u'Le titre que vous avez choisi est déjà pris.', 'error')
480 else:
481 flash(u'Vous devez spécifier un titre.', 'error')
482 groups = query_db('select * from groups')
483 return render_template('admin_vote_new.html', groups=groups, patterns=PATTERNS)
484
485 @app.route('/admin/votes/edit/<voteid>', methods=['GET', 'POST'])
486 def admin_vote_edit(voteid):
487 if not session.get('user').get('is_admin'):
488 abort(401)
489 vote = query_db('select * from votes where id = ?', [voteid], one=True)
490 if vote is None:
491 abort(404)
492 if request.method == 'POST':
493 if request.form['title']:
494 # :TODO:maethor:120529: Calculer date_begin pour pouvoir y ajouter duration et obtenir date_end
495 transparent = 0
496 public = 0
497 if 'transparent' in request.form.keys():
498 transparent = 1
499 if 'public' in request.form.keys():
500 public = 1
501 isopen = 0
502 isterminated = 0
503 if request.form['status'] == 'Ouvert':
504 choices = query_db('select id_vote, count(*) as nb from choices where id_vote = ? group by id_vote', [voteid], one=True)
505 if choices is not None and choices['nb'] >= 2:
506 isopen = 1
507 else:
508 flash(u'Vous devez proposer au moins deux choix pour ouvrir le vote.', 'error')
509 elif request.form['status'] == u'Terminé':
510 isterminated = 1
511 if vote['is_open']:
512 isopen = 1
513 g.db.execute('update votes set title = ?, description = ?, category = ?, is_transparent = ?, is_public = ?, is_open = ?, is_terminated = ? where id = ?',
514 [request.form['title'], request.form['description'], request.form['category'], transparent, public, isopen, isterminated, voteid])
515 g.db.commit()
516 vote = query_db('select * from votes where id = ?', [voteid], one=True)
517 flash(u"Le vote a bien été mis à jour.", "success")
518 else:
519 flash(u'Vous devez spécifier un titre.', 'error')
520
521 # :TODO:maethor:120529: Calculer la durée du vote (différence date_end - date_begin)
522 vote['duration'] = 15
523 group = query_db('select name from groups where id = ?', [vote['id_group']], one=True)
524 choices = query_db('select * from choices where id_vote = ?', [voteid])
525 attachments = query_db('select * from attachments where id_vote = ?', [voteid])
526 return render_template('admin_vote_edit.html', vote=vote, group=group, choices=choices, attachments=attachments)
527
528 @app.route('/admin/votes/addchoice/<voteid>', methods=['POST'])
529 def admin_vote_addchoice(voteid):
530 if not session.get('user').get('is_admin'):
531 abort(401)
532 vote = query_db('select * from votes where id = ?', [voteid], one=True)
533 if vote is None:
534 abort(404)
535 g.db.execute('insert into choices (name, id_vote) values (?, ?)', [request.form['title'], voteid])
536 g.db.commit()
537 return redirect(url_for('admin_vote_edit', voteid=voteid))
538
539 @app.route('/admin/votes/editchoice/<voteid>/<choiceid>', methods=['POST', 'DELETE'])
540 def admin_vote_editchoice(voteid, choiceid):
541 if not session.get('user').get('is_admin'):
542 abort(401)
543 choice = query_db('select * from choices where id = ? and id_vote = ?', [choiceid, voteid], one=True)
544 if choice is None:
545 abort(404)
546 if request.method == 'POST':
547 g.db.execute('update choices set name=? where id = ? and id_vote = ?', [request.form['title'], choiceid, voteid])
548 g.db.commit()
549 return redirect(url_for('admin_vote_edit', voteid=voteid))
550
551 @app.route('/admin/votes/deletechoice/<voteid>/<choiceid>')
552 def admin_vote_deletechoice(voteid, choiceid):
553 if not session.get('user').get('is_admin'):
554 abort(401)
555 choice = query_db('select * from choices where id = ? and id_vote = ?', [choiceid, voteid], one=True)
556 if choice is None:
557 abort(404)
558 g.db.execute('delete from choices where id = ? and id_vote = ?', [choiceid, voteid])
559 g.db.commit()
560 choices = query_db('select id_vote, count(*) as nb from choices where id_vote = ? group by id_vote', [voteid], one=True)
561 if choices is None or choices['nb'] < 2:
562 g.db.execute('update votes set is_open=0 where id = ?', [voteid])
563 g.db.commit()
564 flash(u'Attention ! Il y a moins de deux choix. Le vote a été fermé.', 'error')
565 return redirect(url_for('admin_vote_edit', voteid=voteid))
566
567 @app.route('/admin/votes/addattachment/<voteid>', methods=['POST'])
568 def admin_vote_addattachment(voteid):
569 if not session.get('user').get('is_admin'):
570 abort(401)
571 vote = query_db('select * from votes where id = ?', [voteid], one=True)
572 if vote is None:
573 abort(404)
574 g.db.execute('insert into attachments (url, id_vote) values (?, ?)', [request.form['url'], voteid])
575 g.db.commit()
576 return redirect(url_for('admin_vote_edit', voteid=voteid))
577
578 @app.route('/admin/votes/deleteattachment/<voteid>/<attachmentid>')
579 def admin_vote_deleteattachment(voteid, attachmentid):
580 if not session.get('user').get('is_admin'):
581 abort(401)
582 attachment = query_db('select * from attachments where id = ? and id_vote = ?', [attachmentid, voteid], one=True)
583 if attachment is None:
584 abort(404)
585 g.db.execute('delete from attachments where id = ? and id_vote = ?', [attachmentid, voteid])
586 g.db.commit()
587 return redirect(url_for('admin_vote_edit', voteid=voteid))
588
589 #------
590 # Main
591
592 if __name__ == '__main__':
593 app.run()
594