Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

vigiboard / vigiboard / controllers / root.py @ 858d88aa

History | View | Annotate | Download (22.8 KB)

1 19e88cb8 Thomas ANDREJAK
# -*- coding: utf-8 -*-
2
# vim:set expandtab tabstop=4 shiftwidth=4: 
3
"""Vigiboard Controller"""
4
5 7365fb51 Francois POIROTTE
from datetime import datetime
6
from time import mktime
7
import math
8
import urllib
9
10 4dd2035e Francois POIROTTE
from tg.exceptions import HTTPNotFound
11 aa0788a2 Francois POIROTTE
from tg import expose, validate, require, flash, \
12 c1ce3d6a Francois POIROTTE
    tmpl_context, request, config, session, redirect, url
13 3e6ee4db Francois POIROTTE
from tw.forms import validators
14 19e88cb8 Thomas ANDREJAK
from pylons.i18n import ugettext as _
15 ef31cc13 Francois POIROTTE
from pylons.i18n import lazy_ugettext as l_
16 aa0788a2 Francois POIROTTE
from pylons.controllers.util import abort
17 6ab72614 Vincent QUEMENER
from sqlalchemy import asc
18 97f6d842 Vincent QUEMENER
from sqlalchemy.sql import func
19 7365fb51 Francois POIROTTE
from repoze.what.predicates import Any, not_anonymous
20 ee3ae8c8 Francois POIROTTE
21 5dbfa80d Francois POIROTTE
from vigilo.models.configure import DBSession
22 7365fb51 Francois POIROTTE
from vigilo.models import Event, EventHistory, CorrEvent, SupItem, \
23 6ab72614 Vincent QUEMENER
                            HostGroup, ServiceGroup, StateName, User
24 080abea3 Francois POIROTTE
from vigilo.models.functions import sql_escape_like
25 7365fb51 Francois POIROTTE
26 4d783824 Francois POIROTTE
from vigilo.turbogears.controllers.autocomplete \
27
    import make_autocomplete_controller
28 7365fb51 Francois POIROTTE
from vigiboard.controllers.vigiboardrequest import VigiboardRequest
29
from vigiboard.controllers.vigiboard_controller import VigiboardRootController
30
from vigiboard.widgets.edit_event import edit_event_status_options
31 398c727b Francois POIROTTE
from vigiboard.lib.base import BaseController
32 19e88cb8 Thomas ANDREJAK
33 97f6d842 Vincent QUEMENER
__all__ = ('RootController', 'get_last_modification_timestamp', 
34
           'date_to_timestamp')
35 19e88cb8 Thomas ANDREJAK
36 4d783824 Francois POIROTTE
# pylint: disable-msg=R0201
37 b8500d1a Thomas ANDREJAK
class RootController(VigiboardRootController):
38 19e88cb8 Thomas ANDREJAK
    """
39
    Le controller général de vigiboard
40
    """
41 4d783824 Francois POIROTTE
    autocomplete = make_autocomplete_controller(BaseController)
42 ef31cc13 Francois POIROTTE
43 aa0788a2 Francois POIROTTE
    def process_form_errors(self, *argv, **kwargv):
44 19e88cb8 Thomas ANDREJAK
        """
45
        Gestion des erreurs de validation : On affiche les erreurs
46
        puis on redirige vers la dernière page accédée.
47
        """
48 aa0788a2 Francois POIROTTE
        for k in tmpl_context.form_errors:
49
            flash("'%s': %s" % (k, tmpl_context.form_errors[k]), 'error')
50 19e88cb8 Thomas ANDREJAK
        if request.environ.get('HTTP_REFERER') :
51
            redirect(request.environ.get('HTTP_REFERER'
52
                ).split(request.environ.get('HTTP_HOST'))[1])
53
        else :
54
            redirect('/')
55
56 5f2cd70a Francois POIROTTE
    @expose('vigiboard.html')
57 228aad1c Francois POIROTTE
    @require(Any(not_anonymous(), msg=l_("You need to be authenticated")))
58 080abea3 Francois POIROTTE
    def default(self, page=None, hostgroup=None, servicegroup=None,
59
            host=None, service=None, output=None, trouble_ticket=None,
60
            from_date=None, to_date=None, *argv, **krgv):
61 19e88cb8 Thomas ANDREJAK
            
