1 #!/usr/bin/env python 2 3 """ 4 Login resources which redirect clients back to an application after a successful 5 login. 6 7 Copyright (C) 2004, 2005, 2006, 2007 Paul Boddie <paul@boddie.org.uk> 8 9 This library is free software; you can redistribute it and/or 10 modify it under the terms of the GNU Lesser General Public 11 License as published by the Free Software Foundation; either 12 version 2.1 of the License, or (at your option) any later version. 13 14 This library is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 17 Lesser General Public License for more details. 18 19 You should have received a copy of the GNU Lesser General Public 20 License along with this library; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 22 """ 23 24 import WebStack.Generic 25 from WebStack.Helpers.Auth import LoginAuthenticator 26 27 class LoginResource: 28 29 "A resource providing a login screen." 30 31 encoding = "utf-8" 32 33 def __init__(self, authenticator, use_redirect=1, urlencoding=None, encoding=None): 34 35 """ 36 Initialise the resource with an 'authenticator'. 37 38 If the optional 'use_redirect' flag is set to 0, a confirmation screen 39 is given instead of redirecting the user back to the original 40 application. 41 42 The optional 'urlencoding' parameter allows a special encoding to be 43 used in producing the redirection path. 44 45 The optional 'encoding' parameter allows a special encoding to be used 46 in producing the login pages. 47 48 To change the pages employed by this resource, either redefine the 49 'login_page' and 'success_page' attributes in instances of this class or 50 a subclass, or override the 'show_login' and 'show_success' methods. 51 """ 52 53 self.authenticator = authenticator 54 self.use_redirect = use_redirect 55 self.urlencoding = urlencoding 56 self.encoding = encoding or self.encoding 57 58 def respond(self, trans): 59 60 "Respond using the transaction 'trans'." 61 62 # Check for a submitted login form. 63 64 fields_body = trans.get_fields_from_body(self.encoding) 65 66 if fields_body.has_key("login"): 67 if self.authenticator.authenticate(trans, fields_body.get("username", [None])[0], fields_body.get("password", [None])[0]): 68 app = fields_body.get("app", [""])[0] 69 70 self._redirect(trans, app) 71 # The above method does not return. 72 73 # Otherwise, show the login form. 74 75 fields_path = trans.get_fields_from_path(self.urlencoding) 76 app = fields_path.get("app", [""])[0] 77 78 self.show_login(trans, app) 79 80 def _redirect(self, trans, app): 81 82 """ 83 Redirect the client using 'trans' and the given 'app' details. 84 """ 85 86 # Show the success page anyway. 87 88 self.show_success(trans, app) 89 if self.use_redirect: 90 trans.redirect(app) 91 else: 92 raise WebStack.Generic.EndOfResponse 93 94 def show_login(self, trans, app): 95 96 """ 97 Writes a login screen using the transaction 'trans', including details 98 of the 'app' which the client was attempting to access. 99 """ 100 101 trans.set_content_type(WebStack.Generic.ContentType("text/html", self.encoding)) 102 out = trans.get_response_stream() 103 out.write(self.login_page % app) 104 105 def show_success(self, trans, app): 106 107 """ 108 Writes a success screen using the transaction 'trans', including details 109 of the 'app' which the client was attempting to access. 110 """ 111 112 trans.set_content_type(WebStack.Generic.ContentType("text/html", self.encoding)) 113 out = trans.get_response_stream() 114 out.write(self.success_page % (app, app)) 115 116 login_page = """ 117 <html> 118 <head> 119 <title>Login</title> 120 </head> 121 <body> 122 <h1>Login</h1> 123 <form method="POST"> 124 <p>Username: <input name="username" type="text" size="12"/></p> 125 <p>Password: <input name="password" type="password" size="12"/></p> 126 <p><input name="login" type="submit" value="Login"/></p> 127 <input name="app" type="hidden" value="%s"/> 128 </form> 129 </body> 130 </html> 131 """ 132 133 success_page = """ 134 <html> 135 <head> 136 <title>Login Example</title> 137 </head> 138 <body> 139 <h1>Login Successful</h1> 140 <p>Please proceed to the application: <a href="%s">%s</a></p> 141 </body> 142 </html> 143 """ 144 145 # vim: tabstop=4 expandtab shiftwidth=4