source: package_branches/invirt-web/cherrypy/code/view.py @ 2521

Last change on this file since 2521 was 2519, checked in by price, 15 years ago

Replace weird username logic with the old logic.

remote_user_login() was just like the old getUser(), but different
in puzzling ways.

File size: 5.3 KB
Line 
1import os, sys
2
3import cherrypy
4from mako.template import Template
5from mako.lookup import TemplateLookup
6import simplejson
7import datetime, decimal
8from StringIO import StringIO
9from invirt.config import structs as config
10from webcommon import State
11
12class MakoHandler(cherrypy.dispatch.LateParamPageHandler):
13    """Callable which sets response.body."""
14   
15    def __init__(self, template, next_handler, content_type='text/html; charset=utf-8'):
16        self.template = template
17        self.next_handler = next_handler
18        self.content_type = content_type
19   
20    def __call__(self):
21        env = globals().copy()
22        env.update(self.next_handler())
23        cherrypy.response.headers['Content-Type'] = self.content_type
24        return self.template.render(**env)
25       
26
27class MakoLoader(object):
28   
29    def __init__(self):
30        self.lookups = {}
31
32    def get_lookup(self, directories, module_directory=None,
33                     collection_size=-1, imports=[], **kwargs):
34        # Find the appropriate template lookup.
35        key = (tuple(directories), module_directory)
36        try:
37            lookup = self.lookups[key]
38        except KeyError:
39            lookup = TemplateLookup(directories=directories,
40                                    module_directory=module_directory,
41                                    collection_size=collection_size,
42                                    default_filters=['decode.utf8'],
43                                    input_encoding='utf-8',
44                                    output_encoding='utf-8',
45                                    imports=imports,
46                                    )
47            self.lookups[key] = lookup
48        return lookup
49
50    def __call__(self, filename, directories, module_directory=None,
51                 collection_size=-1, content_type='text/html; charset=utf-8',
52                 imports=[]):
53        cherrypy.request.lookup = lookup = self.get_lookup(directories, module_directory,
54                                                           collection_size, imports)
55       
56        # Replace the current handler.
57        cherrypy.request.template = t = lookup.get_template(filename)
58        cherrypy.request.handler = MakoHandler(t, cherrypy.request.handler, content_type)
59
60cherrypy.tools.mako = cherrypy.Tool('on_start_resource', MakoLoader())
61
62def revertStandardError():
63    """Move stderr to stdout, and return the contents of the old stderr."""
64    errio = sys.stderr
65    if not isinstance(errio, StringIO):
66        return ''
67    sys.stderr = sys.stdout
68    errio.seek(0)
69    return errio.read()
70
71def catchStderr():
72    old_handler = cherrypy.request.handler
73    def wrapper(*args, **kwargs):
74        sys.stderr = StringIO()
75        ret = old_handler(*args, **kwargs)
76        e = revertStandardError()
77        if e:
78            if isinstance(ret, dict):
79                ret["error_text"] = e
80        return ret
81    if old_handler:
82        cherrypy.request.handler = wrapper
83
84cherrypy.tools.catch_stderr = cherrypy.Tool('before_handler', catchStderr)
85
86class JSONEncoder(simplejson.JSONEncoder):
87        def default(self, obj):
88                if isinstance(obj, datetime.datetime):
89                        return str(obj)
90                elif isinstance(obj, decimal.Decimal):
91                        return float(obj)
92                else:
93                        return simplejson.JSONEncoder.default(self, obj)
94
95def jsonify_tool_callback(*args, **kwargs):
96    if not cherrypy.request.cached:
97        response = cherrypy.response
98        response.headers['Content-Type'] = 'text/javascript'
99        response.body = JSONEncoder().iterencode(response.body)
100
101cherrypy.tools.jsonify = cherrypy.Tool('before_finalize', jsonify_tool_callback, priority=30)
102
103def require_login():
104    """If the user isn't logged in, raise 403 with an error."""
105    if not cherrypy.request.login:
106        raise cherrypy.HTTPError(403,
107            "You are not authorized to access that resource")
108
109cherrypy.tools.require_login = cherrypy.Tool('on_start_resource', require_login, priority=150)
110
111def require_POST():
112    """If the request isn't a POST request, raise 405 Method Not Allowed"""
113    if cherrypy.request.method != "POST":
114        raise cherrypy.HTTPError(405,
115                                 "You must submit this request with POST")
116
117cherrypy.tools.require_POST = cherrypy.Tool('on_start_resource', require_POST, priority=150)
118
119def remote_user_login():
120    """Get the current user based on the SSL or GSSAPI environment variables"""
121    environ = cherrypy.request.wsgi_environ
122    user = environ.get('REMOTE_USER')
123    if user is None:
124        cherrypy.request.login = None
125        return
126
127    if environ.get('AUTH_TYPE') == 'Negotiate':
128        # Convert the krb5 principal into a krb4 username
129        if not user.endswith('@%s' % config.kerberos.realm):
130            cherrypy.request.login = None
131        else:
132            cherrypy.request.login = user.split('@')[0].replace('/', '.')
133    else:
134        cherrypy.request.login = user
135
136cherrypy.tools.remote_user_login = cherrypy.Tool('on_start_resource', remote_user_login, priority=50)
137
138def invirtwebstate_init():
139    """Initialize the cherrypy.request.state object from Invirt"""
140    if not hasattr(cherrypy.request, "state"):
141        cherrypy.request.state = State(cherrypy.request.login)
142
143cherrypy.tools.invirtwebstate = cherrypy.Tool('on_start_resource', invirtwebstate_init, priority=100)
144
145class View(object):
146    _cp_config = {'tools.mako.directories': [os.path.join(os.path.dirname(__file__),'templates')]}
Note: See TracBrowser for help on using the repository browser.