62
        """
63 bc94248f Francois POIROTTE
        Page d'accueil de Vigiboard. Elle affiche, suivant la page demandée
64 a2a22ade Francois POIROTTE
        (page 1 par defaut), la liste des événements, rangés par ordre de prise
65 bc94248f Francois POIROTTE
        en compte, puis de sévérité.
66 19e88cb8 Thomas ANDREJAK
        Pour accéder à cette page, l'utilisateur doit être authentifié.
67

68 bc94248f Francois POIROTTE
        @param page: Numéro de la page souhaitée, commence à 1
69 19e88cb8 Thomas ANDREJAK
        @param host: Si l'utilisateur souhaite sélectionner seulement certains
70 a2a22ade Francois POIROTTE
                     événements suivant leur hôte, il peut placer une expression
71 19e88cb8 Thomas ANDREJAK
                     ici en suivant la structure du LIKE en SQL
72
        @param service: Idem que host mais sur les services
73
        @param output: Idem que host mais sur le text explicatif
74
        @param trouble_ticket: Idem que host mais sur les tickets attribués
75
        """
76 aa0788a2 Francois POIROTTE
        if page is None:
77
            page = 1
78 693e96f1 Thomas ANDREJAK
79 aa0788a2 Francois POIROTTE
        try:
80
            page = int(page)
81
        except ValueError:
82
            abort(404)
83
84
        if page < 1:
85 19e88cb8 Thomas ANDREJAK
            page = 1
86
87 bc94248f Francois POIROTTE
        username = request.environ['repoze.who.identity']['repoze.who.userid']
88 4952a19c Francois POIROTTE
        user = User.by_user_name(username)
89 840079e0 Vincent QUEMENER
        
90 97f6d842 Vincent QUEMENER
        aggregates = VigiboardRequest(user)
91 911069bc Francois POIROTTE
        aggregates.add_table(
92
            CorrEvent,
93
            aggregates.items.c.hostname,
94
            aggregates.items.c.servicename
95
        )
96
        aggregates.add_join((Event, CorrEvent.idcause == Event.idevent))
97 bfd8ead8 Vincent QUEMENER
        aggregates.add_join((aggregates.items, 
98
            Event.idsupitem == aggregates.items.c.idsupitem))
99 5d20c2c5 Francois POIROTTE
        aggregates.add_order_by(asc(aggregates.items.c.hostname))
100 d6c3a0c9 Thomas ANDREJAK
        
101 bc94248f Francois POIROTTE
        search = {
102
            'host': '',
103
            'service': '',
104
            'output': '',
105 1101e03e Francois POIROTTE
            'tt': '',
106
            'from_date': '',
107
            'to_date': '',
108 080abea3 Francois POIROTTE
            'hostgroup': '',
109
            'servicegroup': '',
110 bc94248f Francois POIROTTE
        }
111 398c727b Francois POIROTTE
112 19e88cb8 Thomas ANDREJAK
        # Application des filtres si nécessaire
113 398c727b Francois POIROTTE
        if hostgroup:
114
            search['hostgroup'] = hostgroup
115
            hostgroup = sql_escape_like(hostgroup)
116 24334b4b Vincent QUEMENER
            aggregates.add_join((HostGroup, HostGroup.idgroup == \
117
                aggregates.items.c.idhostgroup))
118
            aggregates.add_filter(HostGroup.name.ilike('%%%s%%' % hostgroup))
119 398c727b Francois POIROTTE
120
        if servicegroup:
121
            search['servicegroup'] = servicegroup
122
            servicegroup = sql_escape_like(servicegroup)
123 24334b4b Vincent QUEMENER
            aggregates.add_join((ServiceGroup, ServiceGroup.idgroup == \
124
                aggregates.items.c.idservicegroup))
125 6ab72614 Vincent QUEMENER
            aggregates.add_filter(
126
                ServiceGroup.name.ilike('%%%s%%' % servicegroup))
127 398c727b Francois POIROTTE
128 08d86103 Francois POIROTTE
        if host:
129 693e96f1 Thomas ANDREJAK
            search['host'] = host
130 08d86103 Francois POIROTTE
            host = sql_escape_like(host)
131 24334b4b Vincent QUEMENER
            aggregates.add_filter(aggregates.items.c.hostname.ilike(
132
                '%%%s%%' % host))
133 bc94248f Francois POIROTTE
134 08d86103 Francois POIROTTE
        if service:
135 693e96f1 Thomas ANDREJAK
            search['service'] = service
136 08d86103 Francois POIROTTE
            service = sql_escape_like(service)
137 24334b4b Vincent QUEMENER
            aggregates.add_filter(aggregates.items.c.servicename.ilike(
138 1101e03e Francois POIROTTE
                '%%%s%%' % service))
139 bc94248f Francois POIROTTE
140 08d86103 Francois POIROTTE
        if output:
141 693e96f1 Thomas ANDREJAK
            search['output'] = output
