1 #!/usr/bin/env python 2 3 """ 4 Login resources for XSLForms applications. These resources use "root" attributes 5 on transaction objects, and therefore should be defined within the appropriate 6 resources in site maps. 7 8 Copyright (C) 2006, 2007 Paul Boddie <paul@boddie.org.uk> 9 10 This software is free software; you can redistribute it and/or 11 modify it under the terms of the GNU General Public License as 12 published by the Free Software Foundation; either version 2 of 13 the License, or (at your option) any later version. 14 15 This software is distributed in the hope that it will be useful, 16 but WITHOUT ANY WARRANTY; without even the implied warranty of 17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 GNU General Public License for more details. 19 20 You should have received a copy of the GNU General Public 21 License along with this library; see the file LICENCE.txt 22 If not, write to the Free Software Foundation, Inc., 23 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA 24 """ 25 26 from WebStack.Generic import ContentType, EndOfResponse 27 import XSLForms.Resources.WebResources 28 29 import WebStack.Resources.LoginRedirect # LoginRedirectResource 30 import WebStack.Resources.Login # get_target 31 32 class LoginResource(XSLForms.Resources.WebResources.XSLFormsResource): 33 34 """ 35 A login screen resource which should be modified or subclassed to define the 36 following attributes: 37 38 * resource_dir 39 * template_resources - including a "login" entry for the login screen 40 * document_resources - including a "translations" entry 41 42 The latter attribute is optional. 43 44 The login template must define a "login" action, and provide a document 45 structure where the login credentials can be found through this class's 46 'path_to_login_element' attribute (which can be overridden or modified). 47 Such a structure would be as follows for the default configuration: 48 49 <login username="..." password="..."/> 50 """ 51 52 path_to_login_element = "/login" 53 54 def __init__(self, authenticator): 55 56 """ 57 Initialise the resource with an 'authenticator'. 58 59 To get the root of the application, this resource needs an attribute on 60 the transaction called "root". 61 """ 62 63 self.authenticator = authenticator 64 65 def respond_to_form(self, trans, form): 66 67 """ 68 Respond to a request having the given transaction 'trans' and the given 69 'form' information. 70 """ 71 72 parameters = form.get_parameters() 73 documents = form.get_documents() 74 attributes = trans.get_attributes() 75 76 # Ensure the presence of a document. 77 78 if documents.has_key("login"): 79 login = documents["login"] 80 else: 81 login = form.new_instance("login") 82 83 # Test for login. 84 85 if parameters.has_key("login"): 86 logelem = login.xpath(self.path_to_login_element)[0] 87 username = logelem.getAttribute("username") 88 password = logelem.getAttribute("password") 89 90 if self.authenticator.authenticate(trans, username, password): 91 app, path, qs = WebStack.Resources.Login.get_target(trans) 92 trans.redirect(app + trans.encode_path(path) + qs) 93 else: 94 error = login.createElement("error") 95 logelem.appendChild(error) 96 error.setAttribute("message", "Username or password not valid") 97 98 # Start the response. 99 100 trans.set_content_type(ContentType("application/xhtml+xml")) 101 stylesheet_parameters = {} 102 references = {} 103 104 # Set up translations. 105 106 if self.document_resources.has_key("translations"): 107 translations_xml = self.prepare_document("translations") 108 109 try: 110 language = trans.get_content_languages()[0] 111 except IndexError: 112 language = "en" 113 114 stylesheet_parameters["locale"] = language 115 references["translations"] = translations_xml 116 117 # Complete the response. 118 119 trans_xsl = self.prepare_output("login") 120 stylesheet_parameters["root"] = attributes["root"] 121 self.send_output(trans, [trans_xsl], login, stylesheet_parameters, references=references) 122 123 class LoginRedirectResource(WebStack.Resources.LoginRedirect.LoginRedirectResource): 124 125 "A redirect resource which uses dynamic knowledge about the URL space." 126 127 def __init__(self, host, path_to_login, *args, **kw): 128 129 """ 130 Initialise the resource with the 'host', 'path_to_login' (the path from 131 the root of the application to the login screen), and other 132 LoginRedirectResource details. 133 134 To get the root of the application, this resource needs an attribute on 135 the transaction called "root". 136 137 Examples of 'path_to_login' with "root" attribute and result: 138 139 "login", "/" -> "/login" 140 "login", "/app/" -> "/app/login" 141 "app/login", "/" -> "/app/login" 142 """ 143 144 self.host = host 145 self.path_to_login = path_to_login 146 WebStack.Resources.LoginRedirect.LoginRedirectResource.__init__(self, *args, **kw) 147 148 def get_app_url(self, trans): 149 return self.host 150 151 def get_login_url(self, trans): 152 return self.host + trans.get_attributes()["root"] + self.path_to_login 153 154 # vim: tabstop=4 expandtab shiftwidth=4