source: TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/authz/result_handler/genshi/genshi.py @ 6267

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/NDGSecurity/python/ndg_security_server/ndg/security/server/wsgi/authz/result_handler/genshi/genshi.py@6267
Revision 6267, 5.2 KB checked in by pjkersha, 10 years ago (diff)
Line 
1"""WSGI Policy Enforcement Point basic result handler module for a Genshi
2based implementation.  Access denied HTML response is rendered using the
3Genshi templating language.
4
5NERC DataGrid Project
6"""
7__author__ = "P J Kershaw"
8__date__ = "05/01/10"
9__copyright__ = "(C) 2010 Science and Technology Facilities Council"
10__contact__ = "Philip.Kershaw@stfc.ac.uk"
11__revision__ = "$Id: $"
12__license__ = "BSD - see LICENSE file in top-level directory"
13from string import Template
14from genshi.template import TemplateLoader
15
16from httplib import UNAUTHORIZED, FORBIDDEN
17
18from ndg.security.server.wsgi import NDGSecurityMiddlewareBase
19from ndg.security.server.wsgi.session import SessionMiddlewareBase
20
21
22class GenshiPEPResultHandlerMiddleware(SessionMiddlewareBase):
23    """Genshi based PEP result handler
24    """
25    PROPERTY_NAMES = (
26        'messageTemplate',
27        'templateName',
28        'templateRootDir'
29    )
30    __slots__ = PROPERTY_NAMES
31       
32    DEFAULT_TMPL_NAME = 'accessdenied.html'
33    DEFAULT_TMPL_DIR = path.join(path.dirname(__file__), 'templates')
34   
35    MSG_TMPL = (
36        "Access is forbidden for this resource:<br/><br/>"
37        "$pdpResponseMsg<br/><br/>"
38        "Please check with your site administrator that you have the required "
39        "access privileges."
40    )
41   
42    def __init__(self, app, global_conf, prefix='', **app_conf):
43        '''
44        @type app: callable following WSGI interface
45        @param app: next middleware application in the chain     
46        @type global_conf: dict       
47        @param global_conf: PasteDeploy global configuration dictionary
48        @type prefix: basestring
49        @param prefix: prefix for configuration items
50        @type app_conf: dict       
51        @param app_conf: PasteDeploy application specific configuration
52        dictionary
53        '''
54        super(GenshiPEPResultHandlerMiddleware, self).__init__(app,
55                                                               global_conf,
56                                                               prefix=prefix,
57                                                               **app_conf) 
58               
59        # Initialise attributes
60        for i in GenshiRendering.PROPERTY_NAMES:
61            setattr(self, i, '')
62         
63        # Update from keywords   
64        for i in app_conf:
65            setattr(self, i, app_conf[i])
66
67        if not self.templateRootDir:
68            self.templateRootDir = \
69                            GenshiPEPResultHandlerMiddleware.DEFAULT_TMPL_DIR
70         
71        if not self.messageTemplate:
72            self.messageTemplate = GenshiPEPResultHandlerMiddleware.MSG_TMPL
73           
74        if not self.templateName:
75            self.templateName = \
76                GenshiPEPResultHandlerMiddleware.DEFAULT_TMPL_NAME
77           
78        self.__loader = TemplateLoader(self.templateRootDir, auto_reload=True)
79       
80    @NDGSecurityMiddlewareBase.initCall
81    def __call__(self, environ, start_response):
82       
83        if not self.isAuthenticated:
84            # sets 401 response to be trapped by authentication handler
85            log.warning("PEPResultHandlerMiddleware: user is not "
86                        "authenticated - setting HTTP 401 response")
87            return self._setErrorResponse(code=UNAUTHORIZED)
88        else:
89            # Get response message from PDP recorded by PEP
90            pepCtx = self.session.get(PEPFilter.PEPCTX_SESSION_KEYNAME, {})
91            pdpResponse = pepCtx.get(PEPFilter.PEPCTX_RESPONSE_SESSION_KEYNAME)
92            pdpResponseMsg = getattr(pdpResponse, 'message', '') or ''
93               
94            msg = Template(self.messageTemplate).substitute(
95                                                pdpResponseMsg=pdpResponseMsg)
96
97            response = self._render(xml=msg)
98            start_response(
99                GenshiPEPResultHandlerMiddleware.getStatusMessage(FORBIDDEN),
100                [('Content-type', 'text/html'),
101                 ('Content-Length', str(len(response)))])
102           
103            return response
104       
105    def __setattr__(self, name, value):
106        """Apply some generic type checking"""
107        if name in GenshiRendering.PROPERTY_NAMES:
108            if not isinstance(value, basestring):
109                raise TypeError('Expecting string type for %r attribute; got '
110                                '%r' % (name, type(value)))
111           
112        super(GenshiPEPResultHandlerMiddleware, self).__setattr__(name, value)
113                       
114    def _getLoader(self):
115        return self.__loader
116
117    def _setLoader(self, value):
118        if not isinstance(value, TemplateLoader):
119            raise TypeError('Expecting %r type for "loader"; got %r' % 
120                            (TemplateLoader, type(value)))
121        self.__loader = value
122
123    loader = property(_getLoader, _setLoader, 
124                      doc="Genshi TemplateLoader instance") 
125         
126    def _render(self, **kw):
127        '''Wrapper for Genshi template rendering
128        @type kw: dict
129        @param kw: keywords to pass to template
130        @rtype: string
131        @return: rendered template
132        '''       
133        tmpl = self.loader.load(self.templateName)
134        rendering = tmpl.generate(**kw).render('html', doctype='html')
135       
136        return rendering
Note: See TracBrowser for help on using the repository browser.