142 08d86103 Francois POIROTTE
            output = sql_escape_like(output)
143 a2a22ade Francois POIROTTE
            aggregates.add_filter(Event.message.ilike('%%%s%%' % output))
144 bc94248f Francois POIROTTE
145 08d86103 Francois POIROTTE
        if trouble_ticket:
146 693e96f1 Thomas ANDREJAK
            search['tt'] = trouble_ticket
147 08d86103 Francois POIROTTE
            trouble_ticket = sql_escape_like(trouble_ticket)
148 780ca169 Francois POIROTTE
            aggregates.add_filter(CorrEvent.trouble_ticket.ilike(
149 19e88cb8 Thomas ANDREJAK
                '%%%s%%' % trouble_ticket))
150
151 1101e03e Francois POIROTTE
        if from_date:
152
            search['from_date'] = from_date
153
            # TRANSLATORS: Format de date et heure.
154
            try:
155
                from_date = datetime.strptime(
156
                    from_date, _('%Y-%m-%d %I:%M:%S %p'))
157
            except ValueError:
158
                to_date = None
159
            aggregates.add_filter(CorrEvent.timestamp_active >= from_date)
160
161
        if to_date:
162
            search['to_date'] = to_date
163
            # TRANSLATORS: Format de date et heure.
164
            try:
165
                to_date = datetime.strptime(
166
                    to_date, _('%Y-%m-%d %I:%M:%S %p'))
167
            except ValueError:
168
                to_date = None
169
            aggregates.add_filter(CorrEvent.timestamp_active <= to_date)
170
171 19e88cb8 Thomas ANDREJAK
        # Calcul des éléments à afficher et du nombre de pages possibles
172 3d0d254c Francois POIROTTE
        total_rows = aggregates.num_rows()
173 ee3ae8c8 Francois POIROTTE
        items_per_page = int(config['vigiboard_items_per_page'])
174 19e88cb8 Thomas ANDREJAK
175 ee3ae8c8 Francois POIROTTE
        id_first_row = items_per_page * (page-1)
176
        id_last_row = min(id_first_row + items_per_page, total_rows)
177 19e88cb8 Thomas ANDREJAK
178 3d0d254c Francois POIROTTE
        aggregates.format_events(id_first_row, id_last_row)
179
        aggregates.generate_tmpl_context()
180 baedcd0f Francois POIROTTE
181 ee3ae8c8 Francois POIROTTE
        nb_pages = int(math.ceil(total_rows / (items_per_page + 0.0)))
182 baedcd0f Francois POIROTTE
        if not total_rows:
183
            id_first_row = 0
184
        else:
185
            id_first_row += 1
186 3d0d254c Francois POIROTTE
187 19e88cb8 Thomas ANDREJAK
        return dict(
188 1101e03e Francois POIROTTE
            events = aggregates.events,
189
            rows_info = {
190
                'id_first_row': id_first_row,
191
                'id_last_row': id_last_row,
192
                'total_rows': total_rows,
193
            },
194
            nb_pages = nb_pages,
195
            page = page,
196
            event_edit_status_options = edit_event_status_options,
197
            history = [],
198
            hist_error = False,
199
            plugin_context = aggregates.context_fct,
200
            search = search,
201 398c727b Francois POIROTTE
            refresh_times = config['vigiboard_refresh_times'],
202 1101e03e Francois POIROTTE
        )
203 693e96f1 Thomas ANDREJAK
      
204 08d86103 Francois POIROTTE
    @validate(validators={'idcorrevent': validators.Int(not_empty=True)},
205 19e88cb8 Thomas ANDREJAK
            error_handler=process_form_errors)
206
    @expose('json')
207 228aad1c Francois POIROTTE
    @require(Any(not_anonymous(), msg=l_("You need to be authenticated")))
208 a45763b4 Francois POIROTTE
    def history_dialog(self, idcorrevent):
209 19e88cb8 Thomas ANDREJAK
        
210
        """
211
        JSon renvoyant les éléments pour l'affichage de la fenêtre de dialogue
212
        contenant des liens internes et externes.
213
        Pour accéder à cette page, l'utilisateur doit être authentifié.
214

215 a2a22ade Francois POIROTTE
        @param id: identifiant de l'événement
216 19e88cb8 Thomas ANDREJAK
        """
217 693e96f1 Thomas ANDREJAK
218 a2a22ade Francois POIROTTE
        # Obtention de données sur l'événement et sur son historique
219 aa0788a2 Francois POIROTTE
        username = request.environ.get('repoze.who.identity'
220
                    ).get('repoze.who.userid')
221
222 911069bc Francois POIROTTE
        username = request.environ['repoze.who.identity']['repoze.who.userid']
