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 references = {} 102 103 # Set up translations. 104 105 if self.document_resources.has_key("translations"): 106 translations_xml = self.prepare_document("translations") 107 108 try: 109 language = trans.get_content_languages()[0] 110 except IndexError: 111 language = "en" 112 113 stylesheet_parameters = {"locale" : language} 114 references["translations"] = translations_xml 115 116 # Complete the response. 117 118 trans_xsl = self.prepare_output("login") 119 stylesheet_parameters["root"] = attributes["root"] 120 self.send_output(trans, [trans_xsl], login, stylesheet_parameters, references=references) 121 122 class LoginRedirectResource(WebStack.Resources.LoginRedirect.LoginRedirectResource): 123 124 "A redirect resource which uses dynamic knowledge about the URL space." 125 126 def __init__(self, host, path_to_login, *args, **kw): 127 128 """ 129 Initialise the resource with the 'host', 'path_to_login' (the path from 130 the root of the application to the login screen), and other 131 LoginRedirectResource details. 132 133 To get the root of the application, this resource needs an attribute on 134 the transaction called "root". 135 136 Examples of 'path_to_login' with "root" attribute and result: 137 138 "login", "/" -> "/login" 139 "login", "/app/" -> "/app/login" 140 "app/login", "/" -> "/app/login" 141 """ 142 143 self.host = host 144 self.path_to_login = path_to_login 145 WebStack.Resources.LoginRedirect.LoginRedirectResource.__init__(self, *args, **kw) 146 147 def get_app_url(self, trans): 148 return self.host 149 150 def get_login_url(self, trans): 151 return self.host + trans.get_attributes()["root"] + path_to_login 152 153 # vim: tabstop=4 expandtab shiftwidth=4