thirdparty/google_appengine/google/appengine/tools/dev_appserver_login.py
changeset 109 620f9b141567
child 686 df109be0567c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/thirdparty/google_appengine/google/appengine/tools/dev_appserver_login.py	Tue Aug 26 21:49:54 2008 +0000
@@ -0,0 +1,293 @@
+#!/usr/bin/env python
+#
+# Copyright 2007 Google Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+"""Helper CGI for logins/logout in the development application server.
+
+This CGI has these parameters:
+
+  continue: URL to redirect to after a login or logout has completed.
+  email: Email address to set for the client.
+  admin: If 'True', the client should be logged in as an admin.
+  action: What action to take ('Login' or 'Logout').
+
+To view the current user information and a form for logging in and out,
+supply no parameters.
+"""
+
+
+import Cookie
+import cgi
+import os
+import sys
+import urllib
+
+
+CONTINUE_PARAM = 'continue'
+EMAIL_PARAM = 'email'
+ADMIN_PARAM = 'admin'
+ACTION_PARAM = 'action'
+
+LOGOUT_ACTION = 'Logout'
+LOGIN_ACTION = 'Login'
+
+LOGOUT_PARAM = 'action=%s' % LOGOUT_ACTION
+
+COOKIE_NAME = 'dev_appserver_login'
+
+
+def GetUserInfo(http_cookie, cookie_name=COOKIE_NAME):
+  """Get the requestor's user info from the HTTP cookie in the CGI environment.
+
+  Args:
+    http_cookie: Value of the HTTP_COOKIE environment variable.
+    cookie_name: Name of the cookie that stores the user info.
+
+  Returns:
+    Tuple (email, admin) where:
+      email: The user's email address, if any.
+      admin: True if the user is an admin; False otherwise.
+  """
+  cookie = Cookie.SimpleCookie(http_cookie)
+
+  cookie_value = ''
+  if cookie_name in cookie:
+    cookie_value = cookie[cookie_name].value
+
+  email, admin = (cookie_value.split(':') + ['', ''])[:2]
+  return email, (admin == 'True')
+
+
+def CreateCookieData(email, admin):
+  """Creates cookie payload data.
+
+  Args:
+    email, admin: Parameters to incorporate into the cookie.
+
+  Returns:
+    String containing the cookie payload.
+  """
+  admin_string = 'False'
+  if admin:
+    admin_string = 'True'
+  return '%s:%s' % (email, admin_string)
+
+
+def SetUserInfoCookie(email, admin, cookie_name=COOKIE_NAME):
+  """Creates a cookie to set the user information for the requestor.
+
+  Args:
+    email: Email to set for the user.
+    admin: True if the user should be admin; False otherwise.
+    cookie_name: Name of the cookie that stores the user info.
+
+  Returns:
+    'Set-Cookie' header for setting the user info of the requestor.
+  """
+  cookie_value = CreateCookieData(email, admin)
+  set_cookie = Cookie.SimpleCookie()
+  set_cookie[cookie_name] = cookie_value
+  set_cookie[cookie_name]['path'] = '/'
+  return '%s\r\n' % set_cookie
+
+
+def ClearUserInfoCookie(cookie_name=COOKIE_NAME):
+  """Clears the user info cookie from the requestor, logging them out.
+
+  Args:
+    cookie_name: Name of the cookie that stores the user info.
+
+  Returns:
+    'Set-Cookie' header for clearing the user info of the requestor.
+  """
+  set_cookie = Cookie.SimpleCookie()
+  set_cookie[cookie_name] = ''
+  set_cookie[cookie_name]['path'] = '/'
+  set_cookie[cookie_name]['max-age'] = '0'
+  return '%s\r\n' % set_cookie
+
+
+LOGIN_TEMPLATE = """<html>
+<head>
+  <title>Login</title>
+</head>
+<body>
+
+<form method='get' action='%(login_url)s'
+      style='text-align:center; font: 13px sans-serif'>
+  <div style='width: 20em; margin: 1em auto;
+              text-align:left;
+              padding: 0 2em 1.25em 2em;
+              background-color: #d6e9f8;
+              border: 2px solid #67a7e3'>
+    <h3>%(login_message)s</h3>
+    <p style='padding: 0; margin: 0'>
+      <label for='email' style="width: 3em">Email:</label>
+      <input name='email' type='text' value='%(email)s' id='email'/>
+    </p>
+    <p style='margin: .5em 0 0 3em; font-size:12px'>
+      <input name='admin' type='checkbox' value='True'
+       %(admin_checked)s id='admin'/>
+        <label for='admin'>Sign in as Administrator</label>
+    </p>
+    <p style='margin-left: 3em'>
+      <input name='action' value='Login' type='submit'
+             id='submit-login' />
+      <input name='action' value='Logout' type='submit'
+             id='submit-logout' />
+    </p>
+  </div>
+  <input name='continue' type='hidden' value='%(continue_url)s'/>
+</form>
+
+</body>
+</html>
+"""
+
+
+def RenderLoginTemplate(login_url, continue_url, email, admin):
+  """Renders the login page.
+
+  Args:
+    login_url, continue_url, email, admin: Parameters passed to
+      LoginCGI.
+
+  Returns:
+    String containing the contents of the login page.
+  """
+  login_message = 'Not logged in'
+  if email:
+    login_message = 'Logged in'
+  admin_checked = ''
+  if admin:
+    admin_checked = 'checked'
+
+  template_dict = {
+
+
+    'email': email or 'test\x40example.com',
+    'admin_checked': admin_checked,
+    'login_message': login_message,
+    'login_url': login_url,
+    'continue_url': continue_url
+  }
+
+  return LOGIN_TEMPLATE % template_dict
+
+
+def LoginRedirect(login_url,
+                  hostname,
+                  port,
+                  relative_url,
+                  outfile):
+  """Writes a login redirection URL to a user.
+
+  Args:
+    login_url: Relative URL which should be used for handling user logins.
+    hostname: Name of the host on which the webserver is running.
+    port: Port on which the webserver is running.
+    relative_url: String containing the URL accessed.
+    outfile: File-like object to which the response should be written.
+  """
+  dest_url = "http://%s:%s%s" % (hostname, port, relative_url)
+  redirect_url = 'http://%s:%s%s?%s=%s' % (hostname,
+                                           port,
+                                           login_url,
+                                           CONTINUE_PARAM,
+                                           urllib.quote(dest_url))
+  outfile.write('Status: 302 Requires login\r\n')
+  outfile.write('Location: %s\r\n\r\n' % redirect_url)
+
+
+def LoginCGI(login_url,
+             email,
+             admin,
+             action,
+             set_email,
+             set_admin,
+             continue_url,
+             outfile):
+  """Runs the login CGI.
+
+  This CGI does not care about the method at all. For both POST and GET the
+  client will be redirected to the continue URL.
+
+  Args:
+    login_url: URL used to run the CGI.
+    email: Current email address of the requesting user.
+    admin: True if the requesting user is an admin; False otherwise.
+    action: The action used to run the CGI; 'Login' for a login action, 'Logout'
+      for when a logout should occur.
+    set_email: Email to set for the user; Empty if no email should be set.
+    set_admin: True if the user should be an admin; False otherwise.
+    continue_url: URL to which the user should be redirected when the CGI
+      finishes loading; defaults to the login_url with no parameters (showing
+      current status) if not supplied.
+    outfile: File-like object to which all output data should be written.
+  """
+  redirect_url = ''
+  output_headers = []
+
+  if action:
+    if action.lower() == LOGOUT_ACTION.lower():
+      output_headers.append(ClearUserInfoCookie())
+    elif set_email:
+      output_headers.append(SetUserInfoCookie(set_email, set_admin))
+
+    redirect_url = continue_url or login_url
+  elif email and continue_url:
+    redirect_url = continue_url
+
+  if redirect_url:
+    outfile.write('Status: 302 Redirecting to continue URL\r\n')
+    for header in output_headers:
+      outfile.write(header)
+    outfile.write('Location: %s\r\n' % redirect_url)
+    outfile.write('\r\n')
+  else:
+    outfile.write('Status: 200\r\n')
+    outfile.write('Content-Type: text/html\r\n')
+    outfile.write('\r\n')
+    outfile.write(RenderLoginTemplate(login_url,
+                                      continue_url,
+                                      email,
+                                      admin))
+
+
+def main():
+  """Runs the login and logout CGI script."""
+  form = cgi.FieldStorage()
+  login_url = os.environ['PATH_INFO']
+  email = os.environ.get('USER_EMAIL', '')
+  admin = os.environ.get('USER_IS_ADMIN', '0') == '1'
+
+  action = form.getfirst(ACTION_PARAM)
+  set_email = form.getfirst(EMAIL_PARAM, '')
+  set_admin = form.getfirst(ADMIN_PARAM, '') == 'True'
+  continue_url = form.getfirst(CONTINUE_PARAM, '')
+
+  LoginCGI(login_url,
+           email,
+           admin,
+           action,
+           set_email,
+           set_admin,
+           continue_url,
+           sys.stdout)
+  return 0
+
+
+if __name__ == '__main__':
+  main()