223
        events = VigiboardRequest(User.by_user_name(username))
224
        events.add_table(
225
            Event,
226
            events.items.c.hostname,
227
            events.items.c.servicename,
228 24334b4b Vincent QUEMENER
        )
229 911069bc Francois POIROTTE
        events.add_join((CorrEvent, CorrEvent.idcause == Event.idevent))
230 bfd8ead8 Vincent QUEMENER
        events.add_join((events.items, 
231
            Event.idsupitem == events.items.c.idsupitem))
232 911069bc Francois POIROTTE
        events.add_filter(CorrEvent.idcorrevent == idcorrevent)
233 24334b4b Vincent QUEMENER
234 911069bc Francois POIROTTE
        # Vérification que au moins un des identifiants existe et est éditable
235
        if events.num_rows() != 1:
236
            flash(_('No access to this event'), 'error')
237
            redirect('/')
238 8484b8bd Francois POIROTTE
239 911069bc Francois POIROTTE
        event = events.req[0]
240 d6c3a0c9 Thomas ANDREJAK
        eventdetails = {}
241 b8500d1a Thomas ANDREJAK
        for edname, edlink in \
242 aa0788a2 Francois POIROTTE
                config['vigiboard_links.eventdetails'].iteritems():
243 b8500d1a Thomas ANDREJAK
244 08d86103 Francois POIROTTE
            # Rappel:
245
            # event[0] = priorité de l'alerte corrélée.
246
            # event[1] = alerte brute.
247 911069bc Francois POIROTTE
            if event.servicename:
248
                service = urllib.quote(event.servicename)
249 24334b4b Vincent QUEMENER
            else:
250
                service = None
251 d6c3a0c9 Thomas ANDREJAK
            eventdetails[edname] = edlink[1] % {
252 08d86103 Francois POIROTTE
                'idcorrevent': idcorrevent,
253 911069bc Francois POIROTTE
                'host': urllib.quote(event.hostname),
254 24334b4b Vincent QUEMENER
                'service': service,
255 911069bc Francois POIROTTE
                'message': urllib.quote(event[0].message),
256 08d86103 Francois POIROTTE
            }
257 b8500d1a Thomas ANDREJAK
258 19e88cb8 Thomas ANDREJAK
        return dict(
259 f43329c2 Francois POIROTTE
                current_state = StateName.value_to_statename(
260 911069bc Francois POIROTTE
                                    event[0].current_state),
261 f43329c2 Francois POIROTTE
                initial_state = StateName.value_to_statename(
262 911069bc Francois POIROTTE
                                    event[0].initial_state),
263 f43329c2 Francois POIROTTE
                peak_state = StateName.value_to_statename(
264 911069bc Francois POIROTTE
                                    event[0].peak_state),
265 a45763b4 Francois POIROTTE
                idcorrevent = idcorrevent,
266 911069bc Francois POIROTTE
                host = event.hostname,
267
                service = event.servicename,
268 c49defb8 Francois POIROTTE
                eventdetails = eventdetails,
269 19e88cb8 Thomas ANDREJAK
            )
270
271 08d86103 Francois POIROTTE
    @validate(validators={'idcorrevent': validators.Int(not_empty=True)},
272 19e88cb8 Thomas ANDREJAK
            error_handler=process_form_errors)
273 5f2cd70a Francois POIROTTE
    @expose('vigiboard.html')
274 228aad1c Francois POIROTTE
    @require(Any(not_anonymous(), msg=l_("You need to be authenticated")))
275 a45763b4 Francois POIROTTE
    def event(self, idcorrevent):
276 19e88cb8 Thomas ANDREJAK
        """
277 a2a22ade Francois POIROTTE
        Affichage de l'historique d'un événement.
278 19e88cb8 Thomas ANDREJAK
        Pour accéder à cette page, l'utilisateur doit être authentifié.
279

280 a2a22ade Francois POIROTTE
        @param idevent: identifiant de l'événement souhaité
281 19e88cb8 Thomas ANDREJAK
        """
282
283 bc94248f Francois POIROTTE
        username = request.environ['repoze.who.identity']['repoze.who.userid']
284
        events = VigiboardRequest(User.by_user_name(username))
285 911069bc Francois POIROTTE
        events.add_table(
286
            CorrEvent,
287
            events.items.c.hostname,
288
            events.items.c.servicename,
289
        )
290
        events.add_join((Event, CorrEvent.idcause == Event.idevent))
291 bfd8ead8 Vincent QUEMENER
        events.add_join((events.items, 
292
            Event.idsupitem == events.items.c.idsupitem))
