source: indico/indico/MaKaC/services/implementation/collaboration.py @ 1d5dc6

hello-world-walkthroughipv6v0.98-seriesv0.98.2v0.98.3v0.99v1.0v1.1
Last change on this file since 1d5dc6 was 1d5dc6, checked in by Pedro Ferreira <jose.pedro.ferreira@…>, 16 months ago

[FIX] Improved separation from core in ical

  • Property mode set to 100644
File size: 21.5 KB
Line 
1# -*- coding: utf-8 -*-
2##
3##
4## This file is part of CDS Indico.
5## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN.
6##
7## CDS Indico is free software; you can redistribute it and/or
8## modify it under the terms of the GNU General Public License as
9## published by the Free Software Foundation; either version 2 of the
10## License, or (at your option) any later version.
11##
12## CDS Indico is distributed in the hope that it will be useful, but
13## WITHOUT ANY WARRANTY; without even the implied warranty of
14## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15## General Public License for more details.
16##
17## You should have received a copy of the GNU General Public License
18## along with CDS Indico; if not, write to the Free Software Foundation, Inc.,
19## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20
21from datetime import timedelta
22from MaKaC.services.implementation.base import ParameterManager, AdminService
23from MaKaC.services.interface.rpc.common import NoReportError
24from MaKaC.services.implementation.conference import ConferenceModifBase
25from MaKaC.plugins.Collaboration.base import CollaborationException, CollaborationServiceException
26from MaKaC.webinterface.rh.collaboration import RCCollaborationAdmin,\
27    RCCollaborationPluginAdmin, RCVideoServicesManager, RCVideoServicesUser
28from MaKaC.i18n import _
29from MaKaC.common.indexes import IndexesHolder
30from MaKaC.plugins import PluginsHolder
31from MaKaC.common.timezoneUtils import nowutc, setAdjustedDate
32from MaKaC.common.utils import parseDateTime
33from MaKaC.plugins.Collaboration.collaborationTools import CollaborationTools
34from MaKaC.webinterface.user import UserListModificationBase,\
35    UserModificationBase
36from MaKaC.common.fossilize import fossilize
37
38
39## Base classes
40class CollaborationBase(ConferenceModifBase):
41    """ This base class stores the _CSBookingManager attribute
42        so that inheriting classes can use it.
43    """
44    def _checkParams(self):
45        ConferenceModifBase._checkParams(self) #sets self._target = self._conf = the Conference object
46        self._checkCollaborationEnabled()
47        self._CSBookingManager = self._conf.getCSBookingManager()
48
49    def _checkCollaborationEnabled(self):
50        """ Checks if the Collaboration plugin system is active
51        """
52        if not PluginsHolder().hasPluginType("Collaboration"):
53            raise CollaborationServiceException("Collaboration plugin system is not active")
54
55    def _checkCanManagePlugin(self, plugin):
56        isAdminOnlyPlugin = CollaborationTools.isAdminOnlyPlugin(plugin)
57
58        hasAdminRights = RCCollaborationAdmin.hasRights(self) or \
59                         RCCollaborationPluginAdmin.hasRights(self, None, [plugin])
60
61        if not hasAdminRights and isAdminOnlyPlugin:
62            raise CollaborationException(_("Cannot acces service of admin-only plugin if user is not admin, for event: ") + str(self._conf.getId()) + _(" with the service ") + str(self.__class__) )
63
64        elif not hasAdminRights and not RCVideoServicesManager.hasRights(self, [plugin]):
65            #we check if it's an event creator / manager (this will call ConferenceModifBase._checkProtection)
66            CollaborationBase._checkProtection(self)
67
68    def process(self):
69        try:
70            return ConferenceModifBase.process(self)
71        except CollaborationException, e:
72            raise CollaborationServiceException(e.getMsg(), str(e.getInner()))
73
74class CollaborationBookingModifBase(CollaborationBase):
75    """ Base class for services that are passed a booking id.
76        It is stored in self._bookingId
77    """
78    def _checkParams(self):
79        CollaborationBase._checkParams(self)
80        if self._params.has_key('bookingId'):
81            self._bookingId = self._params['bookingId']
82            booking = self._CSBookingManager.getBooking(self._bookingId)
83            if booking == None:
84                raise NoReportError(_("The booking that you are trying to modify does not exist. Maybe it was already deleted, please refresh the page."))
85
86            self._bookingType = booking.getType()
87            self._bookingPlugin = booking.getPlugin()
88        else:
89            raise CollaborationException(_("Booking id not set when trying to modify a booking on meeting ") + str(self._conf.getId()) + _(" with the service ") + str(self.__class__) )
90
91    def _checkProtection(self):
92        CollaborationBase._checkCanManagePlugin(self, self._bookingType)
93
94class CollaborationAdminBookingModifBase(CollaborationBookingModifBase):
95    """ Base class for services on booking objects that can only be requested by Server Admins,
96        Video Services Admins, or Plugin admins, such as accept or reject a request, etc.
97    """
98
99    def _checkProtection(self):
100        if not RCCollaborationAdmin.hasRights(self) and not RCCollaborationPluginAdmin.hasRights(self, None, [self._bookingPlugin]):
101            raise CollaborationException(_("You don't have the rights to perform this operation on this booking"))
102
103class AdminCollaborationBase(AdminService):
104    """ Base class for admin services in the Video Services Overview page, not directed towards a specific booking.
105    """
106
107    def _checkParams(self):
108        AdminService._checkParams(self)
109        if not PluginsHolder().hasPluginType("Collaboration"):
110            raise CollaborationServiceException(_("Collaboration plugin system is not active"))
111
112    def _checkProtection(self):
113        if not RCCollaborationAdmin.hasRights(self, None):
114            AdminService._checkProtection(self)
115
116##! End of base classes
117
118class CollaborationBookingModif(CollaborationBookingModifBase):
119    """ Specific to check the authorised users and groups creating, editing and removing.
120        It is different to CollaborationBookingModifBase because:
121        * CollaborationBookingModif: people that can create, edit, remove
122        * CollaborationBookingModifBase: people that can start, stop, sync, etc
123    """
124    def _checkProtection(self):
125        CollaborationBookingModifBase._checkProtection(self)
126        if not RCVideoServicesUser.hasRights(self, None, self._bookingType):
127            raise CollaborationException(_("You dot have access to modify a %s booking")%self._bookingType)
128
129class CollaborationCreateCSBooking(CollaborationBase, CollaborationBookingModif):
130    """ Adds a new booking
131    """
132    def _checkParams(self):
133        CollaborationBase._checkParams(self)
134
135        if 'type' in self._params:
136            self._bookingType = self._params['type']
137        else:
138            raise CollaborationException(_("type parameter not set when trying to create a booking on meeting ") + str(self._conf.getId() ))
139
140        if 'bookingParams' in self._params:
141            pm = ParameterManager(self._params)
142            self._bookingParams = pm.extract("bookingParams", pType=dict, allowEmpty = True)
143        else:
144            raise CollaborationException(_("Custom parameters for plugin ") + str(self._type) + _(" not set when trying to create a booking on meeting ") + str(self._conf.getId() ))
145
146    def _checkProtection(self):
147        CollaborationBookingModif._checkProtection(self)
148
149    def _getAnswer(self):
150        return fossilize(self._CSBookingManager.createBooking(self._bookingType, bookingParams = self._bookingParams),
151                         None, tz = self._conf.getTimezone())
152
153class CollaborationRemoveCSBooking(CollaborationBookingModif):
154    """ Removes a booking
155    """
156
157    def _getAnswer(self):
158        return fossilize(self._CSBookingManager.removeBooking(self._bookingId),
159                         None, tz = self._conf.getTimezone())
160
161
162class CollaborationEditCSBooking(CollaborationBookingModif):
163    """ Edits a booking
164    """
165    def _checkParams(self):
166        CollaborationBookingModif._checkParams(self)
167
168        if self._params.has_key('bookingParams'):
169            pm = ParameterManager(self._params)
170            self._bookingParams = pm.extract("bookingParams", pType=dict, allowEmpty = True)
171        else:
172            raise CollaborationException(_("Custom parameters for booking ") + str(self._bookingId) + _(" not set when trying to edit a booking on meeting ") + str(self._conf.getId() ))
173
174    def _getAnswer(self):
175        return fossilize(self._CSBookingManager.changeBooking(self._bookingId, self._bookingParams),
176                         None, tz = self._conf.getTimezone())
177
178
179class CollaborationStartCSBooking(CollaborationBookingModifBase):
180    """ Performs server-side actions when a booking is started
181    """
182    def _getAnswer(self):
183        return fossilize(self._CSBookingManager.startBooking(self._bookingId),
184                         None, tz = self._conf.getTimezone())
185
186class CollaborationStopCSBooking(CollaborationBookingModifBase):
187    """ Performs server-side actions when a booking is stopped
188    """
189    def _getAnswer(self):
190        return fossilize(self._CSBookingManager.stopBooking(self._bookingId),
191                                  timezone = self._conf.getTimezone())
192
193class CollaborationConnectCSBooking(CollaborationBookingModifBase):
194    """ Performs server-side actions when a booking is connected
195    """
196    def _getAnswer(self):
197        return fossilize(self._CSBookingManager.connectBooking(self._bookingId),
198                                  timezone = self._conf.getTimezone())
199
200class CollaborationCheckCSBookingStatus(CollaborationBookingModifBase):
201    """ Performs server-side actions when a booking's status is checked
202    """
203    def _getAnswer(self):
204        return fossilize(self._CSBookingManager.checkBookingStatus(self._bookingId),
205                         None, tz = self._conf.getTimezone())
206
207class CollaborationAcceptCSBooking(CollaborationAdminBookingModifBase):
208    """ Performs server-side actions when a booking / request is accepted
209    """
210    def _getAnswer(self):
211        return fossilize(self._CSBookingManager.acceptBooking(self._bookingId, self.getAW().getUser()),
212                                  None, tz = self._conf.getTimezone())
213
214class CollaborationRejectCSBooking(CollaborationAdminBookingModifBase):
215    """ Performs server-side actions when a booking / request is rejected
216    """
217    def _checkParams(self):
218        CollaborationAdminBookingModifBase._checkParams(self)
219        self._reason = self._params.get("reason", "")
220
221    def _getAnswer(self):
222        return fossilize(self._CSBookingManager.rejectBooking(self._bookingId, self._reason),
223                                  None, tz = self._conf.getTimezone())
224
225class CollaborationChangePluginManagersBase(CollaborationBase):
226    """ Base class for adding and removing plugin managers in an event
227        self._plugin will be a string with the plugin name.
228    """
229
230    def _checkParams(self):
231        CollaborationBase._checkParams(self)
232        if self._params.has_key('plugin'):
233            self._plugin = self._params['plugin']
234        else:
235            raise CollaborationException(_("Plugin name not set when trying to add or remove a manager on event: ") + str(self._conf.getId()) + _(" with the service ") + str(self.__class__) )
236
237        if CollaborationTools.getCollaborationPluginType().hasPlugin(self._plugin) and CollaborationTools.isAdminOnlyPlugin(self._plugin):
238            raise CollaborationException(_("Tried to add or remove a manager for an admin-only plugin on event : ") + str(self._conf.getId()) + _(" with the service ") + str(self.__class__) )
239
240    def _checkProtection(self):
241        if not RCVideoServicesManager.hasRights(self):
242            CollaborationBase._checkProtection(self)
243
244class CollaborationAddPluginManager(CollaborationChangePluginManagersBase, UserListModificationBase):
245    """ Adds a user as Plugin Manager for an event and plugin
246    """
247
248    def _checkParams(self):
249        CollaborationChangePluginManagersBase._checkParams(self)
250        UserListModificationBase._checkParams(self)
251
252    def _getAnswer(self):
253        existingManagerIds = set([u.getId() for u in self._CSBookingManager.getPluginManagers(self._plugin)])
254        for u in self._avatars:
255            if not u.getId() in existingManagerIds:
256                self._CSBookingManager.addPluginManager(self._plugin, u)
257
258        return True
259
260
261class CollaborationRemovePluginManager(CollaborationChangePluginManagersBase, UserModificationBase):
262    """ Removes a user as Plugin Manager for an event and plugin
263    """
264
265    def _checkParams(self):
266        CollaborationChangePluginManagersBase._checkParams(self)
267        UserModificationBase._checkParams(self)
268
269    def _getAnswer(self):
270        self._CSBookingManager.removePluginManager(self._plugin, self._targetUser)
271        return True
272
273
274class CollaborationBookingIndexQuery(AdminCollaborationBase):
275    """ Performs a query to the Collaboration index of bookings / request objects.
276    """
277
278    def _checkProtection(self):
279        if not RCCollaborationPluginAdmin.hasRights(self, None, "any"):
280            AdminCollaborationBase._checkProtection(self)
281
282    def _checkParams(self):
283        AdminCollaborationBase._checkParams(self)
284        user = self.getAW().getUser()
285        if user: #someone is logged in. if not, AdminCollaborationBase's _checkProtection will take care of it
286            self._tz = user.getTimezone()
287
288            try:
289                self._page = self._params.get("page", None)
290                self._resultsPerPage = self._params.get("resultsPerPage", None)
291                self._indexName = self._params['indexName']
292                self._viewBy = self._params['viewBy']
293                self._orderBy = self._params['orderBy']
294
295                minKey = None
296                maxKey = None
297                if self._params['sinceDate']:
298                    minKey = setAdjustedDate(parseDateTime(self._params['sinceDate'].strip()), tz = self._tz)
299                if self._params['toDate']:
300                    maxKey = setAdjustedDate(parseDateTime(self._params['toDate'].strip()), tz = self._tz)
301                if self._params['fromTitle']:
302                    minKey = self._params['fromTitle'].strip()
303                if self._params['toTitle']:
304                    maxKey = self._params['toTitle'].strip()
305
306                """ For relative dates, create a diff timedelta for resetting to
307                    00:00 at the start of range and 23:59 at the end.
308                """
309                if self._params['fromDays']:
310                    try:
311                        fromDays = int(self._params['fromDays'])
312                    except ValueError, e:
313                        raise CollaborationException(_("Parameter 'fromDays' is not an integer"), inner = e)
314                    now = nowutc()
315                    diff = timedelta(hours = now.hour, minutes = now.minute, seconds = now.second)
316                    minKey = now - diff - timedelta(days = fromDays)
317                if self._params['toDays']:
318                    try:
319                        toDays = int(self._params['toDays'])
320                    except ValueError, e:
321                        raise CollaborationException(_("Parameter 'toDays' is not an integer"), inner = e)
322                    now = nowutc()
323                    diff = timedelta(days = 1) - \
324                           timedelta(hours = now.hour, minutes = now.minute, seconds = (now.second + 1))
325                    maxKey = now + diff + timedelta(days = toDays)
326
327                self._minKey = minKey
328                self._maxKey = maxKey
329
330                self._onlyPending = self._params['onlyPending']
331                categoryId = self._params['categoryId'].strip()
332                if categoryId:
333                    self._categoryId = categoryId
334                else:
335                    self._categoryId = None
336                conferenceId = self._params['conferenceId'].strip()
337                if conferenceId:
338                    self._conferenceId = conferenceId
339                else:
340                    self._conferenceId = None
341
342            except KeyError, e:
343                raise CollaborationException(_("One of the necessary parameters to query the booking index is missing"), inner = e)
344
345    def _getAnswer(self):
346        ci = IndexesHolder().getById('collaboration')
347
348        return ci.getBookings(self._indexName,
349                              self._viewBy,
350                              self._orderBy,
351                              self._minKey,
352                              self._maxKey,
353                              tz = self._tz,
354                              onlyPending = self._onlyPending,
355                              conferenceId = self._conferenceId,
356                              categoryId = self._categoryId,
357                              pickle = True,
358                              dateFormat='%a %d %b %Y',
359                              page = self._page,
360                              resultsPerPage = self._resultsPerPage,
361                              grouped=True)
362
363class CollaborationCustomPluginService(CollaborationBase):
364    """ Class to support plugin-defined services.
365        Plugins have to call 'collaboration.pluginService' and
366        specify a 'plugin' and 'service' arguments.
367        Then they have to create a class that inherits from
368        CollaborationPluginServiceBase with the same name
369        as the 'service' argument, plus 'Service' at the end.
370        The classes can have _checkParams, _checkProtetion methods,
371        and must have a _getAnswer method.
372        They will have the following attributes available:
373        _params, _aw, _conf, _target, _CSBookingManager.
374    """
375
376    def _checkParams(self):
377        CollaborationBase._checkParams(self)
378
379        self._pluginName = self._params.get('plugin', None)
380        if not self._pluginName:
381            raise CollaborationException(_("No 'plugin' paramater in CollaborationPluginService"))
382
383        serviceName = self._params.get('service', None)
384        if not serviceName:
385            raise CollaborationException(_("No 'service' paramater in CollaborationPluginService"))
386
387        self._serviceClass = CollaborationTools.getServiceClass(self._pluginName, serviceName)
388        if not self._serviceClass:
389            raise CollaborationException(_("Service " + str(serviceName) + _("Service not found for plugin ") + str(self._pluginName) + _("in CollaborationPluginService")))
390
391    def _checkProtection(self):
392        CollaborationBase._checkCanManagePlugin(self, self._pluginName)
393
394    def _getAnswer(self):
395        serviceObject = self._serviceClass(self._params, self._aw)
396        serviceObject._checkParams()
397        serviceObject._checkProtection()
398        return serviceObject._getAnswer()
399
400
401class CollaborationPluginServiceBase(CollaborationBase):
402    """ Base class that plugin-defined services need to inherit from.
403        The _params and _aw attributes will be available for them,
404        and also _target and _conf and _CSBookingManager from CollaborationBase.
405        If they implement a _checkParams method, they need to call
406        their parent's (this class's) method first.
407        This class _checkParam method calls CollaborationBase's
408    """
409
410    def __init__(self, params, aw):
411        self._params = params
412        self._aw = aw
413
414    def _checkParams(self):
415        CollaborationBase._checkParams(self)
416
417    def _checkProtection(self):
418        pass
419
420    def _getAnswer(self):
421        raise CollaborationException("No answer was returned")
422
423class CollaborationPluginServiceBookingModifBase(CollaborationPluginServiceBase):
424
425    def __init__(self, params, aw):
426        CollaborationPluginServiceBase.__init__(self, params, aw)
427        self._booking = None
428
429    def _checkParams(self):
430        CollaborationPluginServiceBase._checkParams(self)
431        bookingId = self._params.get("booking", None)
432        if bookingId:
433            self._booking = self._CSBookingManager.getBooking(bookingId)
434        else:
435            raise CollaborationException(_("Service " + str(self.__class__.__name__) + _(" was called without a 'booking' parameter ")))
436
437
438class CollaborationCreateTestCSBooking(CollaborationCreateCSBooking):
439    """ Service that creates a 'test' booking for performance test.
440        Avoids to use any of the plugins except DummyPlugin
441    """
442    def _checkParams(self):
443        CollaborationBase._checkParams(self)
444
445        if 'bookingParams' in self._params:
446            pm = ParameterManager(self._params)
447            self._bookingParams = pm.extract("bookingParams", pType=dict, allowEmpty = True)
448        else:
449            raise CollaborationException(_("Custom parameters for plugin ") + str(self._type) + _(" not set when trying to create a booking on meeting ") + str(self._conf.getId() ))
450
451    def _getAnswer(self):
452        return fossilize(self._CSBookingManager.createTestBooking(bookingParams = self._bookingParams),
453                         None, tz = self._conf.getTimezone())
454
455class CollaborationMakeMeModeratorCSBooking(CollaborationBookingModifBase):
456    """ Service that creates a 'test' booking for performance test.
457        Avoids to use any of the plugins except DummyPlugin
458    """
459    def _getAnswer(self):
460        return fossilize(self._CSBookingManager.makeMeModeratorBooking(self._bookingId, fossilize(self.getAW().getUser())),
461                                  None, tz = self._conf.getTimezone())
462
463
464methodMap = {
465    "createCSBooking": CollaborationCreateCSBooking,
466    "removeCSBooking": CollaborationRemoveCSBooking,
467    "editCSBooking": CollaborationEditCSBooking,
468    "startCSBooking": CollaborationStartCSBooking,
469    "stopCSBooking": CollaborationStopCSBooking,
470    "connectCSBooking": CollaborationConnectCSBooking,
471    "checkCSBookingStatus": CollaborationCheckCSBookingStatus,
472    "acceptCSBooking": CollaborationAcceptCSBooking,
473    "rejectCSBooking": CollaborationRejectCSBooking,
474    "bookingIndexQuery": CollaborationBookingIndexQuery,
475    "addPluginManager": CollaborationAddPluginManager,
476    "removePluginManager": CollaborationRemovePluginManager,
477    "pluginService": CollaborationCustomPluginService,
478    "makeMeModerator": CollaborationMakeMeModeratorCSBooking
479}
Note: See TracBrowser for help on using the repository browser.