Revision 97f6d842
Ajout d'un test visant à empêcher l'utilisateur d'opérer un changement sur un évènement corrélé sans avoir pris connaissance au préalable d'éventuelles modifications intervenues depuis le chargement de la page.
git-svn-id: https://vigilo-dev.si.c-s.fr/svn@1667 b22e2e97-25c9-44ff-b637-2e5ceca36478
vigiboard/controllers/root.py | ||
---|---|---|
7 | 7 |
from tw.forms import validators |
8 | 8 |
from pylons.i18n import ugettext as _ |
9 | 9 |
from pylons.i18n import lazy_ugettext as l_ |
10 |
from tg.i18n import get_lang |
|
11 | 10 |
from pylons.controllers.util import abort |
12 | 11 |
from sqlalchemy import not_, and_, asc |
13 | 12 |
from sqlalchemy.orm import aliased |
13 |
from sqlalchemy.sql import func |
|
14 | 14 |
from datetime import datetime |
15 |
from time import mktime |
|
15 | 16 |
import math |
16 | 17 |
import urllib |
17 | 18 |
|
... | ... | |
27 | 28 |
from vigilo.models.functions import sql_escape_like |
28 | 29 |
from vigilo.models.secondary_tables import HOST_GROUP_TABLE, \ |
29 | 30 |
SERVICE_GROUP_TABLE |
30 |
from vigilo.common.conf import settings |
|
31 | 31 |
from vigiboard.lib.base import BaseController |
32 | 32 |
|
33 |
__all__ = ('RootController', ) |
|
33 |
__all__ = ('RootController', 'get_last_modification_timestamp', |
|
34 |
'date_to_timestamp') |
|
34 | 35 |
|
35 | 36 |
class RootController(VigiboardRootController): |
36 | 37 |
""" |
... | ... | |
84 | 85 |
|
85 | 86 |
username = request.environ['repoze.who.identity']['repoze.who.userid'] |
86 | 87 |
user = User.by_user_name(username) |
87 |
|
|
88 |
# TODO: Utiliser le champ "language" du modèle pour cet utilisateur ? |
|
89 |
# On récupère la langue du navigateur de l'utilisateur |
|
90 |
lang = get_lang() |
|
91 |
if not lang: |
|
92 |
lang = settings['VIGILO_ALL_DEFAULT_LANGUAGE'] |
|
93 |
else: |
|
94 |
lang = lang[0] |
|
95 | 88 |
|
96 |
aggregates = VigiboardRequest(user, lang)
|
|
89 |
aggregates = VigiboardRequest(user) |
|
97 | 90 |
|
98 | 91 |
search = { |
99 | 92 |
'host': '', |
... | ... | |
408 | 401 |
Cela peut être un changement de ticket ou un changement de statut. |
409 | 402 |
|
410 | 403 |
@param krgv['id']: Le ou les identifiants des événements à traiter |
404 |
@param krgv['last_modification']: La date de la dernière modification |
|
405 |
dont l'utilisateur est au courant. |
|
411 | 406 |
@param krgv['tt']: Nouveau numéro du ticket associé. |
412 | 407 |
@param krgv['status']: Nouveau status de/des événements. |
413 | 408 |
""" |
414 |
|
|
415 |
# Si l'utilisateur édite plusieurs événements à la fois, |
|
416 |
# il nous faut chacun des identifiants |
|
417 | 409 |
|
410 |
# On vérifie que des identifiants ont bien été transmis via |
|
411 |
# le formulaire, et on informe l'utilisateur le cas échéant. |
|
418 | 412 |
if krgv['id'] is None: |
419 | 413 |
flash(_('No event has been selected'), 'warning') |
420 | 414 |
raise redirect(request.environ.get('HTTP_REFERER', url('/'))) |
421 |
|
|
422 | 415 |
ids = krgv['id'].split(',') |
416 |
|
|
417 |
# Si des changements sont survenus depuis que la |
|
418 |
# page est affichée, on en informe l'utilisateur. |
|
419 |
if datetime.fromtimestamp(float(krgv['last_modification'])) \ |
|
420 |
< get_last_modification_timestamp(ids): |
|
421 |
flash(_('Changes have occurred since the page was displayed, ' |
|
422 |
'please refresh it.'), 'warning') |
|
423 |
print "\n\n\n\n ##### ", datetime.fromtimestamp(float(krgv['last_modification'])), " #####" |
|
424 |
print "##### ", get_last_modification_timestamp(ids), "\n\n\n\n" |
|
425 |
raise redirect(request.environ.get('HTTP_REFERER', url('/'))) |
|
426 |
|
|
427 |
# Si l'utilisateur édite plusieurs événements à la fois, |
|
428 |
# il nous faut chacun des identifiants |
|
423 | 429 |
|
424 | 430 |
if len(ids) > 1 : |
425 | 431 |
ids = ids[:-1] |
... | ... | |
435 | 441 |
|
436 | 442 |
# Modification des événements et création d'un historique |
437 | 443 |
# pour chacun d'eux. |
438 |
username = request.environ['repoze.who.identity']['repoze.who.userid'] |
|
439 |
|
|
440 | 444 |
for req in events.req: |
441 | 445 |
if isinstance(req, CorrEvent): |
442 | 446 |
event = req |
... | ... | |
457 | 461 |
DBSession.add(history) |
458 | 462 |
event.trouble_ticket = krgv['trouble_ticket'] |
459 | 463 |
|
460 |
if krgv['status'] != 'NoChange' :
|
|
464 |
if krgv['ack'] != 'NoChange' :
|
|
461 | 465 |
history = EventHistory( |
462 | 466 |
type_action="Acknowlegement change state", |
463 | 467 |
idevent=event.idcause, |
464 |
value=krgv['status'],
|
|
468 |
value=krgv['ack'],
|
|
465 | 469 |
text=_("Changed acknowledgement status from '%s' to '%s'") % ( |
466 |
event.status, krgv['status']
|
|
470 |
event.status, krgv['ack']
|
|
467 | 471 |
), |
468 | 472 |
username=username, |
469 | 473 |
timestamp=datetime.now(), |
470 | 474 |
) |
471 | 475 |
DBSession.add(history) |
472 |
event.status = krgv['status']
|
|
476 |
event.status = krgv['ack']
|
|
473 | 477 |
|
474 | 478 |
DBSession.flush() |
475 | 479 |
flash(_('Updated successfully')) |
... | ... | |
528 | 532 |
session['theme'] = theme |
529 | 533 |
session.save() |
530 | 534 |
return dict() |
531 |
|
|
535 |
|
|
536 |
def get_last_modification_timestamp(event_id_list): |
|
537 |
""" |
|
538 |
Récupère le timestamp de la dernière modification |
|
539 |
opérée sur l'un des événements dont l'identifiant |
|
540 |
fait partie de la liste passée en paramètre. |
|
541 |
""" |
|
542 |
last_modification_timestamp = DBSession.query( |
|
543 |
func.max(EventHistory.timestamp), |
|
544 |
).filter(EventHistory.idevent.in_(event_id_list) |
|
545 |
).scalar() |
|
546 |
|
|
547 |
return last_modification_timestamp |
|
548 |
|
|
549 |
def date_to_timestamp(date): |
|
550 |
""" |
|
551 |
Convertit une date en timestamp (décimal) |
|
552 |
""" |
|
553 |
return mktime(date.timetuple()) + date.microsecond / 1000000.0 |
vigiboard/controllers/vigiboardrequest.py | ||
---|---|---|
15 | 15 |
from vigiboard.widgets.edit_event import EditEventForm |
16 | 16 |
from vigiboard.widgets.search_form import SearchForm |
17 | 17 |
from vigiboard.controllers.vigiboard_plugin import VigiboardRequestPlugin |
18 |
from vigilo.common.conf import settings |
|
19 |
from tg.i18n import get_lang |
|
18 | 20 |
from pylons.i18n import ugettext as _ |
19 | 21 |
|
20 | 22 |
class VigiboardRequest(): |
... | ... | |
29 | 31 |
'AAClosed': '_Ack', |
30 | 32 |
} |
31 | 33 |
|
32 |
def __init__(self, user, lang):
|
|
34 |
def __init__(self, user): |
|
33 | 35 |
""" |
34 | 36 |
Initialisation de toutes les variables nécessaires : |
35 | 37 |
- la liste des groupes de l'utilisateur, |
... | ... | |
38 | 40 |
- la liste des plugins à appliquer. |
39 | 41 |
""" |
40 | 42 |
|
43 |
# TODO: Utiliser le champ "language" du modèle pour cet utilisateur ? |
|
44 |
# On récupère la langue du navigateur de l'utilisateur |
|
45 |
lang = get_lang() |
|
46 |
if not lang: |
|
47 |
lang = settings['VIGILO_ALL_DEFAULT_LANGUAGE'] |
|
48 |
else: |
|
49 |
lang = lang[0] |
|
50 |
|
|
41 | 51 |
self.user_groups = user.groups |
42 | 52 |
self.lang = lang |
43 | 53 |
self.generaterq = False |
... | ... | |
443 | 453 |
formulaires nécessaire au fonctionnement de Vigiboard |
444 | 454 |
""" |
445 | 455 |
|
456 |
from vigiboard.controllers.root import get_last_modification_timestamp |
|
457 |
from vigiboard.controllers.root import date_to_timestamp |
|
458 |
|
|
446 | 459 |
# Dialogue d'édition |
447 | 460 |
tmpl_context.edit_event_form = EditEventForm('edit_event_form', |
448 |
action=url('/update')) |
|
461 |
last_modification=date_to_timestamp( |
|
462 |
get_last_modification_timestamp(self.idevents)), |
|
463 |
action=url('/update'), |
|
464 |
) |
|
449 | 465 |
|
450 | 466 |
# Dialogue de recherche |
451 | 467 |
tmpl_context.search_form = SearchForm('search_form', lang=self.lang, |
vigiboard/widgets/edit_event.py | ||
---|---|---|
3 | 3 |
"""Le formulaire d'édition d'un événement.""" |
4 | 4 |
|
5 | 5 |
from pylons.i18n import lazy_ugettext as l_ |
6 |
from tw.forms import TableForm, SingleSelectField, TextField, HiddenField |
|
6 |
from tw.forms import TableForm, SingleSelectField, TextField, \ |
|
7 |
HiddenField, SubmitButton |
|
7 | 8 |
from tw.api import WidgetsList |
8 | 9 |
|
9 | 10 |
__all__ = ('EditEventForm', 'edit_event_status_options') |
... | ... | |
22 | 23 |
Affiche une zone de texte pour le Trouble Ticket et une |
23 | 24 |
liste déroulante pour le nouveau status |
24 | 25 |
""" |
25 |
class fields(WidgetsList): |
|
26 |
id = HiddenField() |
|
27 |
trouble_ticket = TextField(label_text=l_('Trouble Ticket')) |
|
28 |
ack = SingleSelectField(label_text=l_('Status'), |
|
29 |
options=edit_event_status_options) |
|
26 |
|
|
27 |
# class fields(WidgetsList): |
|
28 |
# id = HiddenField() |
|
29 |
# trouble_ticket = TextField(label_text=l_('Trouble Ticket')) |
|
30 |
# ack = SingleSelectField(label_text=l_('Status'), |
|
31 |
# options=edit_event_status_options) |
|
32 |
# |
|
33 |
# submit_text = l_('Apply') |
|
30 | 34 |
|
31 |
submit_text = l_('Apply') |
|
35 |
submit_text = None |
|
36 |
fields = [ |
|
37 |
HiddenField('id'), |
|
38 |
TextField('trouble_ticket', label_text=l_('Trouble Ticket')), |
|
39 |
SingleSelectField('ack', label_text=l_('Status'), |
|
40 |
options=edit_event_status_options) |
|
41 |
] |
|
42 |
|
|
43 |
def __init__(self, id, last_modification, *args, **kwargs): |
|
44 |
super(TableForm, self).__init__(id, *args, **kwargs) |
|
45 |
|
|
46 |
self.children.append(HiddenField('last_modification', |
|
47 |
attrs={'value':last_modification})) |
|
48 |
self.children.append(SubmitButton('submit', |
|
49 |
attrs={'value':l_('Apply')})) |
|
32 | 50 |
|
vigiboard/widgets/search_form.py | ||
---|---|---|
36 | 36 |
|
37 | 37 |
self.children.append(CalendarDateTimePicker(id + '_from_date', |
38 | 38 |
name = 'from_date', |
39 |
label_text = l_('From:'),
|
|
39 |
label_text = l_('From'), |
|
40 | 40 |
button_text = l_("Choose"), |
41 | 41 |
date_format = date_format, |
42 | 42 |
not_empty = False, |
... | ... | |
44 | 44 |
|
45 | 45 |
self.children.append(CalendarDateTimePicker(id + '_to_date', |
46 | 46 |
name = 'to_date', |
47 |
label_text = l_('To:'),
|
|
47 |
label_text = l_('To'), |
|
48 | 48 |
button_text = l_("Choose"), |
49 | 49 |
date_format = date_format, |
50 | 50 |
not_empty = False, |
51 | 51 |
calendar_lang=lang)) |
52 | 52 |
|
53 |
self.children.append(SubmitButton('search', value=l_('Search'))) |
|
53 |
self.children.append(SubmitButton('search', |
|
54 |
attrs={'value':l_('Search')})) |
|
54 | 55 |
|
Also available in: Unified diff