def __init__(self, get_user_identity, identify_user, storage=None, cookie_name='auth', login_form=LoginForm, crash_without_storage=True): self.get_user_identity = get_user_identity self.identify_user = identify_user self._cookie_name = cookie_name self._login_form = login_form self.storage = LocalMemStorage() if storage is None else storage self.crash_without_storage = crash_without_storage
def test_delete(self): '`LocalMemStorage` delete method' s = LocalMemStorage() self.assertEqual(s.delete('key'), True) s.set('key', 'value') self.assertEqual(s.delete('key'), True) self.assertEqual(s.get('key'), None)
def test_get(self): '`LocalMemStorage` get method' s = LocalMemStorage() self.assertEqual(s.get('key'), None) self.assertEqual(s.get('key', '1'), '1') s.set('key', 'value') self.assertEqual(s.get('key'), 'value')
class CookieAuth(web.WebHandler): def __init__(self, get_user_identity, identify_user, storage=None, cookie_name='auth', login_form=LoginForm, crash_without_storage=True): self.get_user_identity = get_user_identity self.identify_user = identify_user self._cookie_name = cookie_name self._login_form = login_form self.storage = LocalMemStorage() if storage is None else storage self.crash_without_storage = crash_without_storage def cookie_auth(self, env, data): user = None if self._cookie_name in env.request.cookies: key = env.request.cookies[self._cookie_name] user_identity = self.storage.get(self._cookie_name + ':' + key.encode('utf-8')) if user_identity is not None: user = self.identify_user(env, user_identity) logger.debug('Authenticated: %r', user) env.user = user try: result = self.next_handler(env, data) finally: del env.user return result __call__ = cookie_auth def login_identity(self, user_identity, response=None, path='/'): key = os.urandom(10).encode('hex') response = web.Response() if response is None else response response.set_cookie(self._cookie_name, key, path=path) if not self.storage.set(self._cookie_name+':'+key.encode('utf-8'), str(user_identity)): logger.warning('storage "%r" is unreachable', self.storage) if self.crash_without_storage: raise Exception( 'Storage {!r} is gone or down'.format(self.storage)) return response def logout_user(self, request, response): if self._cookie_name in request.cookies: response.delete_cookie(self._cookie_name) key = request.cookies[self._cookie_name] if key is not None: if not self.storage.delete(self._cookie_name + ':' + \ key.encode('utf-8')): logger.warning('storage "%r" is unreachable', self.storage) def login(self, template='login'): ''' This property will return component which will handle login requests. auth.login(template='login.html') ''' def _login(env, data): form = self._login_form(env) next = env.request.GET.get('next', '/') login_failed = False if env.request.method == 'POST': if form.accept(env.request.POST): user_identity = self.get_user_identity( env, **form.python_data) if user_identity is not None: response = self.login_identity(user_identity) response.status = 303 response.headers['Location'] = next.encode('utf-8') return response login_failed = True data.form = form data.login_failed = login_failed data.login_url = env.root.login.as_url.qs_set(next=next) return env.template.render_to_response(template, data.as_dict()) return web.match('/login', 'login') | _login def logout(self, redirect_to='/'): ''' This property will return component which will handle logout requests. It only handles POST requests and do not display any rendered content. This handler deletes session id from `storage`. If there is no session id provided or id is incorrect handler silently redirects to login url and does not throw any exception. ''' def _logout(env, data): location = redirect_to if location is None and env.request.referer: location = env.request.referer elif location is None: location = '/' response = HTTPSeeOther(location=str(location)) self.logout_user(env.request, response) return response return web.match('/logout', 'logout') | web.method('post') | _logout
class CookieAuth(web.WebHandler): def __init__(self, get_user_identity, identify_user, storage=None, cookie_name='auth', login_form=LoginForm, crash_without_storage=True): self.get_user_identity = get_user_identity self.identify_user = identify_user self._cookie_name = cookie_name self._login_form = login_form self.storage = LocalMemStorage() if storage is None else storage self.crash_without_storage = crash_without_storage def cookie_auth(self, env, data): user = None if self._cookie_name in env.request.cookies: key = env.request.cookies[self._cookie_name] user_identity = self.storage.get(self._cookie_name + ':' + key) if user_identity is not None: user = self.identify_user(env, user_identity) logger.debug('Authenticated: %r', user) env.user = user try: result = self.next_handler(env, data) finally: del env.user return result __call__ = cookie_auth def login_identity(self, user_identity, response=None, path='/'): key = binascii.hexlify(os.urandom(10)).decode('ascii') response = web.Response() if response is None else response response.set_cookie(self._cookie_name, key, path=path) if not self.storage.set(self._cookie_name + ':' + key, str(user_identity)): logger.warning('storage "%r" is unreachable', self.storage) if self.crash_without_storage: raise Exception('Storage {!r} is gone or down'.format( self.storage)) return response def logout_user(self, request, response): if self._cookie_name in request.cookies: response.delete_cookie(self._cookie_name) key = request.cookies[self._cookie_name] if key is not None: if not self.storage.delete(self._cookie_name + ':' + key): logger.warning('storage "%r" is unreachable', self.storage) def login(self, template='login'): ''' This property will return component which will handle login requests. auth.login(template='login.html') ''' def _login(env, data): form = self._login_form(env) next = env.request.GET.get('next', '/') login_failed = False if env.request.method == 'POST': if form.accept(env.request.POST): user_identity = self.get_user_identity( env, **form.python_data) if user_identity is not None: response = HTTPSeeOther(location=next) return self.login_identity(user_identity, response) login_failed = True data.form = form data.login_failed = login_failed data.login_url = env.root.login.as_url.qs_set(next=next) return env.template.render_to_response(template, data.as_dict()) return web.match('/login', 'login') | _login def logout(self, redirect_to='/'): ''' This property will return component which will handle logout requests. It only handles POST requests and do not display any rendered content. This handler deletes session id from `storage`. If there is no session id provided or id is incorrect handler silently redirects to login url and does not throw any exception. ''' def _logout(env, data): location = redirect_to if location is None and env.request.referer: location = env.request.referer elif location is None: location = '/' response = HTTPSeeOther(location=str(location)) self.logout_user(env.request, response) return response return web.match('/logout', 'logout') | web.method('post') | _logout
def test_set(self): '`LocalMemStorage` set method' s = LocalMemStorage() s.set('key', 'value') self.assertEqual(s.storage['key'], 'value')
def test_set_rewrite(self): '`LocalMemStorage` set method of existing key' s = LocalMemStorage() s.set('key', 'value') s.set('key', 'value1') self.assertEqual(s.storage['key'], 'value1')