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

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