[REF] Changed name of permissive format
[cds-indico.git] / indico / MaKaC / services / implementation / conference.py
bloba09ab579f9187c9b446aaff21f81f15a675882e4
1 # -*- coding: utf-8 -*-
2 ##
3 ##
4 ## This file is part of Indico.
5 ## Copyright (C) 2002 - 2012 European Organization for Nuclear Research (CERN).
6 ##
7 ## 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 3 of the
10 ## License, or (at your option) any later version.
12 ## 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.
17 ## You should have received a copy of the GNU General Public License
18 ## along with Indico;if not, see <http://www.gnu.org/licenses/>.
21 """
22 Asynchronous request handlers for conference-related data modification.
23 """
25 # 3rd party imports
26 from email.utils import formataddr
27 from indico.util.string import permissive_format
29 import datetime
30 from pytz import timezone
32 # legacy indico imports
33 from MaKaC.i18n import _
34 from MaKaC import domain, conference as conference
36 from MaKaC.common import indexes, info, filters, Config, timezoneUtils
37 from MaKaC.common.utils import validMail, setValidEmailSeparators, formatDateTime
38 from MaKaC.common.url import ShortURLMapper
39 from MaKaC.common.fossilize import fossilize
40 from MaKaC.common.contextManager import ContextManager
41 from MaKaC.common.logger import Logger
43 from MaKaC.errors import TimingError
44 from MaKaC.user import PrincipalHolder, Avatar, Group, AvatarHolder
45 from MaKaC.participant import Participant
46 from MaKaC.fossils.contribution import IContributionFossil
48 import MaKaC.webinterface.displayMgr as displayMgr
49 from MaKaC.webinterface import urlHandlers, wcomponents
50 from MaKaC.webinterface.rh.reviewingModif import RCReferee, RCPaperReviewManager
51 from MaKaC.webinterface.common import contribFilters
52 from MaKaC.webinterface.mail import GenericMailer, GenericNotification
53 import MaKaC.webinterface.pages.conferences as conferences
55 from MaKaC.services.implementation.base import ProtectedModificationService, ListModificationBase, ParameterManager, \
56 ProtectedDisplayService, ServiceBase, TextModificationBase, HTMLModificationBase, DateTimeModificationBase, ExportToICalBase
57 from MaKaC.services.interface.rpc.common import ServiceError, ServiceAccessError, Warning, \
58 ResultWithWarning, TimingNoReportError, NoReportError
61 # indico imports
62 from indico.modules.scheduler import tasks
63 from indico.util.i18n import i18nformat
64 from indico.web.http_api.util import generate_public_auth_request
67 class ConferenceBase:
68 """
69 Base class for conference modification
70 """
72 def _checkParams( self ):
74 try:
75 self._target = self._conf = conference.ConferenceHolder().getById(self._params["conference"]);
76 except:
77 try:
78 self._target = self._conf = conference.ConferenceHolder().getById(self._params["confId"]);
79 except:
80 raise ServiceError("ERR-E4", "Invalid conference id.")
81 if self._target == None:
82 Logger.get('rpc.conference').debug('self._target is null')
83 raise Exception("Null target.")
86 def _getCheckFlag(self):
87 """
88 Returns the "check" flag, a value that specifies what kind of
89 checking should be done before modifying. Classes that wish
90 to change this behavior should overload it.
91 """
93 # automatically adapt everything
94 return 2
97 class ConferenceModifBase(ProtectedModificationService, ConferenceBase):
98 def _checkParams(self):
99 ConferenceBase._checkParams(self)
100 ProtectedModificationService._checkParams(self)
102 class ConferenceScheduleModifBase(ConferenceModifBase):
103 def _checkParams(self):
104 ConferenceModifBase._checkParams(self)
105 if not self._params.has_key("scheduleEntry"):
106 raise ServiceError("ERR-E4", "No scheduleEntry id set.")
107 self._schEntry = self._conf.getSchedule().getEntryById(self._params["scheduleEntry"])
108 if self._schEntry == None:
109 raise NoReportError(_("It seems that the entry has been deleted or moved, please refresh the page"))
111 def _checkProtection( self ):
112 self._target = self._schEntry.getOwner()
113 ConferenceModifBase._checkProtection(self)
115 class ConferenceDisplayBase(ProtectedDisplayService, ConferenceBase):
117 def _checkParams(self):
118 ConferenceBase._checkParams(self)
119 ProtectedDisplayService._checkParams(self)
121 class ConferenceTextModificationBase(TextModificationBase, ConferenceModifBase):
122 #Note: don't change the order of the inheritance here!
123 pass
125 class ConferenceHTMLModificationBase(HTMLModificationBase, ConferenceModifBase):
126 #Note: don't change the order of the inheritance here!
127 pass
129 class ConferenceDateTimeModificationBase (DateTimeModificationBase, ConferenceModifBase):
130 #Note: don't change the order of the inheritance here!
131 pass
133 class ConferenceListModificationBase (ListModificationBase, ConferenceModifBase):
134 #Note: don't change the order of the inheritance here!
135 pass
138 class ConferenceTitleModification( ConferenceTextModificationBase ):
140 Conference title modification
142 def _handleSet(self):
143 title = self._value
144 if (title ==""):
145 raise ServiceError("ERR-E2",
146 "The title cannot be empty")
147 self._target.setTitle(self._value)
149 def _handleGet(self):
150 return self._target.getTitle()
153 class ConferenceDescriptionModification( ConferenceHTMLModificationBase ):
155 Conference description modification
157 def _handleSet(self):
158 self._target.setDescription(self._value)
160 def _handleGet(self):
161 return self._target.getDescription()
163 class ConferenceAdditionalInfoModification( ConferenceHTMLModificationBase ):
165 Conference additional info (a.k.a contact info) modification
167 def _handleSet(self):
168 self._target.setContactInfo(self._value)
170 def _handleGet(self):
171 return self._target.getContactInfo()
173 class ConferenceTypeModification( ConferenceTextModificationBase ):
175 Conference title modification
177 def _handleSet(self):
178 curType = self._target.getType()
179 newType = self._value
180 if newType != "" and newType != curType:
181 import MaKaC.webinterface.webFactoryRegistry as webFactoryRegistry
182 wr = webFactoryRegistry.WebFactoryRegistry()
183 factory = wr.getFactoryById(newType)
184 wr.registerFactory(self._target, factory)
186 styleMgr = info.HelperMaKaCInfo.getMaKaCInfoInstance().getStyleManager()
188 dispMgr = displayMgr.ConfDisplayMgrRegistery().getDisplayMgr(self._target)
189 dispMgr.setDefaultStyle(styleMgr.getDefaultStyleForEventType(newType))
190 self._target._notify('infoChanged')
192 def _handleGet(self):
193 return self._target.getType()
196 class ConferenceBookingModification( ConferenceTextModificationBase ):
198 Conference location name modification
200 def _handleSet(self):
201 changed = False
202 room = self._target.getRoom()
203 loc = self._target.getLocation()
205 newLocation = self._value.get('location')
206 newRoom = self._value.get('room')
208 if room == None:
209 room = conference.CustomRoom()
210 self._target.setRoom(room)
212 if room.getName() != newRoom:
213 room.setName(newRoom)
215 minfo = info.HelperMaKaCInfo.getMaKaCInfoInstance()
216 if minfo.getRoomBookingModuleActive():
217 room.retrieveFullName(newLocation)
218 else:
219 # invalidate full name, as we have no way to know it
220 room.fullName = None
221 changed = True
223 if loc == None:
224 loc = conference.CustomLocation()
225 self._target.setLocation(loc)
227 if loc.getName() != newLocation:
228 loc.setName(newLocation)
229 changed = True
231 loc.setAddress(self._value['address'])
233 if changed:
234 self._target._notify('placeChanged')
236 def _handleGet(self):
238 loc = self._target.getLocation()
239 room = self._target.getRoom()
240 if loc:
241 locName = loc.getName()
242 locAddress = loc.getAddress()
243 else:
244 locName = ''
245 locAddress = ''
246 if room:
247 roomName = room.name
248 else:
249 roomName = ''
251 return { 'location': locName,
252 'room': roomName,
253 'address': locAddress }
255 class ConferenceBookingDisplay( ConferenceDisplayBase ):
257 Conference location
259 def _getAnswer(self):
260 loc = self._target.getLocation()
261 room = self._target.getRoom()
262 if loc:
263 locName = loc.getName()
264 locAddress = loc.getAddress()
265 else:
266 locName = ''
267 locAddress = ''
268 if room:
269 roomName = room.name
270 else:
271 roomName = ''
273 return { 'location': locName,
274 'room': roomName,
275 'address': locAddress }
277 class ConferenceShortURLModification( ConferenceTextModificationBase ):
279 Conference short URL modification
281 def _handleSet(self):
282 mapper = ShortURLMapper()
283 mapper.remove(self._target)
284 self._target.setUrlTag(self._value)
285 if self._value:
286 mapper.add(self._value, self._target)
288 def _handleGet(self):
289 return self._target.getUrlTag()
291 class ConferenceTimezoneModification( ConferenceTextModificationBase ):
293 Conference Timezone modification
295 def _handleSet(self):
296 self._target.setTimezone(self._value)
298 def _handleGet(self):
299 return self._target.getTimezone()
301 class ConferenceKeywordsModification( ConferenceTextModificationBase ):
303 Conference keywords modification
305 def _handleSet(self):
306 self._target.setKeywords(self._value)
308 def _handleGet(self):
309 return self._target.getKeywords()
311 class ConferenceSpeakerTextModification( ConferenceTextModificationBase ):
312 """ Conference chairman text modification (for conferences and meetings)
314 def _handleSet(self):
315 self._target.setChairmanText(self._value)
317 def _handleGet(self):
318 return self._target.getChairmanText()
320 class ConferenceOrganiserTextModification( ConferenceTextModificationBase ):
321 """ Conference organiser text modification (for lectures)
323 def _handleSet(self):
324 self._target.setOrgText(self._value)
326 def _handleGet(self):
327 return self._target.getOrgText()
329 class ConferenceSupportEmailModification( ConferenceTextModificationBase ):
331 Conference support e-mail modification
333 def _handleSet(self):
334 # handling the case of a list of emails with separators different than ","
335 emailstr = setValidEmailSeparators(self._value)
337 if validMail(emailstr) or emailstr == '':
338 self._target.setSupportEmail(emailstr)
339 else:
340 raise ServiceError('ERR-E0', 'E-mail address %s is not valid!' %
341 self._value)
343 def _handleGet(self):
344 return self._target.getSupportEmail()
346 class ConferenceSupportModification( ConferenceTextModificationBase ):
348 Conference support caption and e-mail modification
350 def _handleSet(self):
351 dMgr = displayMgr.ConfDisplayMgrRegistery().getDisplayMgr(self._target)
352 caption = self._value.get("caption","")
353 email = self._value.get("email")
355 if caption == "":
356 raise ServiceError("ERR-E2", "The caption cannot be empty")
357 dMgr.setSupportEmailCaption(caption)
359 # handling the case of a list of emails with separators different than ","
360 email = setValidEmailSeparators(email)
362 if validMail(email) or email == "":
363 self._target.setSupportEmail(email)
364 else:
365 raise ServiceError('ERR-E0', 'E-mail address %s is not valid!' %
366 self._value)
368 def _handleGet(self):
369 dMgr = displayMgr.ConfDisplayMgrRegistery().getDisplayMgr(self._target)
370 caption = dMgr.getSupportEmailCaption()
371 email = self._target.getSupportEmail()
373 return { "caption": caption,
374 "email": email }
376 class ConferenceDefaultStyleModification( ConferenceTextModificationBase ):
378 Conference default style modification
380 def _handleSet(self):
381 dispManReg = displayMgr.ConfDisplayMgrRegistery()
382 dispManReg.getDisplayMgr(self._target).setDefaultStyle(self._value)
384 def _handleGet(self):
385 dispManReg = displayMgr.ConfDisplayMgrRegistery()
386 return dispManReg.getDisplayMgr(self._target).getDefaultStyle()
388 class ConferenceVisibilityModification( ConferenceTextModificationBase ):
390 Conference visibility modification
393 def _handleSet(self):
394 try:
395 val = int(self._value)
396 except ValueError:
397 raise ServiceError("ERR-E1","Invalid value type for property")
398 self._target.setVisibility(val)
400 def _handleGet(self):
401 return self._target.getVisibility()
403 class ConferenceStartEndDateTimeModification( ConferenceModifBase ):
405 Conference start date/time modification
407 When changing the start date / time, the _setParam method will be called
408 by DateTimeModificationBase's _handleSet method.
409 The _setParam method will return None (if there are no problems),
410 or a Warning object if the event start date change was OK but there were
411 side problems, such as an object observing the event start date change
412 could not perform its task
413 (Ex: a videoconference booking could not be moved in time according with
414 the conference's time change)
415 For this, it will check the 'dateChangeNotificationProblems' context variable.
418 def _checkParams(self):
419 ConferenceModifBase._checkParams(self)
421 pm = ParameterManager(self._params.get('value'), timezone=self._conf.getTimezone())
423 try:
424 self._startDate = pm.extract('startDate', pType=datetime.datetime)
425 self._endDate = pm.extract('endDate', pType=datetime.datetime)
426 except ValueError, e:
427 raise NoReportError("Warning",e.message)
428 self._shiftTimes = pm.extract('shiftTimes', pType=bool)
430 def _getAnswer(self):
432 ContextManager.set('dateChangeNotificationProblems', {})
434 if (self._shiftTimes):
435 moveEntries = 1
436 else:
437 moveEntries = 0
439 # first sanity check
440 if (self._startDate > self._endDate):
441 raise ServiceError("ERR-E3",
442 "Date/time of start cannot "
443 "be greater than date/time of end")
445 # catch TimingErrors that can be returned by the algorithm
446 try:
447 self._target.setDates(self._startDate,
448 self._endDate,
449 moveEntries = moveEntries)
450 except TimingError,e:
451 raise TimingNoReportError(e.getMsg(),
452 title = _("Cannot set event dates"),
453 explanation = e.getExplanation())
455 dateChangeNotificationProblems = ContextManager.get('dateChangeNotificationProblems')
457 if dateChangeNotificationProblems:
459 warningContent = []
460 for problemGroup in dateChangeNotificationProblems.itervalues():
461 warningContent.extend(problemGroup)
463 w = Warning(_('Warning'), [_('The start date of your event was changed correctly. '
464 'However, there were the following problems:'),
465 warningContent])
467 return ResultWithWarning(self._params.get('value'), w).fossilize()
469 else:
470 return self._params.get('value')
472 class ConferenceListUsedRooms( ConferenceDisplayBase ):
474 Get rooms that are used in the context of the conference:
475 * Booked in CRBS
476 * Already chosen in sessions
478 def _getAnswer( self ):
480 Calls _handle() on the derived classes, in order to make it happen. Provides
481 them with self._value.
483 roomList = []
484 roomList.extend(self._target.getRoomList())
485 roomList.extend(map(lambda x: x._getName(), self._target.getBookedRooms()))
487 return roomList
490 class ConferenceDateTimeEndModification( ConferenceDateTimeModificationBase ):
491 """ Conference end date/time modification
492 When changing the end date / time, the _setParam method will be called by DateTimeModificationBase's _handleSet method.
493 The _setParam method will return None (if there are no problems),
494 or a FieldModificationWarning object if the event start date change was OK but there were side problems,
495 such as an object observing the event start date change could not perform its task
496 (Ex: a videoconference booking could not be moved in time according with the conference's time change)
498 def _setParam(self):
500 ContextManager.set('dateChangeNotificationProblems', {})
502 if (self._pTime < self._target.getStartDate()):
503 raise ServiceError("ERR-E3",
504 "Date/time of end cannot "+
505 "be lower than data/time of start")
506 self._target.setDates(self._target.getStartDate(),
507 self._pTime.astimezone(timezone("UTC")),
508 moveEntries=0)
510 dateChangeNotificationProblems = ContextManager.get('dateChangeNotificationProblems')
512 if dateChangeNotificationProblems:
513 warningContent = []
514 for problemGroup in dateChangeNotificationProblems.itervalues():
515 warningContent.extend(problemGroup)
517 return Warning(_('Warning'), [_('The end date of your event was changed correctly.'),
518 _('However, there were the following problems:'),
519 warningContent])
520 else:
521 return None
524 def _handleGet(self):
525 return datetime.datetime.strftime(self._target.getAdjustedEndDate(),
526 '%d/%m/%Y %H:%M')
529 class ConferenceListSessions (ConferenceListModificationBase):
530 """ Returns a dictionary of all the Sessions within the current Conference,
531 ordered by index only """
533 def _getAnswer(self):
534 sessions = self._conf.getSessionList()
535 result = {}
537 for sess in sessions:
538 for slot in sess.getSortedSlotList():
539 time = " (" + formatDateTime(slot.getAdjustedStartDate(), format = "dd MMM yyyy HH:mm") + ")"
540 result["s"+sess.getId()+"l"+slot.getId()] = sess.getTitle() + (" - " + slot.getTitle() if slot.getTitle() else "") + time
542 return result
545 class ConferenceListContributions (ConferenceListModificationBase):
546 """ Returns a dictionary of all the Contributions within the current Conference,
547 if the Contribution is part of a Session, the Session name is appended
548 to the name of the Contribution in parenthesis """
550 def _getAnswer(self):
551 contributions = self._conf.getContributionList()
552 result = {}
553 for cont in contributions:
554 session = (" (" + cont.getSession().getTitle() + ")") if (cont.getSession() is not None) else ""
555 time = " (" + formatDateTime(cont.getAdjustedStartDate(), format = "dd MMM yyyy HH:mm") + ")"
556 result[cont.getId()] = cont.getTitle() + session + time
558 return result
561 class ConferenceListContributionsReview (ConferenceListModificationBase):
562 """ Returns a list of all contributions of a conference, ordered by id
565 def _checkParams(self):
566 ConferenceListModificationBase._checkParams(self)
567 pm = ParameterManager(self._params)
568 self._selTypes = pm.extract("selTypes", pType=list, allowEmpty = True, defaultValue = []) #ids of selected types
569 self._selTracks = pm.extract("selTracks", pType=list, allowEmpty = True, defaultValue = []) #ids of selected tracks
570 self._selSessions = pm.extract("selSessions", pType=list, allowEmpty = True, defaultValue = []) #ids of selected sessions
572 self._typeShowNoValue = self._params.get("typeShowNoValue", True)
573 self._trackShowNoValue = self._params.get("trackShowNoValue", True)
574 self._sessionShowNoValue = self._params.get("sessionShowNoValue", True)
576 self._showWithoutTeam = self._params.get("showWithoutTeam", True)
577 self._showWithReferee = self._params.get("showWithReferee", False)
578 self._showWithEditor = self._params.get("showWithEditor", False)
579 self._showWithReviewer = self._params.get("showWithReviewer", False)
581 self._showWithMaterial = self._params.get("showWithMaterial", False)
582 self._showWithoutMaterial = self._params.get("showWithoutMaterial", False)
584 def _checkProtection(self):
585 if not RCPaperReviewManager.hasRights(self) and not RCReferee.hasRights(self):
586 ProtectedModificationService._checkProtection(self)
588 def _handleGet(self):
589 contributions = self._conf.getContributionList()
591 filter = {}
593 #filtering if the active user is a referee: he can only see his own contribs
594 isOnlyReferee = RCReferee.hasRights(self) \
595 and not RCPaperReviewManager.hasRights(self) \
596 and not self._conf.canModify(self.getAW())
598 # We want to make an 'or', not an 'and' of the reviewing assign status
600 filter["reviewing"] = {}
601 if isOnlyReferee:
602 filter["reviewing"]["referee"] = self._getUser()
603 elif self._showWithReferee:
604 filter["reviewing"]["referee"] = "any"
605 if self._showWithEditor:
606 filter["reviewing"]["editor"] = "any"
607 if self._showWithReviewer:
608 filter["reviewing"]["reviewer"] = "any"
611 filter["type"] = self._selTypes
612 filter["track"] = self._selTracks
613 filter["session"] = self._selSessions
615 filter["materialsubmitted"] = self._showWithMaterial
617 filterCrit = ContributionsReviewingFilterCrit(self._conf, filter)
618 sortingCrit = contribFilters.SortingCriteria(["number"])
620 filterCrit.getField("type").setShowNoValue( self._typeShowNoValue )
621 filterCrit.getField("track").setShowNoValue( self._trackShowNoValue )
622 filterCrit.getField("session").setShowNoValue( self._sessionShowNoValue )
624 filterCrit.getField("reviewing").setShowNoValue( self._showWithoutTeam )
625 filterCrit.getField("materialsubmitted").setShowNoValue( self._showWithoutMaterial)
627 f= filters.SimpleFilter(filterCrit, sortingCrit)
628 contributions = f.apply(contributions)
630 return fossilize(contributions, IContributionFossil)
632 class ConferenceDeleteContributions (ConferenceModifBase):
633 """ Deletes a list of all contributions of a conference
636 def _checkParams(self):
637 ConferenceModifBase._checkParams(self)
638 self._selectedContributions = self._params.get('contributions',[])
640 def _getAnswer(self):
641 for contribId in self._selectedContributions:
642 contrib = self._conf.getContributionById(contribId)
643 contrib.getParent().getSchedule().removeEntry(contrib.getSchEntry())
644 self._conf.removeContribution(contrib)
646 #########################
647 # Contribution filtering
648 #########################
650 class ContributionsReviewingFilterCrit(filters.FilterCriteria):
651 _availableFields = {
652 contribFilters.RefereeFilterField.getId() : contribFilters.RefereeFilterField,
653 contribFilters.EditorFilterField.getId() : contribFilters.EditorFilterField,
654 contribFilters.ReviewerFilterField.getId() : contribFilters.ReviewerFilterField,
655 contribFilters.TypeFilterField.getId() : contribFilters.TypeFilterField,
656 contribFilters.TrackFilterField.getId() : contribFilters.TrackFilterField,
657 contribFilters.SessionFilterField.getId() : contribFilters.SessionFilterField,
658 contribFilters.MaterialSubmittedFilterField.getId() : contribFilters.MaterialSubmittedFilterField,
659 contribFilters.ReviewingFilterField.getId(): contribFilters.ReviewingFilterField
662 #############################
663 # Conference Modif Display #
664 #############################
666 class ConferencePicDelete(ConferenceModifBase):
668 def _checkParams(self):
669 ConferenceModifBase._checkParams(self)
671 pm = ParameterManager(self._params)
673 self._id = pm.extract("picId", pType=str, allowEmpty=False)
675 def _getAnswer(self):
676 im = displayMgr.ConfDisplayMgrRegistery().getDisplayMgr(self._conf).getImagesManager()
677 im.removePic(self._id)
679 #############################
680 # Conference cretion #
681 #############################
683 class ShowConcurrentEvents(ServiceBase):
685 def _checkParams(self):
686 ServiceBase._checkParams(self)
688 pm = ParameterManager(self._params)
690 self._tz = pm.extract("timezone", pType=str, allowEmpty=False)
691 pm.setTimezone(self._tz)
692 self._sDate = pm.extract("sDate", pType=datetime.datetime, allowEmpty=False)
693 self._eDate = pm.extract("eDate", pType=datetime.datetime, allowEmpty=False)
695 def _getAnswer( self ):
696 im = indexes.IndexesHolder()
697 ch = conference.ConferenceHolder()
698 calIdx = im.getIndex("calendar")
699 evtIds = calIdx.getObjectsIn(self._sDate, self._eDate)
701 evtsByCateg={}
702 for evtId in evtIds:
703 try:
704 evt = ch.getById(evtId)
705 categs =evt.getOwnerList()
706 categname =categs[0].getName()
707 if not evtsByCateg.has_key(categname):
708 evtsByCateg[categname] = []
709 evtsByCateg[categname].append((evt.getTitle().strip(),evt.getAdjustedStartDate().strftime('%d/%m/%Y %H:%M '),evt.getAdjustedEndDate().strftime('%d/%m/%Y %H:%M '), evt.getTimezone()))
711 except Exception:
712 continue
713 return evtsByCateg
716 class ConferenceGetFieldsAndContribTypes(ConferenceDisplayBase):
717 def _getAnswer( self ):
718 afm = self._target.getAbstractMgr().getAbstractFieldsMgr()
719 afmDict = dict([(f.getId(), f.getName()) for f in afm.getFields()])
720 cTypes = self._target.getContribTypeList()
721 cTypesDict = dict([(ct.getId(), ct.getName()) for ct in cTypes])
722 return [afmDict, cTypesDict]
724 class ConferenceParticipantBase:
726 def _generateParticipant(self, av=None):
727 participant = Participant(self._conf, av)
728 if av is None :
729 participant.setTitle(self._title)
730 participant.setFamilyName(self._familyName)
731 participant.setFirstName(self._firstName)
732 participant.setEmail(self._email)
733 participant.setAffiliation(self._affiliation)
734 participant.setAddress(self._address)
735 participant.setTelephone(self._telephone)
736 participant.setFax(self._fax)
737 return participant
739 def _sendEmailWithFormat(self, participant, data):
740 data["toList"] = [participant.getEmail()]
741 urlInvitation = urlHandlers.UHConfParticipantsInvitation.getURL( self._conf )
742 urlInvitation.addParam("participantId","%s"%participant.getId())
743 urlRefusal = urlHandlers.UHConfParticipantsRefusal.getURL( self._conf )
744 urlRefusal.addParam("participantId","%s"%participant.getId())
746 mailEnv = dict(name=participant.getEmail(),
747 confTitle=self._conf.getTitle(),
748 url=urlHandlers.UHConferenceDisplay.getURL( self._conf ),
749 urlRefusal=urlRefusal, urlInvitation=urlInvitation)
751 data["body"] = permissive_format(data["body"], mailEnv)
752 data["subject"] = permissive_format(data["subject"], mailEnv)
753 GenericMailer.sendAndLog(GenericNotification(data),self._conf,"participants", self._getUser())
755 class ConferenceAddEditParticipantBase(ConferenceParticipantBase):
757 def _checkParams(self):
758 pm = ParameterManager(self._params)
759 self._id = pm.extract("id", pType=str, allowEmpty=True)
760 self._title = pm.extract("title", pType=str, allowEmpty=True, defaultValue="")
761 self._familyName = pm.extract("surName", pType=str, allowEmpty=False)
762 self._firstName = pm.extract("name", pType=str, allowEmpty=False)
763 self._email = pm.extract("email", pType=str, allowEmpty=False)
764 self._affiliation = pm.extract("affiliation", pType=str, allowEmpty=True, defaultValue="")
765 self._address = pm.extract("address", pType=str, allowEmpty=True, defaultValue="")
766 self._telephone = pm.extract("phone", pType=str, allowEmpty=True, defaultValue="")
767 self._fax = pm.extract("fax", pType=str, allowEmpty=True, defaultValue="")
769 class ConferenceParticipantListBase(ConferenceModifBase):
771 def _checkParams(self):
772 ConferenceModifBase._checkParams(self)
773 pm = ParameterManager(self._params)
774 self._userList = pm.extract("userIds", pType=list, allowEmpty=False)
776 def _getWarningAlreadyAdded(self, list, typeList=""):
777 if len(list) == 1:
778 return _("""The participant identified by email %s
779 is already in the %s participants' list.""")%(typeList, list[0])
780 else:
782 return _("""The participants identified by email %s
783 are already in the %s participants' list.""")%(typeList ,", ".join(list))
785 class ConferenceParticipantsDisplay(ConferenceModifBase):
787 def _getAnswer( self ):
788 if self._conf.getParticipation().displayParticipantList() :
789 self._conf.getParticipation().participantListHide()
790 else:
791 self._conf.getParticipation().participantListDisplay()
792 return True
794 class ConferenceParticipantsAddedInfo(ConferenceModifBase):
796 def _getAnswer( self ):
797 if self._conf.getParticipation().isAddedInfo() :
798 self._conf.getParticipation().setNoAddedInfo(self._getUser())
799 else:
800 self._conf.getParticipation().setAddedInfo(self._getUser())
801 return True
804 class ConferenceParticipantsAllowForApplying(ConferenceModifBase):
806 def _getAnswer( self ):
807 if self._conf.getParticipation().isAllowedForApplying() :
808 self._conf.getParticipation().setNotAllowedForApplying(self._getUser())
809 else:
810 self._conf.getParticipation().setAllowedForApplying(self._getUser())
811 return True
814 class ConferenceParticipantsAutoAccept(ConferenceModifBase):
816 def _getAnswer( self ):
817 participation = self._conf.getParticipation()
818 participation.setAutoAccept(not participation.autoAccept(), self._getUser())
819 return True
821 class ConferenceParticipantsSetNumMaxParticipants( ConferenceTextModificationBase ):
823 Conference num max participants modification
825 def _handleSet(self):
826 numMaxPart = self._value
827 if (self._value ==""):
828 raise ServiceError("ERR-E2", _("The value of the maximum numbers of participants cannot be empty."))
829 try:
830 numMaxPart = int(self._value)
831 except ValueError:
832 raise ServiceError("ERR-E3", _("The value of the maximum numbers of participants has to be a positive number."))
834 self._target.getParticipation().setNumMaxParticipants(int(numMaxPart))
837 def _handleGet(self):
838 return self._target.getParticipation().getNumMaxParticipants()
840 class ConferenceApplyParticipant(ConferenceDisplayBase, ConferenceAddEditParticipantBase):
842 def _checkParams(self):
843 ConferenceDisplayBase._checkParams(self)
844 ConferenceAddEditParticipantBase._checkParams(self)
846 def _getAnswer(self):
847 if self._conf.getStartDate() < timezoneUtils.nowutc() :
848 raise NoReportError(_("""This event began on %s, you cannot apply for
849 participation after the event began."""%self._conf.getStartDate()), title=_("Event started"))
850 participation = self._conf.getParticipation()
852 if not participation.isAllowedForApplying() :
853 raise NoReportError( _("""Participation in this event is restricted to persons invited.
854 If you insist on taking part in this event, please contact the event manager."""), title=_("Application restricted"))
855 if participation.getNumMaxParticipants() > 0 and len(participation.getParticipantList()) >= participation.getNumMaxParticipants():
856 raise NoReportError( _("""You cannot apply for participation in this event because the maximum numbers of participants has been reached.
857 If you insist on taking part in this event, please contact the event manager."""), title=_("Maximum number of participants reached"))
859 result = {}
860 user = self._getUser()
861 pending = self._generateParticipant(user)
862 if participation.alreadyParticipating(pending) != 0:
863 raise NoReportError(_("The participant can not be added to the meeting because there is already a participant with the email address '%s'."
864 % pending.getEmail()),title=_('Already registered participant'))
865 elif participation.alreadyPending(pending)!=0:
866 raise NoReportError(_("The participant can not be added to the meeting because there is already a pending participant with the email address '%s'."
867 % pending.getEmail()),title=_('Already pending participant'))
868 else:
869 if participation.addPendingParticipant(pending):
870 if participation.autoAccept():
871 result["msg"] = _("The request for participation has been accepted")
872 if participation.displayParticipantList() :
873 result["listParticipants"] = participation.getPresentParticipantListText()
874 else:
875 result["msg"] = _("The participant identified by email '%s' has been added to the list of pending participants"
876 % pending.getEmail())
877 else:
878 return NoReportError(_("The participant cannot be added."), title=_("Error"))
879 return result
882 class ConferenceAddParticipant(ConferenceModifBase, ConferenceAddEditParticipantBase):
884 def _checkParams(self):
885 ConferenceModifBase._checkParams(self)
886 ConferenceAddEditParticipantBase._checkParams(self)
888 def _getAnswer(self):
889 eventManager = self._getUser()
890 av = AvatarHolder().match({"email": self._email.strip()}, exact=1, forceWithoutExtAuth=False)
891 participation = self._conf.getParticipation()
892 if av != None and av != []:
893 participant = self._generateParticipant(av[0])
894 else:
895 participant = self._generateParticipant()
896 if participation.alreadyParticipating(participant) != 0 :
897 raise NoReportError(_("The participant can not be added to the meeting because there is already a participant with the email address '%s'."
898 % participant.getEmail()),title=_('Already registered participant'))
899 elif participation.alreadyPending(participant)!=0:
900 raise NoReportError(_("The participant can not be added to the meeting because there is already a pending participant with the email address '%s'."
901 % participant.getEmail()),title=_('Already pending participant'))
902 else:
903 participation.addParticipant(participant, eventManager)
904 return conferences.WConferenceParticipant(self._conf,participant).getHTML().replace("\n","")
906 class ConferenceEditParticipant(ConferenceModifBase, ConferenceAddEditParticipantBase):
908 def _checkParams(self):
909 ConferenceModifBase._checkParams(self)
910 ConferenceAddEditParticipantBase._checkParams(self)
912 def _getAnswer(self):
913 participant = self._conf.getParticipation().getParticipantById(self._id)
914 if participant == None:
915 raise NoReportError(_("The participant that you are trying to edit does not exist."))
916 participant.setTitle(self._title)
917 participant.setFamilyName(self._familyName)
918 participant.setFirstName(self._firstName)
919 participant.setEmail(self._email)
920 participant.setAffiliation(self._affiliation)
921 participant.setAddress(self._address)
922 participant.setTelephone(self._telephone)
923 participant.setFax(self._fax)
924 return conferences.WConferenceParticipant(self._conf,participant).getHTML().replace("\n","")
926 class ConferenceEditPending(ConferenceModifBase, ConferenceAddEditParticipantBase):
928 def _checkParams(self):
929 ConferenceModifBase._checkParams(self)
930 ConferenceAddEditParticipantBase._checkParams(self)
932 def _getAnswer(self):
933 pending = self._conf.getParticipation().getPendingParticipantByKey(self._id)
934 if pending == None:
935 raise NoReportError(_("The pending participant that you are trying to edit does not exist."))
936 pending.setTitle(self._title)
937 pending.setFamilyName(self._familyName)
938 pending.setFirstName(self._firstName)
939 pending.setEmail(self._email)
940 pending.setAffiliation(self._affiliation)
941 pending.setAddress(self._address)
942 pending.setTelephone(self._telephone)
943 pending.setFax(self._fax)
944 return conferences.WConferenceParticipantPending(self._conf, self._id, pending).getHTML().replace("\n","")
946 class ConferenceAddParticipants(ConferenceParticipantBase, ConferenceParticipantListBase):
948 def _addParticipant(self, participant, participation):
949 if participation.alreadyParticipating(participant) != 0 :
950 self._usersParticipant.append(participant.getEmail())
951 elif participation.alreadyPending(participant)!=0:
952 self._usersPending.append(participant.getEmail())
953 else:
954 participation.addParticipant(participant, self._getUser())
955 self._added.append(conferences.WConferenceParticipant(self._conf,participant).getHTML())
957 def _getAnswer(self):
958 if self._userList == []:
959 raise NoReportError(_("No users were selected to be added as participants."))
960 self._usersPending = []
961 self._usersParticipant = []
962 self._added =[]
963 participation = self._conf.getParticipation()
964 result = {}
965 infoWarning = []
967 for user in self._userList:
968 ph = PrincipalHolder()
969 selected = ph.getById(user['id'])
970 if isinstance(selected, Avatar) :
971 self._addParticipant(self._generateParticipant(selected), participation)
972 elif isinstance(selected, Group) :
973 for member in selected.getMemberList() :
974 self._addParticipant(self._generateParticipant(member), participation)
976 else :
977 self._addParticipant(self._generateParticipant(), participation)
979 result["added"] = ("".join(self._added)).replace("\n","")
980 if self._usersPending:
981 infoWarning.append(self._getWarningAlreadyAdded(self._usersPending, "pending"))
982 if self._usersParticipant:
983 infoWarning.append(self._getWarningAlreadyAdded(self._usersParticipant))
984 if infoWarning:
985 result["infoWarning"] = infoWarning
986 return result
988 class ConferenceInviteParticipants(ConferenceParticipantBase, ConferenceParticipantListBase):
990 def _checkParams(self):
991 ConferenceParticipantListBase._checkParams(self)
992 pm = ParameterManager(self._params)
993 self._emailSubject = pm.extract("subject", pType=str, allowEmpty=False)
994 self._emailBody = pm.extract("body", pType=str, allowEmpty=False)
996 def _inviteParticipant(self, participant, participation):
997 if participation.alreadyParticipating(participant) != 0 :
998 self._usersParticipant.append(participant.getEmail())
999 return False
1000 elif participation.alreadyPending(participant)!=0:
1001 self._usersPending.append(participant.getEmail())
1002 return False
1003 else:
1004 participation.inviteParticipant(participant, self._getUser())
1005 self._added.append(conferences.WConferenceParticipant(self._conf,participant).getHTML())
1006 return True
1008 def _getAnswer(self):
1009 if self._userList == []:
1010 raise NoReportError(_("No users were selected to be invited as participants."))
1011 self._usersPending = []
1012 self._usersParticipant = []
1013 self._added =[]
1014 currentUser = self._getUser()
1015 participation = self._conf.getParticipation()
1016 infoWarning = []
1018 result = {}
1019 data = {}
1021 if currentUser:
1022 data["fromAddr"] = currentUser.getEmail()
1023 else:
1024 data["fromAddr"] = formataddr((self._conf.getTitle(), Config.getInstance().getNoReplyEmail()))
1026 data["subject"] = self._emailSubject
1027 data["body"] = self._emailBody
1028 for user in self._userList:
1029 ph = PrincipalHolder()
1030 selected = ph.getById(user['id'])
1031 if isinstance(selected, Avatar) :
1032 participant =self._generateParticipant(selected)
1033 if self._inviteParticipant(participant, participation):
1034 self._sendEmailWithFormat(participant, data)
1035 elif isinstance(selected, Group) :
1036 for member in selected.getMemberList() :
1037 participant =self._generateParticipant(member)
1038 if self._inviteParticipant(participant, participation):
1039 self._sendEmailWithFormat(participant, data)
1040 else :
1041 participant = self._generateParticipant()
1042 if self._inviteParticipant(participant, participation):
1043 self._sendEmailWithFormat(participant, data)
1044 result["added"] = ("".join(self._added)).replace("\n","")
1045 if self._usersPending:
1046 infoWarning.append(self._getWarningAlreadyAdded(self._usersPending, "pending"))
1047 if self._usersParticipant:
1048 infoWarning.append(self._getWarningAlreadyAdded(self._usersParticipant))
1049 if infoWarning:
1050 result["infoWarning"] = infoWarning
1051 return result
1053 class ConferenceRemoveParticipants(ConferenceParticipantListBase):
1055 def _getAnswer(self):
1056 if self._userList == []:
1057 raise NoReportError(_("No participants were selected to be removed."))
1058 for id in self._userList:
1059 self._conf.getParticipation().removeParticipant(id, self._getUser())
1060 return True
1062 class ConferenceMarkPresenceParticipants(ConferenceParticipantListBase):
1064 def _getAnswer(self):
1065 if self._userList == []:
1066 raise NoReportError(_("No participants were selected to be marked as presents."))
1067 for id in self._userList:
1068 participant = self._conf.getParticipation().getParticipantById(id)
1069 participant.setPresent()
1070 return True
1072 class ConferenceMarkAbsentParticipants(ConferenceParticipantListBase):
1074 def _getAnswer(self):
1075 if self._userList == []:
1076 raise NoReportError(_("No participants were selected to be marked as absents."))
1077 for id in self._userList:
1078 participant = self._conf.getParticipation().getParticipantById(id)
1079 participant.setAbsent()
1080 return True
1082 class ConferenceExcuseAbsenceParticipants(ConferenceParticipantListBase):
1084 def _getAnswer(self):
1085 if self._userList == []:
1086 raise NoReportError(_("No participants were selected to be excused."))
1087 usersPresent = []
1088 for id in self._userList:
1089 participant = self._conf.getParticipation().getParticipantById(id)
1090 if not participant.setStatusExcused() and participant.isPresent() :
1091 usersPresent.append(participant.getFullName())
1092 if usersPresent:
1093 if len(usersPresent) == 1:
1094 raise NoReportError(_("""You cannot excuse absence of %s - this participant was present
1095 in the event""")%(usersPresent[0]))
1096 else:
1097 raise NoReportError(_("""You cannot excuse absence of %s - these participants were present
1098 in the event""")%(", ".join(usersPresent)))
1100 return True
1102 class ConferenceEmailParticipants(ConferenceParticipantBase, ConferenceParticipantListBase):
1104 def _getAnswer(self):
1105 if self._userList == []:
1106 raise NoReportError(_("No participants were selected."))
1107 emailSubject = self._params.get("subject","")
1108 emailBody = self._params.get("body","")
1109 data = {}
1110 currentUser = self._getUser()
1112 if currentUser:
1113 data["fromAddr"] = currentUser.getEmail()
1114 else:
1115 data["fromAddr"] = formataddr((self._conf.getTitle(), Config.getInstance().getNoReplyEmail()))
1117 data["content-type"] = "text/html"
1118 data["subject"] = emailSubject
1119 for id in self._userList:
1120 participant = self._conf.getParticipation().getParticipantById(id)
1121 if participant:
1122 data["body"] = emailBody
1123 self._sendEmailWithFormat(participant, data)
1124 return True
1126 class ConferenceAcceptPendingParticipants(ConferenceParticipantListBase):
1128 def _getAnswer(self):
1129 if self._userList == []:
1130 raise NoReportError(_("No pending participants were selected to be accepted."))
1131 for id in self._userList:
1132 pending = self._conf.getParticipation().getPendingParticipantByKey(id)
1133 self._conf.getParticipation().addParticipant(pending)
1134 return True
1136 class ConferenceRejectPendingParticipants(ConferenceParticipantListBase):
1138 def _getAnswer(self):
1139 if self._userList == []:
1140 raise NoReportError(_("No pending participants were selected to be rejected."))
1141 for id in self._userList:
1142 pending = self._conf.getParticipation().getPendingParticipantByKey(id)
1143 pending.setStatusDeclined()
1144 self._conf.getParticipation().declineParticipant(pending)
1145 return True
1147 class ConferenceRejectWithEmailPendingParticipants(ConferenceParticipantBase, ConferenceParticipantListBase):
1149 def _getAnswer(self):
1150 if self._userList == []:
1151 raise NoReportError(_("No pending participants were selected to be rejected."))
1152 pm = ParameterManager(self._params)
1153 emailSubject = pm.extract("subject", pType=str, allowEmpty=True)
1154 emailBody = pm.extract("body", pType=str, allowEmpty=True)
1155 data = {}
1156 data["fromAddr"] = Config.getInstance().getNoReplyEmail()
1157 data["subject"] = emailSubject
1158 data["body"] = emailBody
1159 for id in self._userList:
1160 pending = self._conf.getParticipation().getPendingParticipantByKey(id)
1161 pending.setStatusDeclined()
1162 self._conf.getParticipation().declineParticipant(pending)
1163 self._sendEmailWithFormat(pending, data)
1164 return True
1166 class ConferenceProtectionUserList(ConferenceModifBase):
1168 def _getAnswer(self):
1169 #will use IAvatarFossil or IGroupFossil
1170 return fossilize(self._conf.getAllowedToAccessList())
1172 class ConferenceProtectionAddUsers(ConferenceModifBase):
1174 def _checkParams(self):
1175 ConferenceModifBase._checkParams(self)
1177 self._usersData = self._params['value']
1178 self._user = self.getAW().getUser()
1180 def _getAnswer(self):
1182 for user in self._usersData :
1184 userToAdd = PrincipalHolder().getById(user['id'])
1186 if not userToAdd :
1187 raise ServiceError("ERR-U0","User does not exist!")
1189 self._conf.grantAccess(userToAdd)
1191 class ConferenceProtectionRemoveUser(ConferenceModifBase):
1193 def _checkParams(self):
1194 ConferenceModifBase._checkParams(self)
1196 self._userData = self._params['value']
1198 self._user = self.getAW().getUser()
1200 def _getAnswer(self):
1202 userToRemove = PrincipalHolder().getById(self._userData['id'])
1204 if not userToRemove :
1205 raise ServiceError("ERR-U0","User does not exist!")
1206 elif isinstance(userToRemove, Avatar) or isinstance(userToRemove, Group) :
1207 self._conf.revokeAccess(userToRemove)
1210 class ConferenceProtectionToggleDomains(ConferenceModifBase):
1212 def _checkParams(self):
1213 self._params['confId'] = self._params['targetId']
1214 ConferenceModifBase._checkParams(self)
1215 pm = ParameterManager(self._params)
1216 self._domainId = pm.extract("domainId", pType=str)
1217 self._add = pm.extract("add", pType=bool)
1219 def _getAnswer(self):
1220 dh = domain.DomainHolder()
1221 d = dh.getById(self._domainId)
1222 if self._add:
1223 self._target.requireDomain(d)
1224 elif not self._add:
1225 self._target.freeDomain(d)
1228 class ConferenceProtectionSetAccessKey(ConferenceModifBase):
1230 def _checkParams(self):
1231 ConferenceModifBase._checkParams(self)
1232 self._accessKey = self._params.get("accessKey", "")
1234 def _getAnswer(self):
1235 self._conf.setAccessKey(self._accessKey)
1237 class ConferenceProtectionSetModifKey(ConferenceModifBase):
1239 def _checkParams(self):
1240 ConferenceModifBase._checkParams(self)
1241 self._modifKey = self._params.get("modifKey", "")
1243 def _getAnswer(self):
1244 self._conf.setModifKey(self._modifKey)
1246 class ConferenceContactInfoModification( ConferenceTextModificationBase ):
1248 Conference contact email modification
1250 def _handleSet(self):
1251 self._target.getAccessController().setContactInfo(self._value)
1252 def _handleGet(self):
1253 return self._target.getAccessController().getContactInfo()
1255 class ConferenceAlarmSendTestNow(ConferenceModifBase):
1257 def _checkParams(self):
1258 ConferenceModifBase._checkParams(self)
1259 pm = ParameterManager(self._params)
1260 self._fromAddr = pm.extract("fromAddr", pType=str, allowEmpty=True, defaultValue="")
1261 self._note = pm.extract("note", pType=str, allowEmpty=True)
1262 self._includeConf = pm.extract("includeConf", pType=str, allowEmpty=True, defaultValue="")
1264 def _getAnswer(self):
1265 al = tasks.AlarmTask(self._conf, 0, datetime.timedelta(), relative=datetime.timedelta())
1266 if self._fromAddr:
1267 al.setFromAddr(self._fromAddr)
1268 else:
1269 raise NoReportError(_("""Please choose a "FROM" address for the test alarm"""))
1270 al.setNote(self._note)
1271 al.setConfSummary(self._includeConf == "1")
1272 if self._getUser():
1273 al.addToAddr(self._aw.getUser().getEmail())
1274 else:
1275 raise NoReportError(_("You must be logged in to use this feature"))
1276 al.run(check = False)
1277 return True
1280 class ConferenceSocialBookmarksToggle(ConferenceModifBase):
1281 def _getAnswer(self):
1282 val = self._conf.getDisplayMgr().getShowSocialApps()
1283 self._conf.getDisplayMgr().setShowSocialApps(not val)
1285 class ConferenceChairPersonBase(ConferenceModifBase):
1287 def _getChairPersonsList(self):
1288 result = fossilize(self._conf.getChairList())
1289 for chair in result:
1290 av = AvatarHolder().match({"email": chair['email']},
1291 forceWithoutExtAuth=True, exact=True)
1292 chair['showManagerCB'] = True
1293 if (av and self._conf.getAccessController().canModify(av[0])) or chair['email'] in self._conf.getAccessController().getModificationEmail():
1294 chair['showManagerCB'] = False
1295 return result
1297 def _isEmailAlreadyUsed(self, email):
1298 for chair in self._conf.getChairList():
1299 if email == chair.getEmail():
1300 return True
1301 return False
1303 class ConferenceAddExistingChairPerson(ConferenceChairPersonBase):
1305 def _checkParams(self):
1306 ConferenceChairPersonBase._checkParams(self)
1307 pm = ParameterManager(self._params)
1308 self._userList = pm.extract("userList", pType=list, allowEmpty=False)
1309 # Check if there is already a user with the same email
1310 for person in self._userList:
1311 if self._isEmailAlreadyUsed(person["email"]):
1312 raise ServiceAccessError(_("A user with the email address %s is already in the Chairpersons list. Chairperson(s) not added.") % person["email"])
1314 def _newChair(self, av):
1315 chair = conference.ConferenceChair()
1316 chair.setTitle(av.getTitle())
1317 chair.setFirstName(av.getFirstName())
1318 chair.setFamilyName(av.getSurName())
1319 chair.setAffiliation(av.getAffiliation())
1320 chair.setEmail(av.getEmail())
1321 chair.setAddress(av.getAddress())
1322 chair.setPhone(av.getTelephone())
1323 chair.setFax(av.getFax())
1324 self._conf.addChair(chair)
1326 def _getAnswer(self):
1327 for person in self._userList:
1328 ah = AvatarHolder()
1329 av = ah.getById(person["id"])
1330 self._newChair(av)
1332 return self._getChairPersonsList()
1335 class ConferenceAddNewChairPerson(ConferenceChairPersonBase):
1337 def _checkParams(self):
1338 ConferenceChairPersonBase._checkParams(self)
1339 pm = ParameterManager(self._params)
1340 self._userData = pm.extract("userData", pType=dict, allowEmpty=False)
1341 if self._userData.get("email", "") != "" and self._isEmailAlreadyUsed(self._userData.get("email", "")):
1342 raise ServiceAccessError(_("The email address is already used by another chairperson. Chairperson not added."))
1344 def _newChair(self):
1345 chair = conference.ConferenceChair()
1346 chair.setTitle(self._userData.get("title", ""))
1347 chair.setFirstName(self._userData.get("firstName", ""))
1348 chair.setFamilyName(self._userData.get("familyName", ""))
1349 chair.setAffiliation(self._userData.get("affiliation", ""))
1350 chair.setEmail(self._userData.get("email", ""))
1351 chair.setAddress(self._userData.get("address", ""))
1352 chair.setPhone(self._userData.get("phone", ""))
1353 chair.setFax(self._userData.get("fax", ""))
1354 self._conf.addChair(chair)
1355 #If the chairperson needs to be given management rights
1356 if self._userData.get("manager", None):
1357 avl = AvatarHolder().match({"email": self._userData.get("email", "")}, exact=True, forceWithoutExtAuth=True)
1358 if avl:
1359 av = avl[0]
1360 self._conf.grantModification(av)
1361 else:
1362 #Apart from granting the chairman, we add it as an Indico user
1363 self._conf.grantModification(chair)
1365 def _getAnswer(self):
1366 self._newChair()
1367 return self._getChairPersonsList()
1370 class ConferenceRemoveChairPerson(ConferenceChairPersonBase):
1372 def _checkParams(self):
1373 ConferenceChairPersonBase._checkParams(self)
1374 pm = ParameterManager(self._params)
1375 self._chairId = pm.extract("userId", pType=str, allowEmpty=False)
1377 def _getAnswer(self):
1378 chair = self._conf.getChairById(self._chairId)
1379 self._conf.removeChair(chair)
1380 return self._getChairPersonsList()
1383 class ConferenceEditChairPerson(ConferenceChairPersonBase):
1385 def _checkParams(self):
1386 ConferenceChairPersonBase._checkParams(self)
1387 pm = ParameterManager(self._params)
1388 self._userData = pm.extract("userData", pType=dict, allowEmpty=False)
1389 self._chairId = pm.extract("userId", pType=str, allowEmpty=False)
1390 if self._userData.get("email", "") != "" and self._isEmailAlreadyUsed():
1391 raise ServiceAccessError(_("The email address is already used by another chairperson. Chairperson not modified."))
1393 def _isEmailAlreadyUsed(self):
1394 for chair in self._conf.getChairList():
1395 # check if the email is already used by other different chairperson
1396 if self._userData.get("email", "") == chair.getEmail() and self._chairId != str(chair.getId()):
1397 return True
1398 return False
1400 def _editChair(self, chair):
1401 chair.setTitle(self._userData.get("title", ""))
1402 chair.setFirstName(self._userData.get("firstName", ""))
1403 chair.setFamilyName(self._userData.get("familyName", ""))
1404 chair.setAffiliation(self._userData.get("affiliation", ""))
1405 chair.setEmail(self._userData.get("email", ""))
1406 chair.setAddress(self._userData.get("address", ""))
1407 chair.setPhone(self._userData.get("phone", ""))
1408 chair.setFax(self._userData.get("fax", ""))
1409 #If the chairperson needs to be given management rights
1410 if self._userData.get("manager", None):
1411 avl = AvatarHolder().match({"email": self._userData.get("email", "")},
1412 forceWithoutExtAuth=True, exact=True)
1413 if avl:
1414 av = avl[0]
1415 self._conf.grantModification(av)
1416 else:
1417 #Apart from granting the chairman, we add it as an Indico user
1418 self._conf.grantModification(chair)
1420 def _getAnswer(self):
1421 chair = self._conf.getChairById(self._chairId)
1422 self._editChair(chair)
1423 return self._getChairPersonsList()
1425 class ConferenceProgramDescriptionModification( ConferenceHTMLModificationBase ):
1427 Conference program description modification
1429 def _handleSet(self):
1430 self._target.setProgramDescription(self._value)
1432 def _handleGet(self):
1433 return self._target.getProgramDescription()
1435 class ConferenceAddParticipantBase(ConferenceModifBase):
1437 def _checkParams(self):
1438 ConferenceModifBase._checkParams(self)
1439 self._pm = ParameterManager(self._params)
1442 def _isEmailAlreadyUsed(self, email):
1443 for part in self._conf.getParticipation().getParticipantList():
1444 if email == part.getEmail():
1445 return True
1446 return False
1449 class ConferenceParticipantAddExisting(ConferenceAddParticipantBase):
1451 def _checkParams(self):
1452 ConferenceAddParticipantBase._checkParams(self)
1453 self._action = self._pm.extract("action", pType=str, allowEmpty=False)
1454 self._userList = self._pm.extract("userList", pType=list, allowEmpty=False)
1455 # Check if there is already a participant with the same email
1456 for part in self._userList:
1457 if self._isEmailAlreadyUsed(part["email"]):
1458 raise ServiceAccessError(_("The email address (%s) of a participant you are trying to add is already used by another participant. Participant(s) not added.") % part["email"])
1460 def _getAnswer(self):
1461 eventManager = self._getUser()
1462 for part in self._userList:
1463 ah = AvatarHolder()
1464 av = ah.getById(part["id"])
1465 participant = Participant(self._conf, av)
1466 if self._action == "add":
1467 self._conf.getParticipation().addParticipant(participant, eventManager)
1468 elif self._action == "invite":
1469 self._conf.getParticipation().inviteParticipant(participant, eventManager)
1470 return fossilize(self._conf.getParticipation().getParticipantList())
1472 class ConferenceManagerListBase(ConferenceModifBase):
1474 def _getManagersList(self):
1475 result = fossilize(self._conf.getManagerList())
1476 # get pending users
1477 for email in self._conf.getAccessController().getModificationEmail():
1478 pendingUser = {}
1479 pendingUser["email"] = email
1480 pendingUser["pending"] = True
1481 result.append(pendingUser)
1482 return result
1485 class ConferenceProtectionAddExistingManager(ConferenceManagerListBase):
1487 def _checkParams(self):
1488 ConferenceManagerListBase._checkParams(self)
1489 pm = ParameterManager(self._params)
1490 self._userList = pm.extract("userList", pType=list, allowEmpty=False)
1492 def _getAnswer(self):
1493 ph = PrincipalHolder()
1494 for user in self._userList:
1495 self._conf.grantModification(ph.getById(user["id"]))
1496 return self._getManagersList()
1499 class ConferenceProtectionRemoveManager(ConferenceManagerListBase):
1501 def _checkParams(self):
1502 ConferenceManagerListBase._checkParams(self)
1503 pm = ParameterManager(self._params)
1504 self._managerId = pm.extract("userId", pType=str, allowEmpty=False)
1505 self._kindOfUser = pm.extract("kindOfUser", pType=str, allowEmpty=True, defaultValue=None)
1507 def _getAnswer(self):
1508 if self._kindOfUser == "pending":
1509 # remove pending email, self._submitterId is an email address
1510 self._conf.getAccessController().revokeModificationEmail(self._managerId)
1511 else:
1512 ph = PrincipalHolder()
1513 self._conf.revokeModification(ph.getById(self._managerId))
1514 return self._getManagersList()
1517 class ConferenceProtectionAddExistingRegistrar(ConferenceModifBase):
1519 def _checkParams(self):
1520 ConferenceModifBase._checkParams(self)
1521 pm = ParameterManager(self._params)
1522 self._userList = pm.extract("userList", pType=list, allowEmpty=False)
1524 def _getAnswer(self):
1525 ph = PrincipalHolder()
1526 for user in self._userList:
1527 self._conf.addToRegistrars(ph.getById(user["id"]))
1528 return fossilize(self._conf.getRegistrarList())
1531 class ConferenceProtectionRemoveRegistrar(ConferenceManagerListBase):
1533 def _checkParams(self):
1534 ConferenceManagerListBase._checkParams(self)
1535 pm = ParameterManager(self._params)
1536 self._registrarId = pm.extract("userId", pType=str, allowEmpty=False)
1538 def _getAnswer(self):
1539 ph = PrincipalHolder()
1540 self._conf.removeFromRegistrars(ph.getById(self._registrarId))
1541 return fossilize(self._conf.getRegistrarList())
1543 class ConferenceExportURLs(ConferenceDisplayBase, ExportToICalBase):
1545 def _checkParams(self):
1546 ConferenceDisplayBase._checkParams(self)
1547 ExportToICalBase._checkParams(self)
1549 def _getAnswer(self):
1550 result = {}
1552 minfo = info.HelperMaKaCInfo.getMaKaCInfoInstance()
1554 urls = generate_public_auth_request(self._apiMode, self._apiKey, '/export/event/%s.ics'%self._target.getId(), {}, minfo.isAPIPersistentAllowed() and self._apiKey.isPersistentAllowed(), minfo.isAPIHTTPSRequired())
1555 result["publicRequestURL"] = urls["publicRequestURL"]
1556 result["authRequestURL"] = urls["authRequestURL"]
1557 urls = generate_public_auth_request(self._apiMode, self._apiKey, '/export/event/%s.ics'%self._target.getId(), {'detail': "contribution"}, minfo.isAPIPersistentAllowed() and self._apiKey.isPersistentAllowed(), minfo.isAPIHTTPSRequired())
1558 result["publicRequestDetailedURL"] = urls["publicRequestURL"]
1559 result["authRequestDetailedURL"] = urls["authRequestURL"]
1560 return result
1562 methodMap = {
1563 "main.changeTitle": ConferenceTitleModification,
1564 "main.changeSupportEmail": ConferenceSupportEmailModification,
1565 "main.changeSupport": ConferenceSupportModification,
1566 "main.changeSpeakerText": ConferenceSpeakerTextModification,
1567 "main.changeOrganiserText": ConferenceOrganiserTextModification,
1568 "main.changeDefaultStyle": ConferenceDefaultStyleModification,
1569 "main.changeVisibility": ConferenceVisibilityModification,
1570 "main.changeType": ConferenceTypeModification,
1571 "main.changeDescription": ConferenceDescriptionModification,
1572 "main.changeAdditionalInfo": ConferenceAdditionalInfoModification,
1573 "main.changeDates": ConferenceStartEndDateTimeModification,
1574 "main.changeBooking": ConferenceBookingModification,
1575 "main.displayBooking": ConferenceBookingModification,
1576 "main.changeShortURL": ConferenceShortURLModification,
1577 "main.changeKeywords": ConferenceKeywordsModification,
1578 "main.changeTimezone": ConferenceTimezoneModification,
1579 "main.addExistingChairPerson": ConferenceAddExistingChairPerson,
1580 "main.addNewChairPerson": ConferenceAddNewChairPerson,
1581 "main.removeChairPerson": ConferenceRemoveChairPerson,
1582 "main.editChairPerson": ConferenceEditChairPerson,
1583 "program.changeDescription": ConferenceProgramDescriptionModification,
1584 "rooms.list" : ConferenceListUsedRooms,
1585 "contributions.list" : ConferenceListContributionsReview,
1586 "contributions.listAll" : ConferenceListContributions,
1587 "contributions.delete": ConferenceDeleteContributions,
1588 "sessions.listAll" : ConferenceListSessions,
1589 "pic.delete": ConferencePicDelete,
1590 "social.toggle": ConferenceSocialBookmarksToggle,
1591 "showConcurrentEvents": ShowConcurrentEvents,
1592 # "getFields": ConferenceGetFields,
1593 "getFieldsAndContribTypes": ConferenceGetFieldsAndContribTypes,
1594 "participation.allowDisplay": ConferenceParticipantsDisplay,
1595 "participation.addedInfo": ConferenceParticipantsAddedInfo,
1596 "participation.allowForApply": ConferenceParticipantsAllowForApplying,
1597 "participation.autopAccept": ConferenceParticipantsAutoAccept,
1598 "participation.setNumMaxParticipants": ConferenceParticipantsSetNumMaxParticipants,
1599 "participation.applyParticipant": ConferenceApplyParticipant,
1600 "participation.addParticipant": ConferenceAddParticipant,
1601 "participation.editParticipant": ConferenceEditParticipant,
1602 "participation.editPending": ConferenceEditPending,
1603 "participation.addParticipants": ConferenceAddParticipants,
1604 "participation.inviteParticipants": ConferenceInviteParticipants,
1605 "participation.removeParticipants": ConferenceRemoveParticipants,
1606 "participation.markPresent": ConferenceMarkPresenceParticipants,
1607 "participation.markAbsence": ConferenceMarkAbsentParticipants,
1608 "participation.excuseAbsence": ConferenceExcuseAbsenceParticipants,
1609 "participation.emailParticipants": ConferenceEmailParticipants,
1610 "participation.acceptPending": ConferenceAcceptPendingParticipants,
1611 "participation.rejectPending": ConferenceRejectPendingParticipants,
1612 "participation.rejectPendingWithEmail": ConferenceRejectWithEmailPendingParticipants,
1613 "protection.getAllowedUsersList": ConferenceProtectionUserList,
1614 "protection.addAllowedUsers": ConferenceProtectionAddUsers,
1615 "protection.removeAllowedUser": ConferenceProtectionRemoveUser,
1616 "protection.toggleDomains": ConferenceProtectionToggleDomains,
1617 "protection.setAccessKey": ConferenceProtectionSetAccessKey,
1618 "protection.setModifKey": ConferenceProtectionSetModifKey,
1619 "protection.changeContactInfo": ConferenceContactInfoModification,
1620 "alarm.sendTestNow": ConferenceAlarmSendTestNow,
1621 "protection.addExistingManager": ConferenceProtectionAddExistingManager,
1622 "protection.removeManager": ConferenceProtectionRemoveManager,
1623 "protection.addExistingRegistrar": ConferenceProtectionAddExistingRegistrar,
1624 "protection.removeRegistrar": ConferenceProtectionRemoveRegistrar,
1625 "api.getExportURLs": ConferenceExportURLs