293 a45763b4 Francois POIROTTE
        events.add_filter(CorrEvent.idcorrevent == idcorrevent)
294 19e88cb8 Thomas ANDREJAK
        
295 a2a22ade Francois POIROTTE
        # Vérification que l'événement existe
296 19e88cb8 Thomas ANDREJAK
        if events.num_rows() != 1 :
297 911069bc Francois POIROTTE
            flash(_('No access to this event'), 'error')
298 19e88cb8 Thomas ANDREJAK
            redirect('/')
299
       
300
        events.format_events(0, 1)
301
        events.format_history()
302
        events.generate_tmpl_context() 
303
304
        return dict(
305 911069bc Francois POIROTTE
            events = events.events,
306
            rows_info = {
307
                'id_first_row': 1,
308
                'id_last_row': 1,
309
                'total_rows': 1,
310
            },
311
            nb_pages = 1,
312
            page = 1,
313
            event_edit_status_options = edit_event_status_options,
314
            history = events.hist,
315
            hist_error = True,
316
            plugin_context = events.context_fct,
317
            search = {
318
                'host': '',
319
                'service': '',
320
                'output': '',
321
                'tt': '',
322
                'from_date': '',
323
                'to_date': '',
324
                'hostgroup': '',
325
                'servicegroup': '',
326
            },
327
           refresh_times=config['vigiboard_refresh_times'],
328
        )
329 19e88cb8 Thomas ANDREJAK
330 24334b4b Vincent QUEMENER
    @validate(
331
        validators={
332
            'host': validators.NotEmpty(),
333
#            'service': validators.NotEmpty()
334
        }, 
335 6ab72614 Vincent QUEMENER
        error_handler = process_form_errors)
336 5f2cd70a Francois POIROTTE
    @expose('vigiboard.html')
337 228aad1c Francois POIROTTE
    @require(Any(not_anonymous(), msg=l_("You need to be authenticated")))
338 24334b4b Vincent QUEMENER
    def host_service(self, host, service=None):
339 19e88cb8 Thomas ANDREJAK
        """
340 a2a22ade Francois POIROTTE
        Affichage de l'historique de l'ensemble des événements correspondant
341 bc94248f Francois POIROTTE
        au host et service demandé.
342 19e88cb8 Thomas ANDREJAK
        Pour accéder à cette page, l'utilisateur doit être authentifié.
343

344
        @param host: Nom de l'hôte souhaité.
345
        @param service: Nom du service souhaité
346
        """
347
348 24334b4b Vincent QUEMENER
        idsupitem = SupItem.get_supitem(host, service)
349
350 bc94248f Francois POIROTTE
        username = request.environ['repoze.who.identity']['repoze.who.userid']
351
        events = VigiboardRequest(User.by_user_name(username))
352 911069bc Francois POIROTTE
        events.add_table(
353
            CorrEvent,
354
            events.items.c.hostname,
355
            events.items.c.servicename,
356
        )
357
        events.add_join((Event, CorrEvent.idcause == Event.idevent))
358 bfd8ead8 Vincent QUEMENER
        events.add_join((events.items, 
359
            Event.idsupitem == events.items.c.idsupitem))
360 24334b4b Vincent QUEMENER
        events.add_filter(events.items.c.idsupitem == idsupitem)
361 baedcd0f Francois POIROTTE
362 a8f27bb3 Francois POIROTTE
        # XXX On devrait avoir une autre API que ça !!!
363 a2a22ade Francois POIROTTE
        # Supprime le filtre qui empêche d'obtenir des événements fermés
364 a8f27bb3 Francois POIROTTE
        # (ie: ayant l'état Nagios 'OK' et le statut 'AAClosed').
365 24334b4b Vincent QUEMENER
        if len(events.filter) > 0:
366
            del events.filter[0]
367 6892ebac Thomas ANDREJAK
368 a2a22ade Francois POIROTTE
        # Vérification qu'il y a au moins 1 événement qui correspond
369 19e88cb8 Thomas ANDREJAK
        if events.num_rows() == 0 :
370 911069bc Francois POIROTTE
            flash(_('No access to this host/service or no event yet'), 'error')
371 19e88cb8 Thomas ANDREJAK
            redirect('/')
372 ee3ae8c8 Francois POIROTTE
373 19e88cb8 Thomas ANDREJAK
        events.format_events(0, events.num_rows())
374
        events.format_history()
375 ee3ae8c8 Francois POIROTTE
        events.generate_tmpl_context()
