Changeset 4104


Ignore:
Timestamp:
05/08/08 16:02:25 (11 years ago)
Author:
pjkersha
Message:

Begun work abstracting out rendering to enable custom Kid templating.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/openid_provider.py

    r4100 r4104  
    5353                 charset=None, 
    5454                 trace=True,#False, 
     55                 renderingClass=None, 
    5556                 **kw): 
    5657        invalidKw=[k for k in kw if k not in OpenIDProviderMiddleware.defPaths] 
     
    7677        self._trace = trace 
    7778         
     79        # Pages can be customised by setting external rendering interface 
     80        # class 
     81        if renderingClass is None: 
     82            renderingClass = RenderingInterface 
     83             
     84        elif not issubclass(renderingClass, RenderingInterface): 
     85            raise OpenIDProviderMiddlewareError("Rendering interface " 
     86                                                "class %r is not a %r " 
     87                                                "derived type" % \ 
     88                                                (renderingClass,  
     89                                                 RenderingInterface)) 
     90 
     91        try: 
     92            self._renderer = RenderingInterface(self.base_url, self.paths) 
     93        except Exception, e: 
     94            log.error("Error instantiating rendering interface...") 
     95            raise 
     96             
    7897        self.user = None 
    7998        self.app = app 
     
    134153    def do_id(self, environ, start_response): 
    135154        '''Handle ID request''' 
    136          
    137         link_tag = '<link rel="openid.server" href="%s%s">' % \ 
    138               (self.base_url, self.paths['path_openidserver']) 
    139         yadis_loc_tag = '<meta http-equiv="x-xrds-location" content="%s">'%\ 
    140             (self.base_url+self.paths['path_yadis']+'/'+self.path[4:]) 
    141         disco_tags = link_tag + yadis_loc_tag 
    142         ident = self.base_url + self.path 
    143  
    144         approved_trust_roots = [] 
    145         for (aident, trust_root) in self.approved.keys(): 
    146             if aident == ident: 
    147                 trs = '<li><tt>%s</tt></li>\n' % cgi.escape(trust_root) 
    148                 approved_trust_roots.append(trs) 
    149  
    150         if approved_trust_roots: 
    151             prepend = '<p>Approved trust roots:</p>\n<ul>\n' 
    152             approved_trust_roots.insert(0, prepend) 
    153             approved_trust_roots.append('</ul>\n') 
    154             msg = ''.join(approved_trust_roots) 
    155         else: 
    156             msg = '' 
    157  
    158         return self._showPage(200, 'An Identity Page',  
    159                              head_extras=disco_tags,  
    160                              msg='''\ 
    161                             <p>This is an identity page for %s.</p> 
    162                             %s 
    163                             ''' % (ident, msg)) 
     155        response = self.renderIdentityPage() 
     156 
     157        start_response("200 OK", [('Content-length', str(len(response)))]) 
     158        return response 
    164159 
    165160    tmplYadis = """\ 
     
    205200 
    206201        try: 
    207             request = self.oidserver.decodeRequest(self.query) 
     202            oidRequest = self.oidserver.decodeRequest(self.query) 
    208203        except server.ProtocolError, why: 
    209             return self._displayResponse(why) 
    210  
    211         if request is None: 
    212             # Display text indicating that this is an endpoint. 
    213             return self._showAboutPage() 
    214  
    215         # Check mode is one of "checkid_immediate", "checkid_setup" 
    216         if request.mode in server.BROWSER_REQUEST_MODES: 
    217             return self._handleCheckIDRequest(request) 
    218         else: 
    219             response = self.oidserver.handleRequest(request) 
    220             return self._displayResponse(response) 
     204            response = self._displayResponse(why) 
     205        else: 
     206            if oidRequest is None: 
     207                # Display text indicating that this is an endpoint. 
     208                response = self._showAboutPage() 
     209     
     210            # Check mode is one of "checkid_immediate", "checkid_setup" 
     211            if oidRequest.mode in server.BROWSER_REQUEST_MODES: 
     212                response = self._handleCheckIDRequest(oidRequest) 
     213            else: 
     214                oidResponse = self.oidserver.handleRequest(oidRequest) 
     215                response = self._displayResponse(oidResponse) 
     216             
     217        start_response("200 OK", [('Content-length', str(len(response)))]) 
     218        return response 
    221219             
    222220 
     
    254252 
    255253        else: 
    256             assert False, 'Expecting yes/no in allow post.  %r' % (self.query,) 
     254            raise OpenIDProviderMiddlewareError('Expecting yes/no in allow ' 
     255                                                'post.  %r' % self.query) 
    257256 
    258257        return self._displayResponse(response) 
     
    285284 
    286285    def do_login(self, environ, start_response): 
    287          
    288         success_to, fail_to = (self.paths['path_mainpage'],)*2 
    289          
    290         return self._showPage(200, 'Login Page', form='''\ 
    291         <h2>Login</h2> 
    292         <p>You may log in with any name. This server does not use 
    293         passwords because it is just a sample of how to use the OpenID 
    294         library.</p> 
    295         <form method="GET" action="%s"> 
    296           <input type="hidden" name="success_to" value="%s" /> 
    297           <input type="hidden" name="fail_to" value="%s" /> 
    298           <input type="text" name="user" value="" /> 
    299           <input type="submit" name="submit" value="Log In" /> 
    300           <input type="submit" name="cancel" value="Cancel" /> 
    301         </form> 
    302         ''' % (self.paths['path_loginsubmit'], success_to, fail_to)) 
     286        """Display Login form""" 
     287         
     288        response = self._renderer.renderLogin() 
     289        start_response('200 OK',  
     290                       [('Content-type', 'text/html'+self.charset), 
     291                        ('Content-length', str(len(response)))]) 
     292        return response 
    303293 
    304294 
    305295    def do_loginsubmit(self, environ, start_response): 
     296        """Handle user submission from login""" 
     297         
    306298        if 'submit' in self.query: 
    307299            if 'user' in self.query: 
     
    313305            return self._redirect(start_response, self.query['fail_to']) 
    314306        else: 
    315             assert 0, 'strange login %r' % (self.query,)    
     307            raise OpenIDProviderMiddlewareError('strange login %r'%self.query)    
    316308             
    317309 
    318310    def do_mainpage(self, environ, start_response): 
    319311 
    320         yadis_tag = '<meta http-equiv="x-xrds-location" content="%s">'%\ 
    321             (self.base_url + self.paths['path_serveryadis']) 
    322         if self.user: 
    323             openid_url = self.base_url + self.paths['path_id'] + '/' + \ 
    324                         self.user 
    325             user_message = """\ 
    326             <p>You are logged in as %s. Your OpenID identity URL is 
    327             <tt><a href=%s>%s</a></tt>. Enter that URL at an OpenID 
    328             consumer to test this server.</p> 
    329             """ % (self.user, quoteattr(openid_url), openid_url) 
    330         else: 
    331             user_message = """\ 
    332             <p>This server uses a cookie to remember who you are in 
    333             order to simulate a standard Web user experience. You are 
    334             not <a href='%s'>logged in</a>.</p>""" % self.paths['path_login'] 
    335  
    336         return self._showPage(200, 'Main Page', head_extras=yadis_tag, msg='''\ 
    337         <p>This is a simple OpenID server implemented using the <a 
    338         href="http://openid.schtuff.com/">Python OpenID 
    339         library</a>.</p> 
    340  
    341         %s 
    342  
    343         <p>To use this server with a consumer, the consumer must be 
    344         able to fetch HTTP pages from this web server. If this 
    345         computer is behind a firewall, you will not be able to use 
    346         OpenID consumers outside of the firewall with it.</p> 
    347  
    348         <p>The URL for this server is <a href=%s><tt>%s</tt></a>.</p> 
    349         ''' % (user_message, quoteattr(self.base_url), self.base_url)) 
     312        response = self.renderMainPage(self.paths['path_serveryadis']) 
     313        start_response('200 OK',  
     314                       [('Content-type', 'text/html'+self.charset), 
     315                        ('Content-length', str(len(response)))]) 
     316        return response 
    350317             
    351318                         
     
    607574            </form>''' % fdata 
    608575 
    609         return self._showPage(200, 'Approve OpenID request?',msg=msg,form=form) 
     576        return self._showPage('Approve OpenID request?', msg=msg, form=form) 
    610577 
    611578 
     
    636603        %s 
    637604        ''' % (ident, msg)) 
    638          
    639  
    640     def _showPage(self, response_code, title, 
    641                  head_extras='', msg=None, err=None, form=None): 
     605 
     606 
     607class RenderingInterface(object): 
     608    """Interface class for rendering of OpenID Provider pages.  Create a 
     609    derivative from this class to override the default look and feel and  
     610    behaviour of these pages.  Pass the new class name via the renderClass 
     611    keyword to OpenIDProviderMiddleware.__init__""" 
     612     
     613    def __init__(self, base_url, paths): 
     614        self.base_url = base_url 
     615        self.paths = paths 
     616        self.user = '' 
     617 
     618    def renderIdentityPage(self): 
     619        """Render the identity page.""" 
     620 
     621        link_tag = '<link rel="openid.server" href="%s%s">' % \ 
     622              (self.base_url, self.paths['path_openidserver']) 
     623               
     624        yadis_loc_tag = '<meta http-equiv="x-xrds-location" content="%s">'%\ 
     625            (self.base_url+self.paths['path_yadis']+'/'+self.path[4:]) 
     626             
     627        disco_tags = link_tag + yadis_loc_tag 
     628        ident = self.base_url + self.path 
     629 
     630        approved_trust_roots = [] 
     631        for (aident, trust_root) in self.approved.keys(): 
     632            if aident == ident: 
     633                trs = '<li><tt>%s</tt></li>\n' % cgi.escape(trust_root) 
     634                approved_trust_roots.append(trs) 
     635 
     636        if approved_trust_roots: 
     637            prepend = '<p>Approved trust roots:</p>\n<ul>\n' 
     638            approved_trust_roots.insert(0, prepend) 
     639            approved_trust_roots.append('</ul>\n') 
     640            msg = ''.join(approved_trust_roots) 
     641        else: 
     642            msg = '' 
     643 
     644        response = self._showPage('An Identity Page',  
     645                              head_extras=disco_tags,  
     646                              msg='''<p>This is an identity page for %s.</p> 
     647                                %s 
     648                                ''' % (ident, msg)) 
     649         
     650         
     651    def renderLogin(self): 
     652        """Render the login form.""" 
     653        success_to, fail_to = (self.paths['path_mainpage'],)*2 
     654         
     655        return self._showPage('Login Page', form='''\ 
     656            <h2>Login</h2> 
     657            <form method="GET" action="%s"> 
     658              <input type="hidden" name="success_to" value="%s" /> 
     659              <input type="hidden" name="fail_to" value="%s" /> 
     660              <input type="text" name="user" value="" /> 
     661              <input type="submit" name="submit" value="Log In" /> 
     662              <input type="submit" name="cancel" value="Cancel" /> 
     663            </form> 
     664            ''' % (self.paths['path_loginsubmit'], success_to, fail_to)) 
     665 
     666 
     667    def renderMainPage(self): 
     668        """Rendering the main page.""" 
     669         
     670        yadis_tag = '<meta http-equiv="x-xrds-location" content="%s">' % \ 
     671                    (self.base_url + self.paths['path_serveryadis']) 
     672             
     673        if self.user: 
     674            openid_url = self.base_url + self.paths['path_id'] + '/' + \ 
     675                        self.user 
     676            user_message = """\ 
     677            <p>You are logged in as %s. Your OpenID identity URL is 
     678            <tt><a href=%s>%s</a></tt>. Enter that URL at an OpenID 
     679            consumer to test this server.</p> 
     680            """ % (self.user, quoteattr(openid_url), openid_url) 
     681        else: 
     682            user_message = "<p>You are not <a href='%s'>logged in</a>.</p>" % \ 
     683                            self.paths['path_login'] 
     684 
     685        return self._showPage('Main Page', head_extras=yadis_tag, msg='''\ 
     686            <p>OpenID server</p> 
     687     
     688            %s 
     689     
     690            <p>The URL for this server is <a href=%s><tt>%s</tt></a>.</p> 
     691        ''' % (user_message, quoteattr(self.base_url), self.base_url)) 
     692         
     693 
     694    def _showPage(self, title, head_extras='', msg=None, err=None, form=None): 
    642695 
    643696        if self.user is None: 
     
    675728 
    676729        contents = { 
    677             'title': 'Python OpenID Server Example - ' + title, 
     730            'title': 'Python OpenID Server - ' + title, 
    678731            'head_extras': head_extras, 
    679732            'body': body, 
     
    746799      <tr> 
    747800        <td class="leftbanner"> 
    748           <h1><a href="/">Python OpenID Server Example</a></h1> 
     801          <h1><a href="/">Python OpenID Server</a></h1> 
    749802        </td> 
    750803        <td class="rightbanner"> 
     
    758811''' % contents 
    759812 
    760         self.start_response('%s %s' % (response_code,  
    761                                        httplib.responses[response_code]),  
    762                 [ 
    763                     ('Content-type', 'text/html'+self.charset), 
    764                     ('Content-length', str(len(response))) 
    765                 ] 
    766             ) 
    767         return [response] 
    768  
    769  
     813        return response 
     814         
     815            
    770816from authkit.authenticate import middleware, AuthKitConfigError, strip_base 
    771817from authkit.authenticate.multi import MultiHandler, status_checker 
Note: See TracChangeset for help on using the changeset viewer.