1 # -*- coding: utf-8 -*-
4 ## This file is part of CDS Indico.
5 ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN.
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.
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.
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 from urlparse
import urljoin
22 """Base definitions for the request handlers (rh). A rh is a class which
23 complies to a well defined interface and which from a mod_python request knows
24 which action to carry out in order to handle the request made. This means that
25 each of the possible HTTP ports of the system will have a rh which will know
26 what to do depending on the parameter values received, etc.
28 import copy
, time
, os
, sys
, random
, re
, socket
30 from datetime
import datetime
, timedelta
33 from indico
.web
.wsgi
.indico_wsgi_handler_utils
import Field
34 from indico
.web
.wsgi
import webinterface_handler_config
as apache
37 from ZODB
.POSException
import ConflictError
, POSKeyError
38 from ZEO
.Exceptions
import ClientDisconnected
40 from MaKaC
.common
import fossilize
41 from MaKaC
.webinterface
.pages
.conferences
import WPConferenceModificationClosed
43 import MaKaC
.webinterface
.session
as session
44 import MaKaC
.webinterface
.urlHandlers
as urlHandlers
45 import MaKaC
.webinterface
.pages
.errors
as errors
46 from MaKaC
.common
.general
import *
48 from MaKaC
.accessControl
import AccessWrapper
49 from MaKaC
.common
import DBMgr
, Config
, security
50 from MaKaC
.errors
import MaKaCError
, ModificationError
, AccessError
, KeyAccessError
, TimingError
, ParentTimingError
, EntryTimingError
, FormValuesError
, NoReportError
, NotFoundError
, HtmlScriptError
, HtmlForbiddenTag
, ConferenceClosedError
, HostnameResolveError
51 from MaKaC
.webinterface
.mail
import GenericMailer
, GenericNotification
52 from xml
.sax
.saxutils
import escape
54 from MaKaC
.common
.utils
import truncate
55 from MaKaC
.common
.logger
import Logger
56 from MaKaC
.common
.contextManager
import ContextManager
57 from indico
.util
.i18n
import _
, availableLocales
59 from MaKaC
.plugins
import PluginsHolder
60 from MaKaC
.user
import Group
, Avatar
61 from MaKaC
.accessControl
import AdminList
63 from MaKaC
.plugins
.base
import OldObservable
66 class RequestHandlerBase(OldObservable
):
70 def __init__(self
, req
):
72 raise Exception("Request object not initialised")
75 def _checkProtection( self
):
82 Returns True if current user is a user or has either a modification
83 or access key in their session.
84 auth_keys is the set of permissible session keys which do not require user login.
86 auth_keys
= ["modifKeys"]#, "accessKeys"] Cookie would stay forever and force https
89 if self
._websession
.getVar(key
):
92 return self
._getUser
()
96 Returns the access wrapper related to this session/user
102 Returns the current user
104 return self
._aw
.getUser()
106 def _setUser(self
, newUser
=None):
108 Sets the current user
110 self
._aw
.setUser(newUser
)
112 def getCurrentURL( self
):
114 Gets the "current URL", through the URL handler
118 return self
._uh
.getURL( self
._target
)
120 def getRequestURL( self
, secure
=False ):
122 Reconstructs the request URL
125 return urljoin(Config
.getInstance().getBaseSecureURL(), self
._req
.unparsed_uri
)
127 return self
._req
.construct_url(self
._req
.unparsed_uri
)
131 If the RH must be HTTPS and there is a BaseSecurURL, then use it!
133 return self
._tohttps
and Config
.getInstance().getBaseSecureURL()
135 def getRequestParams( self
):
138 def getRequestHTTPHeaders( self
):
139 return self
._req
.headers_in
141 def _setLang(self
, params
=None):
143 # allow to choose the lang from params
144 if params
and 'lang' in params
:
145 newLang
= params
.get('lang', '')
146 for lang
in availableLocales
:
147 if newLang
.lower() == lang
.lower():
148 self
._websession
.setLang(lang
)
151 lang
=self
._websession
.getLang()
152 Logger
.get('i18n').debug("lang:%s"%lang
)
155 from indico
.util
.i18n
import setLocale
159 hostIP
= str(self
._req
.get_remote_ip())
161 minfo
= info
.HelperMaKaCInfo
.getMaKaCInfoInstance()
163 # if we're behind a proxy, use X-Forwarded-For
164 return self
._req
.headers_in
.get("X-Forwarded-For", hostIP
).split(", ")[-1]
168 accessWrapper
= property( getAW
)
171 class RH(RequestHandlerBase
):
172 """This class is the base for request handlers of the application. A request
173 handler will be instantiated when a web request arrives to mod_python;
174 the mp layer will forward the request to the corresponding request
175 handler which will know which action has to be performed (displaying a
176 web page or performing some operation and redirecting to another page).
177 Request handlers will be responsible for parsing the parameters coming
178 from a mod_python request, handle the errors which occurred during the
179 action to perform, managing the sessions, checking security for each
180 operation (thus they implement the access control system of the web
182 It is important to encapsulate all this here as in case of changing
183 the web application framework we'll just need to adapt this layer (the
184 rest of the system wouldn't need any change).
187 _uh - (URLHandler) Associated URLHandler which points to the
189 _req - (mod_python.Request) mod_python request received for the
191 _requestStarted - (bool) Flag which tells whether a DB transaction
192 has been started or not.
193 _websession - ( webinterface.session.sessionManagement.PSession )
194 Web session associated to the HTTP request.
195 _aw - (AccessWrapper) Current access information for the rh.
196 _target - (Locable) Reference to an object which is the destination
197 of the operations needed to carry out the rh. If set it must
198 provide (through the standard Locable interface) the methods
199 to get the url parameters in order to reproduce the access to
201 _reqParams - (dict) Dictionary containing the received HTTP
202 parameters (independently of the method) transformed into
203 python data types. The key is the parameter name while the
204 value should be the received paramter value (or values).
206 _tohttps
= False # set this value to True for the RH that must be HTTPS when there is a BaseSecureURL
207 _doNotSanitizeFields
= []
209 def __init__( self
, req
):
210 """Constructor. Initialises the rh setting up basic attributes so it is
211 able to process the request.
214 req - (mod_python.Request) mod_python request received for the
217 RequestHandlerBase
.__init
__(self
, req
)
218 self
._requestStarted
= False
219 self
._websession
= None
220 self
._aw
= AccessWrapper() #Fill in the aw instance with the current information
223 self
._startTime
= None
225 self
._tempFilesToDelete
= []
226 self
._doProcess
= True #Flag which indicates whether the RH process
227 # must be carried out; this is useful for
228 # the checkProtection methods when they
229 # detect that an inmediate redirection is
232 # Methods =============================================================
234 def getTarget( self
):
237 def _setSession( self
):
238 """Sets up a reference to the corresponding web session. It uses the
239 session manager to retrieve the session corresponding to the
240 received request and makes sure it is a valid one. In case of having
241 an invalid session it reset client settings and creates a new one.
243 if not self
._websession
:
244 sm
= session
.getSessionManager()
246 self
._websession
= sm
.get_session( self
._req
)
247 except session
.SessionError
, e
:
248 sm
.revoke_session_cookie( self
._req
)
249 self
._websession
= sm
.get_session( self
._req
)
250 sm
.maintain_session( self
._req
, self
._websession
)
252 def _getSession( self
):
253 """Returns the web session associated to the received mod_python
256 if not self
._websession
:
258 return self
._websession
260 def _setSessionUser( self
):
263 self
._aw
.setUser( self
._getSession
().getUser() )
265 def _getRequestParams( self
):
266 return self
._reqParams
268 def getRequestParams( self
):
269 return self
._getRequestParams
()
271 def _disableCaching(self
):
273 Disables caching, i.e. for materials
276 # IE doesn't seem to like 'no-cache' Cache-Control headers...
277 if (re
.match(r
'.*MSIE.*', self
._req
.headers_in
.get("User-Agent",""))):
278 # actually, the only way to safely disable caching seems to be this one
279 self
._req
.headers_out
["Cache-Control"] = "private"
280 self
._req
.headers_out
["Expires"] = "-1"
282 self
._req
.headers_out
["Cache-Control"] = "no-store, no-cache, must-revalidate"
283 self
._req
.headers_out
["Pragma"] = "no-cache"
285 def _redirect( self
, targetURL
, noCache
=False ):
286 """Utility for redirecting the client web browser to the specified
289 newURL - Target URL of the redirection
291 #check if there is no \r\n character to avoid http header injection
294 if "\r" in str(targetURL
) or "\n" in str(targetURL
):
295 raise MaKaCError(_("http header CRLF injection detected"))
296 self
._req
.headers_out
["Location"] = str(targetURL
)
299 self
._disableCaching
()
301 self
._req
.status
= apache
.HTTP_SEE_OTHER
305 def _checkHttpsRedirect(self
):
307 If HTTPS must be used but it is not, redirect!
309 if self
.use_https() and not self
._req
.is_https():
310 self
._redirect
(self
.getRequestURL(secure
=True))
315 def _normaliseListParam( self
, param
):
316 if not isinstance(param
, list):
320 def _processError( self
, ex
):
325 def _checkParams( self
, params
):
330 def _process( self
):
335 def _processGeneralError(self
,e
):
336 """Treats general errors occured during the process of a RH.
339 Logger
.get('requestHandler').info('Request %s finished with: "%s"' % (id(self
._req
), e
))
341 p
=errors
.WPGenericError(self
)
345 def _getTruncatedParams(self
):
346 """ Truncates params, so that file objects do not show up in the logs """
350 for key
,value
in self
._reqParams
.iteritems():
351 if isinstance(value
, Field
):
352 params
[key
] = "<FILE>"
353 elif type(value
) == str:
354 params
[key
] = truncate(value
, 1024)
360 def _processUnexpectedError(self
,e
):
364 Logger
.get('requestHandler').exception('Request %s failed: "%s"\n\nurl: %s\n\nparameters: %s\n\n' % (id(self
._req
), e
,self
.getRequestURL(), self
._getTruncatedParams
()))
365 p
=errors
.WPUnexpectedError(self
)
368 def _processHostnameResolveError(self
,e
):
372 Logger
.get('requestHandler').exception('Request %s failed: "%s"\n\nurl: %s\n\nparameters: %s\n\n' % (id(self
._req
), e
,self
.getRequestURL(), self
._getTruncatedParams
()))
373 p
=errors
.WPHostnameResolveError(self
)
377 def _processAccessError(self
,e
):
378 """Treats access errors occured during the process of a RH.
380 Logger
.get('requestHandler').info('Request %s finished with AccessError: "%s"' % (id(self
._req
), e
))
382 self
._req
.status
= apache
.HTTP_FORBIDDEN
383 p
=errors
.WPAccessError(self
)
386 def _processKeyAccessError(self
,e
):
387 """Treats access errors occured during the process of a RH.
389 Logger
.get('requestHandler').info('Request %s finished with KeyAccessError: "%s"' % (id(self
._req
), e
))
391 self
._req
.status
= apache
.HTTP_FORBIDDEN
392 # We are going to redirect to the page asking for access key
393 # and so it must be https if there is a BaseSecureURL. And that's
394 # why we set _tohttps to True.
396 if self
._checkHttpsRedirect
():
398 p
=errors
.WPKeyAccessError(self
)
401 def _processModificationError(self
,e
):
402 """Treats modification errors occured during the process of a RH.
405 Logger
.get('requestHandler').info('Request %s finished with ModificationError: "%s"' % (id(self
._req
), e
))
407 p
=errors
.WPModificationError(self
)
410 def _processConferenceClosedError(self
,e
):
411 """Treats access to modification pages for conferences when they are closed.
413 p
= WPConferenceModificationClosed( self
, e
._conf
)
416 def _processTimingError(self
,e
):
417 """Treats timing errors occured during the process of a RH.
420 Logger
.get('requestHandler').info('Request %s finished with TimingError: "%s"' % (id(self
._req
), e
))
422 p
=errors
.WPTimingError(self
,e
)
425 def _processNoReportError(self
,e
):
426 """Process errors without reporting
429 Logger
.get('requestHandler').info('Request %s finished with NoReportError: "%s"' % (id(self
._req
), e
))
431 p
=errors
.WPNoReportError(self
,e
)
434 def _processNotFoundError(self
,e
):
435 """Process not found error; uses NoReportError template
438 Logger
.get('requestHandler').info('Request %s finished with NotFoundError: "%s"' % (id(self
._req
), e
))
441 self
._req
.status
= apache
.HTTP_NOT_FOUND
445 p
=errors
.WPNoReportError(self
,e
)
448 def _processParentTimingError(self
,e
):
449 """Treats timing errors occured during the process of a RH.
452 Logger
.get('requestHandler').info('Request %s finished with ParentTimingError: "%s"' % (id(self
._req
), e
))
454 p
=errors
.WPParentTimingError(self
,e
)
457 def _processEntryTimingError(self
,e
):
458 """Treats timing errors occured during the process of a RH.
461 Logger
.get('requestHandler').info('Request %s finished with EntryTimingError: "%s"' % (id(self
._req
), e
))
463 p
=errors
.WPEntryTimingError(self
,e
)
466 def _processFormValuesError(self
,e
):
467 """Treats user input related errors occured during the process of a RH.
470 Logger
.get('requestHandler').info('Request %s finished with FormValuesError: "%s"' % (id(self
._req
), e
))
472 p
=errors
.WPFormValuesError(self
,e
)
475 def _processHtmlScriptError(self
, e
):
477 Logger
.get('requestHandler').info('Request %s finished with ProcessHtmlScriptError: "%s"' % (id(self
._req
), e
))
479 p
=errors
.WPHtmlScriptError(self
, escape(str(e
)))
482 def _processRestrictedHTML(self
, e
):
484 Logger
.get('requestHandler').info('Request %s finished with ProcessRestrictedHTMLError: "%s"' % (id(self
._req
), e
))
486 p
=errors
.WPRestrictedHTML(self
, escape(str(e
)))
489 def process( self
, params
):
492 profile
= Config
.getInstance().getProfile()
497 self
._startTime
= datetime
.now()
500 ContextManager
.destroy()
501 ContextManager
.set('currentRH', self
)
503 #redirect to https if necessary
504 if self
._checkHttpsRedirect
():
507 DBMgr
.getInstance().startRequest()
508 self
._startRequestSpecific
2RH
() # I.e. implemented by Room Booking request handlers
509 textLog
.append("%s : Database request started"%(datetime
.now() - self
._startTime
))
510 Logger
.get('requestHandler').info('[pid=%s] Request %s started (%s)' % (os
.getpid(),id(self
._req
), self
._req
.unparsed_uri
))
512 # notify components that the request has started
513 self
._notify
('requestStarted', self
._req
)
519 # notify components that the request is being retried
520 self
._notify
('requestRetry', self
._req
, 10 - retry
)
523 Logger
.get('requestHandler').info('\t[pid=%s] from host %s' % (os
.getpid(), self
.getHostIP()))
525 # clear the fossile cache at the start of each request
526 fossilize
.clearCache()
528 DBMgr
.getInstance().sync()
529 # keep a link to the web session in the access wrapper
530 # this is used for checking access/modification key existence
531 # in the user session
532 self
._aw
.setIP( self
.getHostIP() )
533 self
._aw
.setSession(self
._getSession
())
534 #raise(str(dir(self._websession)))
535 self
._setSessionUser
()
536 self
._setLang
(params
)
539 Logger
.get('requestHandler').info('Request %s identified with user %s (%s)' % (id(self
._req
), self
._getUser
().getFullName(), self
._getUser
().getId()))
540 if not self
._tohttps
and Config
.getInstance().getAuthenticatedEnforceSecure():
542 if self
._checkHttpsRedirect
():
545 #if self._getUser() != None and self._getUser().getId() == "893":
547 self
._reqParams
= copy
.copy( params
)
548 self
._checkParams
( self
._reqParams
)
550 self
._checkProtection
()
551 security
.Sanitization
.sanitizationCheck(self
._target
,
553 self
._aw
, self
._doNotSanitizeFields
)
556 import profile
, pstats
557 proffilename
= os
.path
.join(Config
.getInstance().getTempDir(), "stone%s.prof" % str(random
.random()))
559 profile
.runctx("result[0] = self._process()", globals(), locals(), proffilename
)
562 res
= self
._process
()
565 # notify components that the request has finished
566 self
._notify
('requestFinished', self
._req
)
567 self
._endRequestSpecific
2RH
( True ) # I.e. implemented by Room Booking request handlers
569 DBMgr
.getInstance().endRequest( True )
570 Logger
.get('requestHandler').info('Request %s successful' % (id(self
._req
)))
571 #request succesfull, now, doing tas that must be done only once
574 self
._deleteTempFiles
()
578 except MaKaCError
, e
:
579 #DBMgr.getInstance().endRequest(False)
580 res
= self
._processError
(e
)
581 except (ConflictError
, POSKeyError
):
583 Logger
.get('requestHandler').warning('Conflict in Database! (Request %s)\n%s' % (id(self
._req
), traceback
.format_exc()))
584 self
._abortSpecific
2RH
()
585 DBMgr
.getInstance().abort()
588 except ClientDisconnected
:
589 Logger
.get('requestHandler').warning('Client Disconnected! (Request %s)' % id(self
._req
) )
590 self
._abortSpecific
2RH
()
591 DBMgr
.getInstance().abort()
595 except KeyAccessError
, e
:
596 #Key Access error treatment
597 res
= self
._processKeyAccessError
( e
)
598 self
._endRequestSpecific
2RH
( False )
599 DBMgr
.getInstance().endRequest(False)
600 except AccessError
, e
:
601 #Access error treatment
602 res
= self
._processAccessError
( e
)
603 self
._endRequestSpecific
2RH
( False )
604 DBMgr
.getInstance().endRequest(False)
605 except HostnameResolveError
, e
:
606 res
= self
._processHostnameResolveError
( e
)
607 self
._endRequestSpecific
2RH
( False )
608 DBMgr
.getInstance().endRequest(False)
609 except ModificationError
, e
:
610 #Modification error treatment
611 res
= self
._processModificationError
( e
)
612 self
._endRequestSpecific
2RH
( False )
613 DBMgr
.getInstance().endRequest(False)
614 except ParentTimingError
, e
:
615 #Modification error treatment
616 res
= self
._processParentTimingError
( e
)
617 self
._endRequestSpecific
2RH
( False )
618 DBMgr
.getInstance().endRequest(False)
619 except EntryTimingError
, e
:
620 #Modification error treatment
621 res
= self
._processEntryTimingError
( e
)
622 self
._endRequestSpecific
2RH
( False )
623 DBMgr
.getInstance().endRequest(False)
624 except TimingError
, e
:
625 #Modification error treatment
626 res
= self
._processTimingError
( e
)
627 self
._endRequestSpecific
2RH
( False )
628 DBMgr
.getInstance().endRequest(False)
629 except FormValuesError
, e
:
630 #Error filling the values of a form
631 res
= self
._processFormValuesError
( e
)
632 self
._endRequestSpecific
2RH
( False )
633 DBMgr
.getInstance().endRequest(False)
634 except ConferenceClosedError
, e
:
635 #Modification error treatment
636 res
= self
._processConferenceClosedError
( e
)
637 self
._endRequestSpecific
2RH
( False )
638 DBMgr
.getInstance().endRequest(False)
639 except NoReportError
, e
:
640 #Error without report option
641 res
= self
._processNoReportError
( e
)
642 DBMgr
.getInstance().endRequest(False)
643 except NotFoundError
, e
:
645 res
= self
._processNotFoundError
( e
)
646 DBMgr
.getInstance().endRequest(False)
647 except HtmlScriptError
,e
:
648 res
= self
._processHtmlScriptError
(e
)
649 DBMgr
.getInstance().endRequest(False)
650 except HtmlForbiddenTag
,e
:
651 res
= self
._processRestrictedHTML
(e
)
652 DBMgr
.getInstance().endRequest(False)
653 except MaKaCError
, e
:
654 res
= self
._processGeneralError
( e
)
655 DBMgr
.getInstance().endRequest(False)
656 except ValueError, e
:
657 res
= self
._processGeneralError
( e
)
658 DBMgr
.getInstance().endRequest(False)
659 except Exception, e
: #Generic error treatment
660 res
= self
._processUnexpectedError
( e
)
661 #DBMgr.getInstance().endRequest(False)
662 #self._endRequestSpecific2RH( False )
664 #cancels any redirection
666 del self
._req
.headers_out
["Location"]
667 except AttributeError:
670 self
._req
.status
=apache
.HTTP_INTERNAL_SERVER_ERROR
674 totalTime
= (datetime
.now() - self
._startTime
)
675 textLog
.append("%s : Request ended"%totalTime
)
678 if profile
and totalTime
> timedelta(0, 1) and os
.path
.isfile(proffilename
):
679 rep
= Config
.getInstance().getTempDir()
680 stats
= pstats
.Stats(proffilename
)
682 stats
.sort_stats('cumulative', 'time', 'calls')
683 stats
.dump_stats(os
.path
.join(rep
, "IndicoRequestProfile.log"))
684 output
= StringIO
.StringIO()
686 stats
.print_stats(100)
687 sys
.stdout
= sys
.__stdout
__
688 s
= output
.getvalue()
689 f
= file(os
.path
.join(rep
, "IndicoRequest.log"), 'a+')
690 f
.write("--------------------------------\n")
691 f
.write("URL : " + self
._req
.construct_url(self
._req
.unparsed_uri
) + "\n")
692 f
.write("%s : start request\n"%self
._startTime
)
693 f
.write("params:%s"%params
)
694 f
.write("\n".join(textLog
))
696 f
.write("retried : %d\n"%(10-retry
))
698 f
.write("--------------------------------\n\n")
700 if profile
and proffilename
!= "" and os
.path
.exists(proffilename
):
701 os
.remove(proffilename
)
703 # In case of no process needed, we should return empty string to avoid erroneous ouput
704 # specially with getVars breaking the JS files.
705 if not self
._doProcess
:
713 def _sendEmails( self
):
714 if hasattr( self
, "_emailsToBeSent" ):
715 for email
in self
._emailsToBeSent
:
716 GenericMailer
.send(GenericNotification(email
))
718 def _deleteTempFiles( self
):
719 if len(self
._tempFilesToDelete
) > 0:
720 for file in self
._tempFilesToDelete
:
723 def _startRequestSpecific2RH( self
):
725 Works like DBMgr.getInstance().startRequest() but is specific to
726 request handler. It is used to connect to other database only
727 in choosen request handlers.
729 I.e. all Room Booking request handlers override this
730 method to connect to Room Booking backend.
734 def _endRequestSpecific2RH( self
, commit
):
736 Works like DBMgr.getInstance().endRequest() but is specific to
737 request handler. It is used to disconnect from other database only
738 in choosen request handlers.
740 I.e. all Room Booking request handlers override this
741 method to disconnect from Room Booking backend.
745 def _syncSpecific2RH( self
):
747 Works like DBMgr.getInstance().sync() but is specific to
748 request handler. It is used to connect to other database only
749 in choosen request handlers.
751 I.e. all Room Booking request handlers override this
752 method to sync backend.
756 def _abortSpecific2RH( self
):
758 Works like DBMgr.getInstance().abort() but is specific to
759 request handler. It is used to abort transactions of other database
760 only in choosen request handlers.
762 I.e. all Room Booking request handlers override this method.
766 # Properties =============================================================
771 from MaKaC
.rb_location
import CrossLocationDB
772 import MaKaC
.common
.info
as info
774 class RoomBookingDBMixin
: # It's _not_ RH
777 Only _some_ Request Handlers should connect to
778 room booking database.
780 Mix in this class into all Request Handlers,
781 which must use Room Booking backend.
785 class RHExample( RoomBookingDBMixin, RHProtected ):
788 NOTE: it is important to put RoomBookingDBMixin as first
792 def _startRequestSpecific2RH( self
):
793 minfo
= info
.HelperMaKaCInfo
.getMaKaCInfoInstance()
794 if minfo
.getRoomBookingModuleActive():
795 CrossLocationDB
.connect()
797 def _endRequestSpecific2RH( self
, commit
= True ):
798 minfo
= info
.HelperMaKaCInfo
.getMaKaCInfoInstance()
799 if minfo
.getRoomBookingModuleActive():
800 if commit
: CrossLocationDB
.commit()
801 else: CrossLocationDB
.rollback()
802 CrossLocationDB
.disconnect()
804 def _syncSpecific2RH( self
):
805 minfo
= info
.HelperMaKaCInfo
.getMaKaCInfoInstance()
806 if minfo
.getRoomBookingModuleActive():
807 CrossLocationDB
.sync()
809 def _abortSpecific2RH( self
):
810 minfo
= info
.HelperMaKaCInfo
.getMaKaCInfoInstance()
811 if minfo
.getRoomBookingModuleActive():
812 CrossLocationDB
.rollback()
815 class RHProtected( RH
):
817 def _getLoginURL( self
):
818 return urlHandlers
.UHSignIn
.getURL(self
.getRequestURL())
820 def _checkSessionUser( self
):
824 if self
._getUser
() == None:
825 self
._redirect
( self
._getLoginURL
() )
826 self
._doProcess
= False
828 def _checkProtection( self
):
829 self
._checkSessionUser
()
832 class RHRoomBookingProtected( RHProtected
):
834 def _checkSessionUser( self
):
835 user
= self
._getUser
()
837 self
._redirect
( self
._getLoginURL
() )
838 self
._doProcess
= False
841 if PluginsHolder().getPluginType("RoomBooking").isActive():
842 if not AdminList
.getInstance().isAdmin(user
) and PluginsHolder().getPluginType("RoomBooking").getOption("AuthorisedUsersGroups").getValue() != []:
843 authenticatedUser
= False
844 for entity
in PluginsHolder().getPluginType("RoomBooking").getOption("AuthorisedUsersGroups").getValue():
845 if isinstance(entity
, Group
) and entity
.containsUser(user
) or \
846 isinstance(entity
, Avatar
) and entity
== user
:
847 authenticatedUser
= True
849 if not authenticatedUser
:
854 class RHDisplayBaseProtected( RHProtected
):
856 def _checkProtection( self
):
857 if not self
._target
.canAccess( self
.getAW() ):
858 from MaKaC
.conference
import Link
, LocalFile
, Category
859 if isinstance(self
._target
,Link
) or isinstance(self
._target
,LocalFile
):
860 target
= self
._target
.getOwner()
862 target
= self
._target
863 if not isinstance(self
._target
, Category
) and target
.isProtected():
864 if target
.getAccessKey() != "" or target
.getConference() and target
.getConference().getAccessKey() != "":
865 raise KeyAccessError()
866 if self
._getUser
() == None:
867 self
._checkSessionUser
()
872 class RHModificationBaseProtected( RHProtected
):
876 def _checkProtection( self
):
877 if not self
._target
.canModify( self
.getAW() ):
878 if self
._target
.getModifKey() != "":
879 raise ModificationError()
880 if self
._getUser
() == None:
881 self
._checkSessionUser
()
883 raise ModificationError()
884 if hasattr(self
._target
, "getConference") and not self
._allowClosed
:
885 if self
._target
.getConference().isClosed():
886 raise ConferenceClosedError(self
._target
.getConference())