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

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/__init__.py@7077
Revision 7077, 5.8 KB checked in by pjkersha, 10 years ago (diff)
  • Property svn:keywords set to Id
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"
13import logging
14log = logging.getLogger(__name__)
15
16from os import path
17from httplib import UNAUTHORIZED, FORBIDDEN
18from string import Template
19
20from paste.cascade import Cascade
21from paste.urlparser import StaticURLParser
22from genshi.template import TemplateLoader
23
24from ndg.security.server.wsgi.authz.result_handler import \
25    PEPResultHandlerMiddlewareBase
26
27
28class GenshiPEPResultHandlerMiddleware(PEPResultHandlerMiddlewareBase):
29    """Genshi based PEP result handler
30    """       
31    DEFAULT_TMPL_NAME = 'accessdenied.html'
32    DEFAULT_TMPL_DIR = path.join(path.dirname(__file__), 'templates')
33   
34    MSG_TMPL = (
35        "Access is forbidden for this resource:<br/><br/>"
36        "$pdpResponseMsg<br/><br/>"
37        "Please check with your site administrator that you have the required "
38        "access privileges."
39    )
40   
41    PROPERTY_DEFAULTS = {
42        'messageTemplate': MSG_TMPL,
43        'templateName': DEFAULT_TMPL_NAME,
44        'templateRootDir': DEFAULT_TMPL_DIR,
45        'baseURL': '',
46        'heading': '',
47        'title': '',
48        'leftLogo': '',
49        'leftAlt': '',
50        'leftLink': '',
51        'leftImage': '',
52        'footerText': 'Test deployment only',
53        'rightLink': '',
54        'rightImage': '',
55        'rightAlt': '',
56        'helpIcon': ''
57    }
58    __slots__ = PROPERTY_DEFAULTS
59   
60    def __init__(self, app, global_conf, prefix='', **app_conf):
61        '''
62        @type app: callable following WSGI interface
63        @param app: next middleware application in the chain     
64        @type global_conf: dict       
65        @param global_conf: PasteDeploy global configuration dictionary
66        @type prefix: basestring
67        @param prefix: prefix for configuration items
68        @type app_conf: dict       
69        @param app_conf: PasteDeploy application specific configuration
70        dictionary
71        '''
72        super(GenshiPEPResultHandlerMiddleware, self).__init__(app, {}) 
73               
74        # Initialise attributes
75        for k, v in GenshiPEPResultHandlerMiddleware.PROPERTY_DEFAULTS.items():
76            setattr(self, k, v)
77         
78        # Update from keywords   
79        for i in app_conf:
80            if prefix and i.startswith(prefix):
81                attrName = i.rsplit(prefix, 2)[-1]
82                setattr(self, attrName, app_conf[i])
83           
84        self.__loader = TemplateLoader(self.templateRootDir, auto_reload=True)
85
86    @PEPResultHandlerMiddlewareBase.initCall
87    def __call__(self, environ, start_response):
88        """Render access denied message or else if user is not authenticated,
89        set HTTP 401 response
90       
91        @type environ: dict
92        @param environ: WSGI environment variables dictionary
93        @type start_response: function
94        @param start_response: standard WSGI start response function
95        @rtype: iterable
96        @return: response
97        """ 
98        session = self.environ.get(self.sessionKey)
99        if not self.isAuthenticated:
100            # sets 401 response to be trapped by authentication handler
101            log.warning("GenshiPEPResultHandlerMiddleware: user is not "
102                        "authenticated - setting HTTP 401 response")
103            return self._setErrorResponse(code=UNAUTHORIZED)
104        else:
105            # Get response message from PDP recorded by PEP
106            cls = GenshiPEPResultHandlerMiddleware
107            pepCtx = session.get(cls.PEPCTX_SESSION_KEYNAME, {})
108            pdpResponse = pepCtx.get(cls.PEPCTX_RESPONSE_SESSION_KEYNAME)
109            pdpResponseMsg = getattr(pdpResponse, 'message', '') or ''
110               
111            msg = Template(self.messageTemplate).substitute(
112                                                pdpResponseMsg=pdpResponseMsg)
113
114            response = self._render(xml=msg)
115            start_response(cls.getStatusMessage(FORBIDDEN),
116                           [('Content-type', 'text/html'),
117                            ('Content-Length', str(len(response)))])
118           
119            return response
120       
121    def __setattr__(self, name, value):
122        """Apply some generic type checking"""
123        if name in GenshiPEPResultHandlerMiddleware.PROPERTY_DEFAULTS:
124            if not isinstance(value, basestring):
125                raise TypeError('Expecting string type for %r attribute; got '
126                                '%r' % (name, type(value)))
127           
128        super(GenshiPEPResultHandlerMiddleware, self).__setattr__(name, value)
129                       
130    def _getLoader(self):
131        return self.__loader
132
133    def _setLoader(self, value):
134        if not isinstance(value, TemplateLoader):
135            raise TypeError('Expecting %r type for "loader"; got %r' % 
136                            (TemplateLoader, type(value)))
137        self.__loader = value
138
139    loader = property(_getLoader, _setLoader, 
140                      doc="Genshi TemplateLoader instance") 
141         
142    def _render(self, c=None, **kw):
143        '''Wrapper for Genshi template rendering
144       
145        @type c: None/object
146        @param c: reference to object to pass into template - defaults to self
147        @type kw: dict
148        @param kw: keywords to pass to template
149        @rtype: string
150        @return: rendered template
151        '''   
152        if c is None:
153            kw['c'] = self 
154             
155        tmpl = self.loader.load(self.templateName)
156        rendering = tmpl.generate(**kw).render('html', doctype='html')
157       
158        return rendering
Note: See TracBrowser for help on using the repository browser.