from wsgiref.validate import validator as V from base64 import b64decode from genshi.template import MarkupTemplate from demo1_basic import serve from demo3_getparams import err_404, slides_app from demo4_dispatcher import files_app, dispatcher def login_mw(app, users={}): def authenticate(environ): try: loginstring = b64decode(environ['HTTP_AUTHORIZATION'][6:]) uname, pw = loginstring.split(':', 1) udata = users[uname] if udata['password'] == pw: return {'user': uname, 'permissions': udata['permissions']} except (KeyError, ValueError, TypeError): pass return {'user': None, 'permissions': [], 'deny_reason': 'Invalid username or password'} def login_wrapper(environ, start_response): environ['demo.login'] = authenticate(environ) return app(environ, start_response) return login_wrapper def access_denied_app(environ, start_response): headers = [('WWW-Authenticate', 'basic realm="rosedu"'), ('Content-Type', 'text/plain')] start_response('401 Unauthorized', headers) reason = environ.get('demo.login', {}).get('deny_reason', '') return [reason] def auth_mw(app, permission=None): def auth_wrapper(environ, start_response): login_data = environ.setdefault('demo.login', {}) if permission not in login_data.get('permissions', []): user = login_data.get('user', '') if user is not None: login_data['deny_reason'] = ( 'User %r is not allowed in here' % user) return access_denied_app(environ, start_response) else: return app(environ, start_response) return auth_wrapper def logger_mw(app): def logger_wrapper(environ, start_response): print 'method:', environ['REQUEST_METHOD'] print 'path:', repr(environ['PATH_INFO']) print 'qery_string:', repr(environ['QUERY_STRING']) return app(environ, start_response) return logger_wrapper def htmldeco_mw(app, template): def htmldeco_wrapper(environ, start_response): start = {} def fake_start_response(status, headers): headers = filter(lambda h: h[0].lower() != 'content-type', headers) start.update({'status': status, 'headers': headers}) ret = app(environ, fake_start_response) out = template(environ=environ, raw_output=''.join(ret)) start['headers'].append(('Content-Type', 'text/html')) start_response(start['status'], start['headers']) return [out] return htmldeco_wrapper template = MarkupTemplate(""" ${raw_output} ${pformat(environ)} """) def decorate(**kwargs): return template.generate(**kwargs).render() if __name__ == '__main__': demo_config = { 'users': { 'gigel': {'password': 'gig1', 'permissions': ['see_files']}, 'nicu': {'password': 'nic1', 'permissions': ['see_slides']}, }, 'url_map': [ ('/file', V(auth_mw(files_app, 'see_files'))), ('/slide', V(auth_mw(V(htmldeco_mw(slides_app, decorate)), 'see_slides'))), ], } app = V(dispatcher(demo_config['url_map'])) app = V(login_mw(app, demo_config['users'])) app = V(logger_mw(app)) serve(app)