4 from mako.template import Template
5 from mako.lookup import TemplateLookup
7 import datetime, decimal
8 from StringIO import StringIO
9 from invirt.config import structs as config
10 import invirt.database
11 from webcommon import State
14 class MakoHandler(cherrypy.dispatch.LateParamPageHandler):
15 """Callable which processes a dictionary, returning the rendered body."""
17 def __init__(self, template, next_handler,
18 content_type='text/html; charset=utf-8'):
19 self.template = template
20 self.next_handler = next_handler
21 self.content_type = content_type
24 env = globals().copy()
25 env.update(self.next_handler())
26 cherrypy.response.headers['Content-Type'] = self.content_type
27 return self.template.render(**env)
30 class MakoLoader(object):
35 def get_lookup(self, directories, module_directory=None,
36 collection_size=-1, imports=[], **kwargs):
37 # Find the appropriate template lookup.
38 key = (tuple(directories), module_directory)
40 lookup = self.lookups[key]
42 lookup = TemplateLookup(directories=directories,
43 module_directory=module_directory,
44 collection_size=collection_size,
45 default_filters=['decode.utf8'],
46 input_encoding='utf-8',
47 output_encoding='utf-8',
50 self.lookups[key] = lookup
53 def __call__(self, filename, directories, module_directory=None,
54 collection_size=-1, content_type='text/html; charset=utf-8',
56 cherrypy.request.lookup = lookup = self.get_lookup(
57 directories, module_directory, collection_size, imports)
58 cherrypy.request.template = t = lookup.get_template(filename)
59 cherrypy.request.handler = MakoHandler(
60 t, cherrypy.request.handler, content_type)
62 cherrypy.tools.mako = cherrypy.Tool('on_start_resource', MakoLoader())
65 def revertStandardError():
66 """Move stderr to stdout, and return the contents of the old stderr."""
68 if not isinstance(errio, StringIO):
70 sys.stderr = sys.stdout
76 old_handler = cherrypy.request.handler
77 def wrapper(*args, **kwargs):
78 sys.stderr = StringIO()
79 ret = old_handler(*args, **kwargs)
80 e = revertStandardError()
82 if isinstance(ret, dict):
86 cherrypy.request.handler = wrapper
88 cherrypy.tools.catch_stderr = cherrypy.Tool('before_handler', catchStderr)
91 class JSONEncoder(simplejson.JSONEncoder):
92 def default(self, obj):
93 if isinstance(obj, datetime.datetime):
95 elif isinstance(obj, decimal.Decimal):
98 return simplejson.JSONEncoder.default(self, obj)
101 def jsonify_tool_callback(*args, **kwargs):
102 if not cherrypy.request.cached:
103 response = cherrypy.response
104 response.headers['Content-Type'] = 'text/javascript'
105 response.body = JSONEncoder().iterencode(response.body)
107 cherrypy.tools.jsonify = cherrypy.Tool('before_finalize',
108 jsonify_tool_callback, priority=30)
112 """If the user isn't logged in, raise 403 with an error."""
113 if cherrypy.request.login is False:
114 raise cherrypy.HTTPError(403,
115 "You are not authorized to access that resource")
117 cherrypy.tools.require_login = cherrypy.Tool('on_start_resource',
118 require_login, priority=150)
122 """If the request isn't a POST request, raise 405 Method Not Allowed"""
123 if cherrypy.request.method != "POST":
124 raise cherrypy.HTTPError(405,
125 "You must submit this request with POST")
127 cherrypy.tools.require_POST = cherrypy.Tool('on_start_resource',
128 require_POST, priority=150)
131 def remote_user_login():
132 """Get remote user from SSL or GSSAPI, and store in request object.
134 Get the current user based on environment variables set by SSL or
135 GSSAPI, and store it in the attribute cherrpy.request.login.
137 Per the CherryPy API (http://www.cherrypy.org/wiki/RequestObject#login),
138 the attribute is set to the username on successful login, to False on
139 failed login, and is left at None if the user attempted no authentication.
141 environ = cherrypy.request.wsgi_environ
142 user = environ.get('REMOTE_USER')
145 if environ.get('AUTH_TYPE') == 'Negotiate':
146 # Convert the krb5 principal into a krb4 username
147 if not user.endswith('@%s' % config.kerberos.realm):
148 cherrypy.request.login = False # failed to log in
150 cherrypy.request.login = user.split('@')[0].replace('/', '.')
152 cherrypy.request.login = user
154 cherrypy.tools.remote_user_login = cherrypy.Tool('on_start_resource',
155 remote_user_login, priority=50)
158 def invirtwebstate_init():
159 """Initialize the cherrypy.request.state object from Invirt"""
160 if not hasattr(cherrypy.request, "state"):
161 cherrypy.request.state = State(cherrypy.request.login)
163 cherrypy.tools.invirtwebstate = cherrypy.Tool('on_start_resource',
164 invirtwebstate_init, priority=100)
167 cherrypy.tools.clear_db_cache = cherrypy.Tool('on_start_resource', invirt.database.clear_cache)
171 _cp_config = {'tools.mako.directories':
172 [os.path.join(os.path.dirname(__file__),'templates')]}