source: indico/indico/MaKaC/webinterface/rh/base.py @ c3c8d1

burotelhello-world-walkthroughipv6v0.97-seriesv0.98-seriesv0.98.2v0.98.3v0.98b1v0.98b2v0.99v1.0v1.1
Last change on this file since c3c8d1 was c3c8d1, checked in by Pedro Ferreira <jose.pedro.ferreira@…>, 3 years ago

[FIX] IE Pragma:nocache bug for HTTPS downloads

  • Property mode set to 100644
File size: 30.6 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.
20from MaKaC.webinterface.pages.conferences import WPConferenceModificationClosed
21from MaKaC.common.TemplateExec import escapeHTMLForJS
22
23"""Base definitions for the request handlers (rh). A rh is a class which
24complies to a well defined interface and which from a mod_python request knows
25which action to carry out in order to handle the request made. This means that
26each of the possible HTTP ports of the system will have a rh which will know
27what to do depending on the parameter values received, etc.
28"""
29import copy, time, os, sys, random, re
30import StringIO
31from datetime import datetime, timedelta
32
33try:
34    from mod_python.util import Field
35    from mod_python import apache
36except ImportError:
37    pass
38from ZODB.POSException import ConflictError, POSKeyError
39from ZEO.Exceptions import ClientDisconnected
40
41from MaKaC.common import fossilize
42
43import MaKaC.webinterface.session as session
44import MaKaC.webinterface.urlHandlers as urlHandlers
45import MaKaC.webinterface.pages.errors as errors
46from MaKaC.common.general import *
47
48from MaKaC.accessControl import AccessWrapper
49from MaKaC.common import DBMgr, Config, security
50from MaKaC.errors import MaKaCError, ModificationError, AccessError, TimingError, ParentTimingError, EntryTimingError, FormValuesError, NoReportError, HtmlScriptError, HtmlForbiddenTag, ConferenceClosedError, HostnameResolveError
51from MaKaC.webinterface.mail import GenericMailer, GenericNotification
52from xml.sax.saxutils import escape
53
54from MaKaC.common.utils import truncate
55from MaKaC.common.logger import Logger
56from MaKaC.common.contextManager import ContextManager
57from MaKaC.i18n import _
58
59from MaKaC.common.contextManager import ContextManager
60from MaKaC.i18n import _
61
62from MaKaC.common.TemplateExec import escapeHTMLForJS
63
64from MaKaC.plugins.base import PluginsHolder
65from MaKaC.user import Group, Avatar
66from MaKaC.accessControl import AdminList
67
68
69class RequestHandlerBase(object):
70
71    _uh = None
72
73    def _checkProtection( self ):
74        """
75        """
76        pass
77
78    def getAW( self ):
79        """
80        Returns the access wrapper related to this session/user
81        """
82        return self._aw
83
84    def _getUser(self):
85        """
86        Returns the current user
87        """
88        return self._aw.getUser()
89
90    def _setUser(self, newUser=None):
91        """
92        Sets the current user
93        """
94        self._aw.setUser(newUser)
95
96    def getCurrentURL( self ):
97        """
98        Gets the "current URL", through the URL handler
99        """
100        if self._uh == None:
101            return ""
102        return self._uh.getURL( self._target )
103
104    def _setLang(self):
105        lang=self._websession.getLang()
106        Logger.get('i18n').debug("lang:%s"%lang)
107        if lang is None:
108            lang = "en_US"
109        from MaKaC import i18n
110        i18n.install('messages', lang, unicode=True)
111
112
113    accessWrapper = property( getAW )
114
115class RH(RequestHandlerBase):
116    """This class is the base for request handlers of the application. A request
117        handler will be instantiated when a web request arrives to mod_python;
118        the mp layer will forward the request to the corresponding request
119        handler which will know which action has to be performed (displaying a
120        web page or performing some operation and redirecting to another page).
121        Request handlers will be responsible for parsing the parameters coming
122        from a mod_python request, handle the errors which occurred during the
123        action to perform, managing the sessions, checking security for each
124        operation (thus they implement the access control system of the web
125        interface).
126        It is important to encapsulate all this here as in case of changing
127        the web application framework we'll just need to adapt this layer (the
128        rest of the system wouldn't need any change).
129
130        Attributes:
131            _uh - (URLHandler) Associated URLHandler which points to the
132                current rh.
133            _req - (mod_python.Request) mod_python request received for the
134                current rh.
135            _requestStarted - (bool) Flag which tells whether a DB transaction
136                has been started or not.
137            _websession - ( webinterface.session.sessionManagement.PSession )
138                Web session associated to the HTTP request.
139            _aw - (AccessWrapper) Current access information for the rh.
140            _target - (Locable) Reference to an object which is the destination
141                of the operations needed to carry out the rh. If set it must
142                provide (through the standard Locable interface) the methods
143                to get the url parameters in order to reproduce the access to
144                the rh.
145            _reqParams - (dict) Dictionary containing the received HTTP
146                 parameters (independently of the method) transformed into
147                 python data types. The key is the parameter name while the
148                 value should be the received paramter value (or values).
149    """
150    _currentRH = None
151    _tohttps = False
152
153    def __init__( self, req ):
154        """Constructor. Initialises the rh setting up basic attributes so it is
155            able to process the request.
156
157            Parameters:
158                req - (mod_python.Request) mod_python request received for the
159                    current rh.
160        """
161        if req == None:
162            raise Exception("Request object not initialised")
163        self._req = req
164        self._requestStarted = False
165        self._websession = None
166        self._aw = AccessWrapper()  #Fill in the aw instance with the current information
167        self._target = None
168        self._reqParams = {}
169        self._startTime = None
170        self._endTime = None
171        self._tempFilesToDelete = []
172        self._doProcess = True  #Flag which indicates whether the RH process
173                                #   must be carried out; this is useful for
174                                #   the checkProtection methods when they
175                                #   detect that an inmediate redirection is
176                                #   needed
177        RH._currentRH = self
178
179    # Methods =============================================================
180
181    def getHostIP(self):
182        import socket
183
184        host = str(self._req.get_remote_host(apache.REMOTE_NOLOOKUP))
185
186        try:
187            hostIP = socket.gethostbyname(host)
188            minfo = info.HelperMaKaCInfo.getMaKaCInfoInstance()
189            if minfo.useProxy():
190                # if we're behind a proxy, use X-Forwarded-For
191                xff = self._req.headers_in.get("X-Forwarded-For",hostIP).split(", ")[-1]
192                return socket.gethostbyname(xff)
193            else:
194                return hostIP
195        except socket.gaierror, e:
196            # in case host resolution fails
197            raise HostnameResolveError("Error resolving host '%s' : %s" % (host, e))
198
199
200    def getTarget( self ):
201        return self._target
202
203    def _setSession( self ):
204        """Sets up a reference to the corresponding web session. It uses the
205            session manager to retrieve the session corresponding to the
206            received request and makes sure it is a valid one. In case of having
207            an invalid session it reset client settings and creates a new one.
208       """
209        if not self._websession:
210            sm = session.getSessionManager()
211            try:
212                self._websession = sm.get_session( self._req )
213            except session.SessionError, e:
214                sm.revoke_session_cookie( self._req )
215                self._websession = sm.get_session( self._req )
216            sm.maintain_session( self._req, self._websession )
217
218    def _getSession( self ):
219        """Returns the web session associated to the received mod_python
220            request.
221        """
222        if not self._websession:
223            self._setSession()
224        return self._websession
225
226    def _setSessionUser( self ):
227        """
228        """
229        self._aw.setUser( self._getSession().getUser() )
230
231    def _getRequestParams( self ):
232        return self._reqParams
233
234    def getRequestParams( self ):
235        return self._getRequestParams()
236
237    def getRequestHTTPHeaders( self ):
238        return self._req.headers_in
239
240    def _disableCaching(self):
241        """
242        Disables caching, i.e. for materials
243        """
244
245        # IE doesn't seem to like 'no-cache' Cache-Control headers...
246        if (re.match(r'.*MSIE.*', self._req.headers_in.get("User-Agent",""))):
247            # actually, the only way to safely disable caching seems to be this one
248            self._req.headers_out["Cache-Control"] = "private"
249            self._req.headers_out["Expires"] = "-1"
250        else:
251            self._req.headers_out["Cache-Control"] = "no-store, no-cache, must-revalidate"
252            self._req.headers_out["Pragma"] = "no-cache"
253
254    def _redirect( self, targetURL, noCache=False ):
255        """Utility for redirecting the client web browser to the specified
256            URL.
257            Params:
258                newURL - Target URL of the redirection
259        """
260        #check if there is no \r\n character to avoid http header injection
261
262        if str(targetURL):
263            if "\r" in str(targetURL) or "\n" in str(targetURL):
264                raise MaKaCError(_("http header CRLF injection detected"))
265        self._req.headers_out["Location"] = str(targetURL)
266
267        if noCache:
268            self._disableCaching()
269        try:
270            self._req.status = apache.HTTP_SEE_OTHER
271        except NameError:
272            pass
273
274    def _checkHttpsRedirect(self):
275        if self._tohttps and not self._req.is_https():
276            current_url = self._req.construct_url(self._req.unparsed_uri)
277            self._redirect(urlHandlers.setSSLPort(current_url.replace("http://", "https://")))
278            return True
279        else:
280            return False
281
282    def _normaliseListParam( self, param ):
283        if not isinstance(param, list):
284                return [ param ]
285        return param
286
287    def _processError( self, ex ):
288        """
289        """
290        raise ex
291
292    def _checkParams( self, params ):
293        """
294        """
295        pass
296
297    def _process( self ):
298        """
299        """
300        pass
301
302    def _processGeneralError(self,e):
303        """Treats general errors occured during the process of a RH.
304        """
305
306        Logger.get('requestHandler').info('Request %s finished with: "%s"' % (id(self._req), e))
307
308        p=errors.WPGenericError(self)
309        return p.display()
310
311
312    def _getTruncatedParams(self):
313        """ Truncates params, so that file objects do not show up in the logs """
314
315        params = {}
316
317        for key,value in self._reqParams.iteritems():
318            if isinstance(value, Field):
319                params[key] = "<FILE>"
320            elif type(value) == str:
321                params[key] = truncate(value, 1024)
322            else:
323                params[key] = value
324
325        return params
326
327    def _processUnexpectedError(self,e):
328        """Unexpected errors
329        """
330
331        Logger.get('requestHandler').exception('Request %s failed: "%s"\n\nurl: %s\n\nparameters: %s\n\n' % (id(self._req), e,self.getRequestURL(), self._getTruncatedParams()))
332        p=errors.WPUnexpectedError(self)
333        return p.display()
334
335    def _processHostnameResolveError(self,e):
336        """Unexpected errors
337        """
338
339        Logger.get('requestHandler').exception('Request %s failed: "%s"\n\nurl: %s\n\nparameters: %s\n\n' % (id(self._req), e,self.getRequestURL(), self._getTruncatedParams()))
340        p=errors.WPHostnameResolveError(self)
341        return p.display()
342
343
344    def _processAccessError(self,e):
345        """Treats access errors occured during the process of a RH.
346        """
347        Logger.get('requestHandler').info('Request %s finished with AccessError: "%s"' % (id(self._req), e))
348
349        p=errors.WPAccessError(self)
350        return p.display()
351
352    def _processModificationError(self,e):
353        """Treats modification errors occured during the process of a RH.
354        """
355
356        Logger.get('requestHandler').info('Request %s finished with ModificationError: "%s"' % (id(self._req), e))
357
358        p=errors.WPModificationError(self)
359        return p.display()
360
361    def _processConferenceClosedError(self,e):
362        """Treats access to modification pages for conferences when they are closed.
363        """
364        p = WPConferenceModificationClosed( self, e._conf )
365        return p.display()
366
367    def _processTimingError(self,e):
368        """Treats timing errors occured during the process of a RH.
369        """
370
371        Logger.get('requestHandler').info('Request %s finished with TimingError: "%s"' % (id(self._req), e))
372
373        p=errors.WPTimingError(self,e)
374        return p.display()
375
376    def _processNoReportError(self,e):
377        """Process errors without reporting
378        """
379
380        Logger.get('requestHandler').info('Request %s finished with NoReportError: "%s"' % (id(self._req), e))
381
382        p=errors.WPNoReportError(self,e)
383        return p.display()
384
385    def _processParentTimingError(self,e):
386        """Treats timing errors occured during the process of a RH.
387        """
388
389        Logger.get('requestHandler').info('Request %s finished with ParentTimingError: "%s"' % (id(self._req), e))
390
391        p=errors.WPParentTimingError(self,e)
392        return p.display()
393
394    def _processEntryTimingError(self,e):
395        """Treats timing errors occured during the process of a RH.
396        """
397
398        Logger.get('requestHandler').info('Request %s finished with EntryTimingError: "%s"' % (id(self._req), e))
399
400        p=errors.WPEntryTimingError(self,e)
401        return p.display()
402
403    def _processFormValuesError(self,e):
404        """Treats timing errors occured during the process of a RH.
405        """
406
407        Logger.get('requestHandler').info('Request %s finished with FormValuesError: "%s"' % (id(self._req), e))
408
409        p=errors.WPFormValuesError(self,e)
410        return p.display()
411
412    def _processHtmlScriptError(self, e):
413
414        Logger.get('requestHandler').info('Request %s finished with ProcessHtmlScriptError: "%s"' % (id(self._req), e))
415
416        p=errors.WPHtmlScriptError(self, escape(str(e)))
417        return p.display()
418
419    def _processRestrictedHTML(self, e):
420
421        Logger.get('requestHandler').info('Request %s finished with ProcessRestrictedHTMLError: "%s"' % (id(self._req), e))
422
423        p=errors.WPRestrictedHTML(self, escape(str(e)))
424        return p.display()
425
426    def process( self, params ):
427        """
428        """
429
430        profile = Config.getInstance().getProfile()
431        proffilename = ""
432        res = ""
433        retry = 10
434        textLog = []
435        self._startTime = datetime.now()
436
437        # create the context
438        ContextManager.create()
439
440        #redirect to https if necessary
441        if self._checkHttpsRedirect():
442            return res
443
444        DBMgr.getInstance().startRequest()
445        self._startRequestSpecific2RH()     # I.e. implemented by Room Booking request handlers
446        textLog.append("%s : Database request started"%(datetime.now() - self._startTime))
447        Logger.get('requestHandler').info('[pid=%s] Request %s started (%s)' % (os.getpid(),id(self._req), self._req.unparsed_uri))
448        try:
449            while retry>0:
450                try:
451                    Logger.get('requestHandler').info('\t[pid=%s] from host %s' % (os.getpid(), self.getHostIP()))
452                    try:
453                        # clear the fossile cache at the start of each request
454                        fossilize.clearCache()
455
456                        DBMgr.getInstance().sync()
457                        # keep a link to the web session in the access wrapper
458                        # this is used for checking access/modification key existence
459                        # in the user session
460                        self._aw.setIP( self.getHostIP() )
461                        self._aw.setSession(self._getSession())
462                        #raise(str(dir(self._websession)))
463                        self._setSessionUser()
464                        self._setLang()
465
466                        if self._getUser():
467                            Logger.get('requestHandler').debug('Request %s identified with user %s (%s)' % (id(self._req), self._getUser().getFullName(), self._getUser().getId()))
468
469                        #if self._getUser() != None and self._getUser().getId() == "893":
470                        #    profile = True
471                        self._reqParams = copy.copy( params )
472                        self._checkParams( self._reqParams )
473                        self._checkProtection()
474                        security.Sanitization.sanitizationCheck(self._target,
475                                               self._reqParams,
476                                               self._aw)
477                        if self._doProcess:
478                            if profile:
479                                import profile, pstats
480                                proffilename = os.path.join(Config.getInstance().getTempDir(), "stone%s.prof" % str(random.random()))
481                                result = [None]
482                                profile.runctx("result[0] = self._process()", globals(), locals(), proffilename)
483                                res = result[0]
484                            else:
485                                res = self._process()
486                        self._endRequestSpecific2RH( True ) # I.e. implemented by Room Booking request handlers
487
488                        DBMgr.getInstance().endRequest( True )
489                        Logger.get('requestHandler').info('Request %s successful' % (id(self._req)))
490
491                        #request succesfull, now, doing tas that must be done only once
492                        try:
493                            self._sendEmails()
494                            self._deleteTempFiles()
495                        except:
496                            pass
497                        break
498                    except MaKaCError, e:
499                        #DBMgr.getInstance().endRequest(False)
500                        res = self._processError(e)
501                except (ConflictError, POSKeyError):
502                    import traceback
503                    Logger.get('requestHandler').debug('Conflict in Database! (Request %s)\n%s' % (id(self._req), traceback.format_exc()))
504                    self._abortSpecific2RH()
505                    DBMgr.getInstance().abort()
506                    retry -= 1
507                    continue
508                except ClientDisconnected:
509                    Logger.get('requestHandler').debug('Client Disconnected! (Request %s)' % id(self._req) )
510                    self._abortSpecific2RH()
511                    DBMgr.getInstance().abort()
512                    retry -= 1
513                    time.sleep(10-retry)
514                    continue
515        except AccessError, e:
516            #Access error treatment
517            res = self._processAccessError( e )
518            self._endRequestSpecific2RH( False )
519            DBMgr.getInstance().endRequest(False)
520        except HostnameResolveError, e:
521            res = self._processHostnameResolveError( e )
522            self._endRequestSpecific2RH( False )
523            DBMgr.getInstance().endRequest(False)
524        except ModificationError, e:
525            #Modification error treatment
526            res = self._processModificationError( e )
527            self._endRequestSpecific2RH( False )
528            DBMgr.getInstance().endRequest(False)
529        except ParentTimingError, e:
530            #Modification error treatment
531            res = self._processParentTimingError( e )
532            self._endRequestSpecific2RH( False )
533            DBMgr.getInstance().endRequest(False)
534        except EntryTimingError, e:
535            #Modification error treatment
536            res = self._processEntryTimingError( e )
537            self._endRequestSpecific2RH( False )
538            DBMgr.getInstance().endRequest(False)
539        except TimingError, e:
540            #Modification error treatment
541            res = self._processTimingError( e )
542            self._endRequestSpecific2RH( False )
543            DBMgr.getInstance().endRequest(False)
544        except FormValuesError, e:
545            #Error filling the values of a form
546            res = self._processFormValuesError( e )
547            self._endRequestSpecific2RH( False )
548            DBMgr.getInstance().endRequest(False)
549        except ConferenceClosedError, e:
550            #Modification error treatment
551            res = self._processConferenceClosedError( e )
552            self._endRequestSpecific2RH( False )
553            DBMgr.getInstance().endRequest(False)
554        except NoReportError, e:
555            #Error filling the values of a form
556            res = self._processNoReportError( e )
557            DBMgr.getInstance().endRequest(False)
558        except HtmlScriptError,e:
559            res = self._processHtmlScriptError(e)
560            DBMgr.getInstance().endRequest(False)
561        except HtmlForbiddenTag,e:
562            res = self._processRestrictedHTML(e)
563            DBMgr.getInstance().endRequest(False)
564        except MaKaCError, e:
565            res = self._processGeneralError( e )
566            DBMgr.getInstance().endRequest(False)
567        except ValueError, e:
568            res = self._processGeneralError( e )
569            DBMgr.getInstance().endRequest(False)
570        except Exception, e: #Generic error treatment
571            res = self._processUnexpectedError( e )
572            #DBMgr.getInstance().endRequest(False)
573            #self._endRequestSpecific2RH( False )
574
575            #cancels any redirection
576            try:
577                del self._req.headers_out["Location"]
578            except AttributeError:
579                pass
580            try:
581                self._req.status=apache.HTTP_INTERNAL_SERVER_ERROR
582            except NameError:
583                pass
584
585
586
587        #if we have an https request, we replace the links to Indico images by https ones.
588        if self._req.is_https() and self._tohttps and res is not None:
589            imagesBaseURL = Config.getInstance().getImagesBaseURL()
590            imagesBaseSecureURL = urlHandlers.setSSLPort(Config.getInstance().getImagesBaseSecureURL())
591            res = res.replace(imagesBaseURL, imagesBaseSecureURL)
592            res = res.replace(escapeHTMLForJS(imagesBaseURL), escapeHTMLForJS(imagesBaseSecureURL))
593
594        # destroy the context
595        ContextManager.destroy()
596
597        totalTime = (datetime.now() - self._startTime)
598        textLog.append("%s : Request ended"%totalTime)
599
600        # log request timing
601        if profile and totalTime > timedelta(0, 1) and os.path.isfile(proffilename):
602            rep = Config.getInstance().getTempDir()
603            stats = pstats.Stats(proffilename)
604            stats.strip_dirs()
605            stats.sort_stats('cumulative', 'time', 'calls')
606            stats.dump_stats(os.path.join(rep, "IndicoRequestProfile.log"))
607            output = StringIO.StringIO()
608            sys.stdout = output
609            stats.print_stats(100)
610            sys.stdout = sys.__stdout__
611            s = output.getvalue()
612            f = file(os.path.join(rep, "IndicoRequest.log"), 'a+')
613            f.write("--------------------------------\n")
614            f.write("URL     : " + self._req.construct_url(self._req.unparsed_uri) + "\n")
615            f.write("%s : start request\n"%self._startTime)
616            f.write("params:%s"%params)
617            f.write("\n".join(textLog))
618            f.write("\n")
619            f.write("retried : %d\n"%(10-retry))
620            f.write(s)
621            f.write("--------------------------------\n\n")
622            f.close()
623        if profile and proffilename != "" and os.path.exists(proffilename):
624            os.remove(proffilename)
625
626        if res == "" or res == None:
627            return "[done]"
628
629        return res
630
631    def _sendEmails( self ):
632        if hasattr( self, "_emailsToBeSent" ):
633            for email in self._emailsToBeSent:
634                GenericMailer.send(GenericNotification(email))
635
636    def _deleteTempFiles( self ):
637        if len(self._tempFilesToDelete) > 0:
638            for file in self._tempFilesToDelete:
639                os.remove(file)
640
641    def getRequestURL( self ):
642        proc = "http://"
643        try:
644            if self._req.is_https():
645                proc = "https://"
646        except:
647            pass
648
649        port = ""
650        if self._req.parsed_uri[apache.URI_PORT]:
651            port = ":" + str( self._req.parsed_uri[apache.URI_PORT] )
652        return "%s%s%s%s"%(proc, self._req.hostname, port, self._req.unparsed_uri)
653
654    def _startRequestSpecific2RH( self ):
655        """
656        Works like DBMgr.getInstance().startRequest() but is specific to
657        request handler. It is used to connect to other database only
658        in choosen request handlers.
659
660        I.e. all Room Booking request handlers override this
661        method to connect to Room Booking backend.
662        """
663        pass
664
665    def _endRequestSpecific2RH( self, commit ):
666        """
667        Works like DBMgr.getInstance().endRequest() but is specific to
668        request handler. It is used to disconnect from other database only
669        in choosen request handlers.
670
671        I.e. all Room Booking request handlers override this
672        method to disconnect from Room Booking backend.
673        """
674        pass
675
676    def _syncSpecific2RH( self ):
677        """
678        Works like DBMgr.getInstance().sync() but is specific to
679        request handler. It is used to connect to other database only
680        in choosen request handlers.
681
682        I.e. all Room Booking request handlers override this
683        method to sync backend.
684        """
685        pass
686
687    def _abortSpecific2RH( self ):
688        """
689        Works like DBMgr.getInstance().abort() but is specific to
690        request handler. It is used to abort transactions of other database
691        only in choosen request handlers.
692
693        I.e. all Room Booking request handlers override this method.
694        """
695        pass
696
697    # Properties =============================================================
698
699    requestURL = property( getRequestURL )
700    relativeURL = None
701
702
703from MaKaC.rb_location import CrossLocationDB
704import MaKaC.common.info as info
705
706class RoomBookingDBMixin:     # It's _not_ RH
707    """
708    Goal:
709    Only _some_ Request Handlers should connect to
710    room booking database.
711
712    Mix in this class into all Request Handlers,
713    which must use Room Booking backend.
714
715    Usage:
716
717    class RHExample( RoomBookingDBMixin, RHProtected ):
718        pass
719
720    NOTE: it is important to put RoomBookingDBMixin as first
721    base class.
722    """
723
724    def _startRequestSpecific2RH( self ):
725        minfo = info.HelperMaKaCInfo.getMaKaCInfoInstance()
726        if minfo.getRoomBookingModuleActive():
727            CrossLocationDB.connect()
728
729    def _endRequestSpecific2RH( self, commit = True ):
730        minfo = info.HelperMaKaCInfo.getMaKaCInfoInstance()
731        if minfo.getRoomBookingModuleActive():
732            if commit: CrossLocationDB.commit()
733            else: CrossLocationDB.rollback()
734            CrossLocationDB.disconnect()
735
736    def _syncSpecific2RH( self ):
737        minfo = info.HelperMaKaCInfo.getMaKaCInfoInstance()
738        if minfo.getRoomBookingModuleActive():
739            CrossLocationDB.sync()
740
741    def _abortSpecific2RH( self ):
742        minfo = info.HelperMaKaCInfo.getMaKaCInfoInstance()
743        if minfo.getRoomBookingModuleActive():
744            CrossLocationDB.rollback()
745
746
747class RHProtected( RH ):
748
749    def _getLoginURL( self ):
750        #url = self.getCurrentURL()
751        url = self.getRequestURL()
752        if url == "":
753            url = urlHandlers.UHWelcome.getURL()
754        return urlHandlers.UHSignIn.getURL( url )
755
756    def _checkSessionUser( self ):
757        """
758        """
759
760        if self._getUser() == None:
761            self._redirect( self._getLoginURL() )
762            self._doProcess = False
763
764    def _checkProtection( self ):
765        self._checkSessionUser()
766
767
768class RHRoomBookingProtected( RHProtected ):
769
770    def _checkSessionUser( self ):
771        user = self._getUser()
772        if user == None:
773            self._redirect( self._getLoginURL() )
774            self._doProcess = False
775        else:
776            try:
777                if PluginsHolder().getPluginType("RoomBooking").isActive():
778                    if not AdminList.getInstance().isAdmin(user) and PluginsHolder().getPluginType("RoomBooking").getOption("AuthorisedUsersGroups").getValue() != []:
779                        authenticatedUser = False
780                        for entity in PluginsHolder().getPluginType("RoomBooking").getOption("AuthorisedUsersGroups").getValue():
781                            if isinstance(entity, Group) and entity.containsUser(user) or \
782                               isinstance(entity, Avatar) and entity == user:
783                                    authenticatedUser = True
784                                    break
785                        if not authenticatedUser:
786                            raise AccessError()
787            except KeyError:
788                pass
789
790class RHDisplayBaseProtected( RHProtected ):
791
792    def _checkProtection( self ):
793
794        if not self._target.canAccess( self.getAW() ):
795            from MaKaC.conference import Link, LocalFile, Category
796            if isinstance(self._target,Link) or isinstance(self._target,LocalFile):
797                target = self._target.getOwner()
798            else:
799                target = self._target
800            if not isinstance(self._target, Category):
801                if target.getAccessKey() != "" or target.getConference() and target.getConference().getAccessKey() != "":
802                    raise AccessError()
803            if self._getUser() == None:
804                self._checkSessionUser()
805            else:
806                raise AccessError()
807
808
809class RHModificationBaseProtected( RHProtected ):
810
811    def _checkProtection( self ):
812        if not self._target.canModify( self.getAW() ):
813            if self._target.getModifKey() != "":
814                raise ModificationError()
815            if self._getUser() == None:
816                self._checkSessionUser()
817            else:
818                raise ModificationError()
819        if hasattr(self._target, "getConference"):
820            if self._target.getConference().isClosed():
821                raise ConferenceClosedError(self._target.getConference())
822
Note: See TracBrowser for help on using the repository browser.