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

Last change on this file since 2722 was 2722, checked in by broder, 15 years ago

view.py: clean up remote_user_login

Remove dead code, and make the docstring clear about what the function is
actually doing.

File size: 5.6 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 processes a dictionary, returning the rendered 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        cherrypy.request.template = t = lookup.get_template(filename)
56        cherrypy.request.handler = MakoHandler(t, cherrypy.request.handler, content_type)
57
58cherrypy.tools.mako = cherrypy.Tool('on_start_resource', MakoLoader())
59
60def revertStandardError():
61    """Move stderr to stdout, and return the contents of the old stderr."""
62    errio = sys.stderr
63    if not isinstance(errio, StringIO):
64        return ''
65    sys.stderr = sys.stdout
66    errio.seek(0)
67    return errio.read()
68
69def catchStderr():
70    old_handler = cherrypy.request.handler
71    def wrapper(*args, **kwargs):
72        sys.stderr = StringIO()
73        ret = old_handler(*args, **kwargs)
74        e = revertStandardError()
75        if e:
76            if isinstance(ret, dict):
77                ret["error_text"] = e
78        return ret
79    if old_handler:
80        cherrypy.request.handler = wrapper
81
82cherrypy.tools.catch_stderr = cherrypy.Tool('before_handler', catchStderr)
83
84class JSONEncoder(simplejson.JSONEncoder):
85        def default(self, obj):
86                if isinstance(obj, datetime.datetime):
87                        return str(obj)
88                elif isinstance(obj, decimal.Decimal):
89                        return float(obj)
90                else:
91                        return simplejson.JSONEncoder.default(self, obj)
92
93def jsonify_tool_callback(*args, **kwargs):
94    if not cherrypy.request.cached:
95        response = cherrypy.response
96        response.headers['Content-Type'] = 'text/javascript'
97        response.body = JSONEncoder().iterencode(response.body)
98
99cherrypy.tools.jsonify = cherrypy.Tool('before_finalize', jsonify_tool_callback, priority=30)
100
101def require_login():
102    """If the user isn't logged in, raise 403 with an error."""
103    if cherrypy.request.login is False:
104        raise cherrypy.HTTPError(403,
105            "You are not authorized to access that resource")
106
107cherrypy.tools.require_login = cherrypy.Tool('on_start_resource', require_login, priority=150)
108
109def require_POST():
110    """If the request isn't a POST request, raise 405 Method Not Allowed"""
111    if cherrypy.request.method != "POST":
112        raise cherrypy.HTTPError(405,
113                                 "You must submit this request with POST")
114
115cherrypy.tools.require_POST = cherrypy.Tool('on_start_resource', require_POST, priority=150)
116
117def remote_user_login():
118    """Get remote user from SSL or GSSAPI, and store in request object.
119
120Get the current user based on environment variables set by SSL or
121GSSAPI, and store it in the attribute cherrpy.request.login.
122
123Per the CherryPy API (http://www.cherrypy.org/wiki/RequestObject#login),
124the attribute is set to the username on successful login, to False on
125failed login, and is left at None if the user attempted no authentication.
126"""
127    environ = cherrypy.request.wsgi_environ
128    user = environ.get('REMOTE_USER')
129    if user is None:
130        return
131    if environ.get('AUTH_TYPE') == 'Negotiate':
132        # Convert the krb5 principal into a krb4 username
133        if not user.endswith('@%s' % config.kerberos.realm):
134            cherrypy.request.login = False # failed to log in
135        else:
136            cherrypy.request.login = user.split('@')[0].replace('/', '.')
137    else:
138        cherrypy.request.login = user
139
140cherrypy.tools.remote_user_login = cherrypy.Tool('on_start_resource', remote_user_login, priority=50)
141
142def invirtwebstate_init():
143    """Initialize the cherrypy.request.state object from Invirt"""
144    if not hasattr(cherrypy.request, "state"):
145        cherrypy.request.state = State(cherrypy.request.login)
146
147cherrypy.tools.invirtwebstate = cherrypy.Tool('on_start_resource', invirtwebstate_init, priority=100)
148
149class View(object):
150    _cp_config = {'tools.mako.directories': [os.path.join(os.path.dirname(__file__),'templates')]}
Note: See TracBrowser for help on using the repository browser.