class ImpersonationTest(unittest.TestCase): def setUp(self): self.http_context = Context({}) self.http_context.__enter__() def tearDown(self): self.http_context.__exit__(*sys.exc_info()) def test_impersonation(self): role1 = 'role-1' role2 = 'role-2' role3 = 'role-3' role4 = 'role-4' # Simple test role_1_principal = DummyIdentity(role1) with ImpersonateAs(role_1_principal): self.assertEqual(context.identity, role_1_principal) self.assertTrue(context.identity.is_in_roles(role1)) # Now we change the role role_2_principal = DummyIdentity(role2) with ImpersonateAs(role_2_principal): self.assertFalse(context.identity.is_in_roles(role1)) self.assertTrue(context.identity.is_in_roles(role2)) # Multiple roles role_3_4_principal = DummyIdentity(role3, role4) with ImpersonateAs(role_3_4_principal): self.assertTrue(context.identity.is_in_roles(role3)) self.assertTrue(context.identity.is_in_roles(role4)) self.assertFalse(context.identity.is_in_roles(role1)) self.assertFalse(context.identity.is_in_roles(role2))
def __call__(self, environ, start_response): """Method that `WSGI <https://www.python.org/dev/peps/pep-0333/#id15>`_ server calls """ # Entering the context context_ = Context(environ, self) context_.__enter__() # Preparing some variables status = '200 OK' buffer = None response_iterable = None try: self._hook('begin_request') # Removing the trailing slash in-place, if exists context_.path = context_.path.rstrip('/') # Removing the heading slash, and query string anyway path = context_.path[1:].split('?')[0] # Splitting the path by slash(es) if any remaining_paths = path.split('/') if path else [] # Calling the controller, actually this will be serve our request response_body = self.__root__(*remaining_paths) if response_body: # The goal is to yield an iterable, to encode and iter over it # at the end of this method. if isinstance(response_body, (str, bytes)): # Mocking the body inside an iterable to prevent # the iteration over the str character by character # For more info check the pull-request # #34, https://github.com/Carrene/nanohttp/pull/34 response_iterable = (response_body, ) elif isinstance(response_body, types.GeneratorType): # Generators are iterable ! response_iterable = response_body # Trying to get at least one element from the generator, # to force the method call till the second # `yield` statement buffer = next(response_iterable) elif isinstance(response_body, Iterable): # Creating an iterator from iterable! response_iterable = iter(response_body) else: raise ValueError( 'Controller\'s action/handler response must be ' 'generator and or iterable') except Exception as ex: return self._handle_exception(ex, start_response) self._hook('begin_response') # Setting cookies in response headers, if any cookie = context_.cookies.output() if cookie: for line in cookie.split('\r\n'): context_.response_headers.add_header(*line.split(': ', 1)) start_response( status, context_.response_headers.items(), ) # It seems we have to transfer a body, so this function should yield # a generator of the body chunks. def _response(): try: if buffer is not None: yield context_.encode_response(buffer) if response_iterable: # noinspection PyTypeChecker for chunk in response_iterable: yield context_.encode_response(chunk) else: yield b'' except Exception as ex_: self.__logger__.exception( 'Exception while serving the response.') if settings.debug: yield str(ex_).encode() raise ex_ finally: self._hook('end_response') context.__exit__(*sys.exc_info()) return _response()
def __call__(self, environ, start_response): """Method that `WSGI <https://www.python.org/dev/peps/pep-0333/#id15>`_ server calls """ # Entering the context context_ = Context(environ, self) context_.__enter__() # Preparing some variables status = '200 OK' buffer = None response_iterable = None try: self._hook('begin_request') # Removing the trailing slash in-place, if exists context_.path = context_.path.rstrip('/') # Removing the heading slash, and query string anyway path = context_.path[1:].split('?')[0] # Splitting the path by slash(es) if any remaining_paths = path.split('/') if path else [] # Calling the controller, actually this will be serve our request response_body = self.__root__(*remaining_paths) if response_body: # The goal is to yield an iterable, to encode and iter over it # at the end of this method. if isinstance(response_body, types.GeneratorType): # Generators are iterable ! response_iterable = response_body # Trying to get at least one element from the generator, # to force the method call till the second # `yield` statement buffer = next(response_iterable) elif isinstance(response_body, (str, bytes)): # Mocking the body inside an iterable to prevent # the iteration over the str character by character # For more info check the pull-request # #34, https://github.com/Carrene/nanohttp/pull/34 response_iterable = (response_body, ) else: # Assuming the body is an iterable. response_iterable = response_body except Exception as ex: # the self._handle_exception may raise the error again, if the # error is not subclass of the HTTPStatusOtherwise, # a tuple of the status code and response body will be returned. status, response_body = self._handle_exception(ex) buffer = None response_iterable = (response_body, ) self._hook('begin_response') # Setting cookies in response headers, if any cookie = context_.cookies.output() if cookie: for line in cookie.split('\r\n'): context_.response_headers.add_header(*line.split(': ', 1)) # Sometimes don't need to transfer any body, for example the 304 case. if status[:3] in NO_CONTENT_STATUSES: del context_.response_headers['Content-Type'] start_response(status, context_.response_headers.items()) # This is only header, and body should not be transferred. # So the context is also should be destroyed context.__exit__(*sys.exc_info()) return [] else: start_response(status, context_.response_headers.items()) # It seems we have to transfer a body, so this function should yield # a generator of the body chunks. def _response(): try: if buffer is not None: yield context_.encode_response(buffer) if response_iterable: # noinspection PyTypeChecker for chunk in response_iterable: yield context_.encode_response(chunk) else: yield b'' except Exception as ex_: # pragma: no cover self.__logger__.exception( 'Exception while serving the response.') if settings.debug: yield str(ex_).encode() raise ex_ finally: self._hook('end_response') context.__exit__(*sys.exc_info()) return _response()