376
377 19e88cb8 Thomas ANDREJAK
        return dict(
378 8484b8bd Francois POIROTTE
                    events = events.events,
379
                    rows_info = {
380
                        'id_first_row': 1,
381
                        'id_last_row': 1,
382
                        'total_rows': 1,
383
                    },
384 baedcd0f Francois POIROTTE
                    nb_pages = 1,
385 8484b8bd Francois POIROTTE
                    page = 1,
386
                    event_edit_status_options = edit_event_status_options,
387
                    history = events.hist,
388
                    hist_error = True,
389
                    plugin_context = events.context_fct,
390
                    search = {
391 1bb369b9 Francois POIROTTE
                        'host': '',
392
                        'service': '',
393
                        'output': '',
394
                        'tt': '',
395
                        'from_date': '',
396
                        'to_date': '',
397
                        'hostgroup': '',
398
                        'servicegroup': '',
399 ef31cc13 Francois POIROTTE
                    },
400 398c727b Francois POIROTTE
                    refresh_times=config['vigiboard_refresh_times'],
401 8484b8bd Francois POIROTTE
                )
402 19e88cb8 Thomas ANDREJAK
403
    @validate(validators={
404 1bb369b9 Francois POIROTTE
        "id": validators.Regex(r'^[0-9]+(,[0-9]+)*,?$'),
405
#        "trouble_ticket": validators.Regex(r'^[0-9]*$'),
406 5d20c2c5 Francois POIROTTE
        "ack": validators.OneOf([
407 1bb369b9 Francois POIROTTE
            u'NoChange',
408
            u'None',
409
            u'Acknowledged',
410
            u'AAClosed'
411 08d86103 Francois POIROTTE
        ])}, error_handler=process_form_errors)
412 228aad1c Francois POIROTTE
    @require(Any(not_anonymous(), msg=l_("You need to be authenticated")))
413 19e88cb8 Thomas ANDREJAK
    def update(self,**krgv):
414
        """
415 a2a22ade Francois POIROTTE
        Mise à jour d'un événement suivant les arguments passés.
416 8484b8bd Francois POIROTTE
        Cela peut être un changement de ticket ou un changement de statut.
417 19e88cb8 Thomas ANDREJAK
        
418 a2a22ade Francois POIROTTE
        @param krgv['id']: Le ou les identifiants des événements à traiter
419 97f6d842 Vincent QUEMENER
        @param krgv['last_modification']: La date de la dernière modification
420
        dont l'utilisateur est au courant.
421 19e88cb8 Thomas ANDREJAK
        @param krgv['tt']: Nouveau numéro du ticket associé.
422 a2a22ade Francois POIROTTE
        @param krgv['status']: Nouveau status de/des événements.
423 19e88cb8 Thomas ANDREJAK
        """
424
425 97f6d842 Vincent QUEMENER
        # On vérifie que des identifiants ont bien été transmis via
426
        # le formulaire, et on informe l'utilisateur le cas échéant.
427 10848680 Francois POIROTTE
        if krgv['id'] is None:
428
            flash(_('No event has been selected'), 'warning')
429
            raise redirect(request.environ.get('HTTP_REFERER', url('/')))
430 5d20c2c5 Francois POIROTTE
431
        # Le filtre permet d'éliminer les chaines vides contenues dans le
432
        # tableau ('a,b,' -> split -> ['a','b',''] -> filter -> ['a','b']).
433 2597785f Francois POIROTTE
        ids = map(int, filter(len, krgv['id'].split(',')))
434 97f6d842 Vincent QUEMENER
435
        # Si l'utilisateur édite plusieurs événements à la fois,
436
        # il nous faut chacun des identifiants
437 19e88cb8 Thomas ANDREJAK
       
438 bc94248f Francois POIROTTE
        username = request.environ['repoze.who.identity']['repoze.who.userid']
439
        events = VigiboardRequest(User.by_user_name(username))
440 911069bc Francois POIROTTE
        events.add_table(CorrEvent)
441
        events.add_join((Event, CorrEvent.idcause == Event.idevent))
442 5d20c2c5 Francois POIROTTE
        events.add_join((events.items, 
443 bfd8ead8 Vincent QUEMENER
            Event.idsupitem == events.items.c.idsupitem))
444 780ca169 Francois POIROTTE
        events.add_filter(CorrEvent.idcorrevent.in_(ids))
445 19e88cb8 Thomas ANDREJAK
        
446 5edd29ac Vincent QUEMENER
        events.generate_request()
447
        idevents = [cause.idcause for cause in events.req]
448
        # Si des changements sont survenus depuis que la 
449
        # page est affichée, on en informe l'utilisateur.
450
        last_modification = get_last_modification_timestamp(idevents, None)
