def test_auth_read_secret(self): ret = self.run_handler( handle_read, workflow=Workflow(secret_id="wsecret", public=False), workflow_id_or_secret_id="wsecret", ) self.assertHandlerResponse(ret, {"role": "read"})
def build_request(self, **kwargs): request_kwargs = { "request_id": kwargs.get("request_id", 1), "scope": kwargs.get( "scope", { "user": kwargs.get("user", AnonymousUser()), "session": kwargs.get("session", Session()), "headers": kwargs.get("headers", ()), }, ), "workflow": kwargs.get("workflow", Workflow()), "path": kwargs.get("path", "test.path"), "arguments": kwargs.get("arguments", {}), } for key in list(request_kwargs["scope"].keys()) + list(request_kwargs.keys()): try: del kwargs[key] except KeyError: pass # Turn other params, like `wf_module_id=123`, into # `arguments={'wf_module_id':123}` request_kwargs["arguments"].update(kwargs) return HandlerRequest(**request_kwargs)
def test_auth_owner_deny_public(self): ret = self.run_handler( handle_owner, workflow=Workflow(owner=User(), public=True) ) self.assertHandlerResponse( ret, error=("AuthError: no owner access to workflow") )
def test_all_arguments_optional(self): @decorators.websockets_handler(role="read") async def x(**kwargs): return {"x": "y"} user = User() ret = self.run_handler(x, user=user, workflow=Workflow(owner=user)) self.assertHandlerResponse(ret, {"x": "y"})
def test_return_something(self): @decorators.websockets_handler(role="read") async def x(scope, workflow): return {"x": "y"} user = User() ret = self.run_handler(x, user=user, workflow=Workflow(owner=user)) self.assertHandlerResponse(ret, {"x": "y"})
def test_catch_handlererror(self): @decorators.websockets_handler(role="read") async def x(**kwargs): raise HandlerError("should not be logged") user = User() ret = self.run_handler(x, user=user, workflow=Workflow(owner=user)) self.assertHandlerResponse(ret, error="should not be logged")
def test_auth_owner_anonymous_owner(self): user = AnonymousUser() session = Session(session_key="foo") workflow = Workflow(anonymous_owner_session_key=session.session_key) ret = self.run_handler( handle_owner, user=user, session=session, workflow=workflow ) self.assertHandlerResponse(ret, {"role": "owner"})
def test_catch_any_error(self): @decorators.websockets_handler(role="read") async def x(**kwargs): raise ValueError("bad value") user = User() with self.assertLogs(level=logging.ERROR): ret = self.run_handler(x, user=user, workflow=Workflow(owner=user)) self.assertHandlerResponse(ret, error="ValueError: bad value")
def test_auth_role_none(self): # Hopefully, the only way to get here is a race: # # 1. Server receives request and authorizes that the user still has # access to the workflow; # 2. Another process revokes access # 3. Server invokes handler ret = self.run_handler(handle_none, workflow=Workflow(owner=User())) self.assertHandlerResponse(ret, {"role": None})
def test_invalid_arguments(self): @decorators.websockets_handler(role="read") async def x(scope, workflow, x): return None user = User() ret = self.run_handler( x, user=user, workflow=Workflow(owner=user), arguments={"y": 3} ) self.assertHandlerResponse( ret, error=("invalid arguments: x() got an unexpected keyword argument 'y'") )
def test_log_requests(self): @decorators.websockets_handler(role="read") async def x(scope, workflow): return {"x": "y"} user = User() workflow = Workflow(id=1, owner=user) request = self.build_request(path="a.path", user=user, workflow=workflow) with self.assertLogs(decorators.logger, level=logging.INFO) as cm: self.run_with_async_db(x(request)) self.assertEqual( cm.output, ["INFO:server.handlers.decorators:a.path(workflow=1)"] )
def test_passthrough_cancellederror(self): """ CancelledError must be re-raised. Async functions may raise CancelledError at any time It must be re-raised. There's no way to avoid it. (asyncio.shield() in particular is not a way to avoid CancelledError: it's nothing but a waste of time; if you don't believe that go and look it up -- proving it.) """ @decorators.websockets_handler(role="read") async def x(**kwargs): raise asyncio.CancelledError user = User() with self.assertRaises(asyncio.CancelledError): self.run_handler(x, user=user, workflow=Workflow(owner=user))
def test_auth_owner_owner(self): user = User() ret = self.run_handler(handle_owner, user=user, workflow=Workflow(owner=user)) self.assertHandlerResponse(ret, {"role": "owner"})
def test_auth_write_deny_non_owner(self): ret = self.run_handler(handle_write, workflow=Workflow(owner=User())) self.assertHandlerResponse( ret, error=("AuthError: no write access to workflow"))
def test_auth_read_public(self): ret = self.run_handler(handle_read, workflow=Workflow(owner=User(), public=True)) self.assertHandlerResponse(ret, {"role": "read"})
@decorators.websockets_handler(role="write") async def handle_write(workflow, **kwargs): return {"role": "write"} @decorators.websockets_handler(role="owner") async def handle_owner(workflow, **kwargs): return {"role": "owner"} DefaultKwargs = { "user": AnonymousUser(), "session": Session(), "workflow": Workflow(), "path": "path", "arguments": {}, } class WebsocketsHandlerDecoratorTest(HandlerTestCase): def handle(self, **kwargs): """handlers.handle(), synchronous.""" request = self.build_request(**kwargs) return async_to_sync(handlers.handle)(request) def assertHandlerResponse(self, response, data=None, error=""): self.assertEqual( { "data": response.data,