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 def __init__(self, authenticator, use_redirect=1, urlencoding=None, encoding=None): 32 33 """ 34 Initialise the resource with an 'authenticator'. 35 36 If the optional 'use_redirect' flag is set to 0, a confirmation screen 37 is given instead of redirecting the user back to the original 38 application. 39 40 The optional 'urlencoding' parameter allows a special encoding to be 41 used in producing the redirection path. 42 43 The optional 'encoding' parameter allows a special encoding to be used 44 in producing the login pages. 45 46 To change the pages employed by this resource, either redefine the 47 'login_page' and 'success_page' attributes in instances of this class or 48 a subclass, or override the 'show_login' and 'show_success' methods. 49 """ 50 51 self.authenticator = authenticator 52 self.use_redirect = use_redirect 53 self.urlencoding = urlencoding 54 self.encoding = encoding 55 56 def respond(self, trans): 57 58 "Respond using the transaction 'trans'." 59 60 # Check for a submitted login form. 61 62 fields_body = trans.get_fields_from_body(self.encoding) 63 64 if fields_body.has_key("login"): 65 if self.authenticator.authenticate(trans, fields_body.get("username", [None])[0], fields_body.get("password", [None])[0]): 66 app = fields_body.get("app", [""])[0] 67 68 self._redirect(trans, app) 69 # The above method does not return. 70 71 # Otherwise, show the login form. 72 73 fields_path = trans.get_fields_from_path(self.urlencoding) 74 app = fields_path.get("app", [""])[0] 75 76 self.show_login(trans, app) 77 78 def _redirect(self, trans, app): 79 80 """ 81 Redirect the client using 'trans' and the given 'app' details. 82 """ 83 84 # Show the success page anyway. 85 86 self.show_success(trans, app) 87 if self.use_redirect: 88 trans.redirect(app) 89 else: 90 raise WebStack.Generic.EndOfResponse 91 92 def show_login(self, trans, app): 93 94 """ 95 Writes a login screen using the transaction 'trans', including details 96 of the 'app' which the client was attempting to access. 97 """ 98 99 trans.set_content_type(WebStack.Generic.ContentType("text/html", self.encoding)) 100 out = trans.get_response_stream() 101 out.write(self.login_page % app) 102 103 def show_success(self, trans, app): 104 105 """ 106 Writes a success screen using the transaction 'trans', including details 107 of the 'app' which the client was attempting to access. 108 """ 109 110 trans.set_content_type(WebStack.Generic.ContentType("text/html", self.encoding)) 111 out = trans.get_response_stream() 112 out.write(self.success_page % (app, app)) 113 114 login_page = """ 115 <html> 116 <head> 117 <title>Login</title> 118 </head> 119 <body> 120 <h1>Login</h1> 121 <form method="POST"> 122 <p>Username: <input name="username" type="text" size="12"/></p> 123 <p>Password: <input name="password" type="password" size="12"/></p> 124 <p><input name="login" type="submit" value="Login"/></p> 125 <input name="app" type="hidden" value="%s"/> 126 </form> 127 </body> 128 </html> 129 """ 130 131 success_page = """ 132 <html> 133 <head> 134 <title>Login Example</title> 135 </head> 136 <body> 137 <h1>Login Successful</h1> 138 <p>Please proceed to the application: <a href="%s">%s</a></p> 139 </body> 140 </html> 141 """ 142 143 # vim: tabstop=4 expandtab shiftwidth=4