451
        if last_modification and datetime.fromtimestamp(\
452
            float(krgv['last_modification'])) < last_modification:
453
            flash(_('Changes have occurred since the page was last displayed, '
454
                    'your changes HAVE NOT been saved.'), 'warning')
455
            raise redirect(request.environ.get('HTTP_REFERER', url('/')))
456
        
457 19e88cb8 Thomas ANDREJAK
        # Vérification que au moins un des identifiants existe et est éditable
458 858d88aa Francois POIROTTE
        if events.num_rows() <= 0:
459 19e88cb8 Thomas ANDREJAK
            flash(_('No access to this event'), 'error')
460
            redirect('/')
461
        
462 a2a22ade Francois POIROTTE
        # Modification des événements et création d'un historique
463 a8f27bb3 Francois POIROTTE
        # pour chacun d'eux.
464 3d0d254c Francois POIROTTE
        for req in events.req:
465 780ca169 Francois POIROTTE
            if isinstance(req, CorrEvent):
466 19e88cb8 Thomas ANDREJAK
                event = req
467
            else:
468
                event = req[0]
469 8484b8bd Francois POIROTTE
470 19e88cb8 Thomas ANDREJAK
            if krgv['trouble_ticket'] != '' :
471 8484b8bd Francois POIROTTE
                history = EventHistory(
472
                        type_action="Ticket change",
473
                        idevent=event.idcause,
474 ee3ae8c8 Francois POIROTTE
                        value=krgv['trouble_ticket'],
475 9494bbb3 Vincent QUEMENER
                        text="Changed trouble ticket from '%s' to '%s'" % (
476 ee3ae8c8 Francois POIROTTE
                            event.trouble_ticket, krgv['trouble_ticket']
477
                        ),
478 8484b8bd Francois POIROTTE
                        username=username,
479 ee3ae8c8 Francois POIROTTE
                        timestamp=datetime.now(),
480 8484b8bd Francois POIROTTE
                    )
481 19e88cb8 Thomas ANDREJAK
                DBSession.add(history)   
482 ee3ae8c8 Francois POIROTTE
                event.trouble_ticket = krgv['trouble_ticket']
483 8484b8bd Francois POIROTTE
484 97f6d842 Vincent QUEMENER
            if krgv['ack'] != 'NoChange' :
485 19e88cb8 Thomas ANDREJAK
                history = EventHistory(
486 ed4a7159 Vincent QUEMENER
                        type_action="Acknowledgement change state",
487 8484b8bd Francois POIROTTE
                        idevent=event.idcause,
488 97f6d842 Vincent QUEMENER
                        value=krgv['ack'],
489 9494bbb3 Vincent QUEMENER
                        text="Changed acknowledgement status "
490
                            "from '%s' to '%s'" % (
491 97f6d842 Vincent QUEMENER
                            event.status, krgv['ack']
492 ee3ae8c8 Francois POIROTTE
                        ),
493 8484b8bd Francois POIROTTE
                        username=username,
494 ee3ae8c8 Francois POIROTTE
                        timestamp=datetime.now(),
495 8484b8bd Francois POIROTTE
                    )
496 19e88cb8 Thomas ANDREJAK
                DBSession.add(history)
497 97f6d842 Vincent QUEMENER
                event.status = krgv['ack']
498 3d0d254c Francois POIROTTE
499 10848680 Francois POIROTTE
        DBSession.flush()
500 19e88cb8 Thomas ANDREJAK
        flash(_('Updated successfully'))
501 c1ce3d6a Francois POIROTTE
        redirect(request.environ.get('HTTP_REFERER', url('/')))
502 19e88cb8 Thomas ANDREJAK
503 8ad24667 Thomas ANDREJAK
504 08d86103 Francois POIROTTE
    @validate(validators={"plugin_name": validators.OneOf(
505 3d0d254c Francois POIROTTE
        [i for [i, j] in config.get('vigiboard_plugins', [])])},
506 b8500d1a Thomas ANDREJAK
                error_handler = process_form_errors)
507 8ad24667 Thomas ANDREJAK
    @expose('json')
508 4dd2035e Francois POIROTTE
    @require(Any(not_anonymous(), msg=l_("You need to be authenticated")))
509
    def get_plugin_value(self, idcorrevent, plugin_name, *arg, **krgv):
510 8ad24667 Thomas ANDREJAK
        """
511 4dd2035e Francois POIROTTE
        Permet de récupérer la valeur d'un plugin associée à un CorrEvent
512
        donné via JSON.
513 8ad24667 Thomas ANDREJAK
        """
514 0f56fff9 Francois POIROTTE
        plugins = config['vigiboard_plugins']
515
        if plugins is None:
516 4dd2035e Francois POIROTTE
            raise HTTPNotFound()
517
518
        # Permet de vérifier si l'utilisateur a bien les permissions
519
        # pour accéder à cet événement et si l'événement existe.
520
        username = request.environ['repoze.who.identity']['repoze.who.userid']
521
        events = VigiboardRequest(User.by_user_name(username))
522
        events.add_table(CorrEvent.idcorrevent)
523
        events.add_join((Event, CorrEvent.idcause == Event.idevent))
524 bfd8ead8 Vincent QUEMENER
        events.add_join((events.items, 
525
            Event.idsupitem == events.items.c.idsupitem))
526 4dd2035e Francois POIROTTE
        events.add_filter(CorrEvent.idcorrevent == idcorrevent)
527
528
        # Pas d'événement ou permission refusée. On ne distingue pas
529
        # les 2 cas afin d'éviter la divulgation d'informations.
530
        if not events.num_rows():
531
            raise HTTPNotFound()
532 0f56fff9 Francois POIROTTE
533
        plugin = [i for i in plugins if i[0] == plugin_name][0]
534 8ad24667 Thomas ANDREJAK
        try:
535
            mypac = __import__(
536 b8500d1a Thomas ANDREJAK
                'vigiboard.controllers.vigiboard_plugin.' + plugin[0],
537
                globals(), locals(), [plugin[1]], -1)
538
            plug = getattr(mypac, plugin[1])()
539 4dd2035e Francois POIROTTE
            return plug.controller(idcorrevent, *arg, **krgv)
540
        except ImportError:
541
            raise HTTPNotFound()
542 1bb369b9 Francois POIROTTE
543
    @validate(validators={
544
        "fontsize": validators.Regex(
545
            r'[0-9]+(pt|px|em|%)',
546 6ab72614 Vincent QUEMENER
            regexOps = ('I',)
547 1bb369b9 Francois POIROTTE
        )}, error_handler = process_form_errors)
548 693e96f1 Thomas ANDREJAK
    @expose('json')
549 b8500d1a Thomas ANDREJAK
    def set_fontsize(self, fontsize):
550 4dd2035e Francois POIROTTE
        """Enregistre la taille de la police dans les préférences."""
551 b8500d1a Thomas ANDREJAK
        session['fontsize'] = fontsize
552
        session.save()
553 e2e218d7 Francois POIROTTE
        return dict()
554 693e96f1 Thomas ANDREJAK
555 08d86103 Francois POIROTTE
    @validate(validators={"refresh": validators.Int()},
556
            error_handler=process_form_errors)
557 693e96f1 Thomas ANDREJAK
    @expose('json')
558 b8500d1a Thomas ANDREJAK
    def set_refresh(self, refresh):
559 4dd2035e Francois POIROTTE
        """Enregistre le temps de rafraichissement dans les préférences."""
560 b8500d1a Thomas ANDREJAK
        session['refresh'] = refresh
561
        session.save()
562 e2e218d7 Francois POIROTTE
        return dict()
563
564
    @expose('json')
565
    def set_theme(self, theme):
566 4dd2035e Francois POIROTTE
        """Enregistre le thème à utiliser dans les préférences."""
567
        # On sauvegarde l'ID du thème sans vérifications
568
        # car les thèmes (styles CSS) sont définies dans
569
        # les packages de thèmes (ex: vigilo-themes-default).
570
        # La vérification de la valeur est faite dans les templates.
571 e2e218d7 Francois POIROTTE
        session['theme'] = theme
572
        session.save()
573
        return dict()
574 97f6d842 Vincent QUEMENER
    
575 24334b4b Vincent QUEMENER
def get_last_modification_timestamp(event_id_list, 
576 4dd2035e Francois POIROTTE
                                    value_if_none=datetime.now()):
577 97f6d842 Vincent QUEMENER
    """
578
    Récupère le timestamp de la dernière modification 
579
    opérée sur l'un des événements dont l'identifiant
580
    fait partie de la liste passée en paramètre.
581
    """
582
    last_modification_timestamp = DBSession.query(
583
                                func.max(EventHistory.timestamp),
584
                         ).filter(EventHistory.idevent.in_(event_id_list)
585
                         ).scalar()
586 e9ccb711 Francois POIROTTE
    if not last_modification_timestamp:
587 24334b4b Vincent QUEMENER
        if not value_if_none:
588
            return None
589
        else:
590
            last_modification_timestamp = value_if_none
591 e9ccb711 Francois POIROTTE
    return datetime.fromtimestamp(mktime(
592
        last_modification_timestamp.timetuple()))