def test_middleware_token_validation_raises_error_on_token_exp(app_settings): def test_handler(jwt_identity: JWTIdentity): if jwt_identity is None: return "No user token present" return jwt_identity.id jwt = JWT(key="keepthissafe", alg="HS256") iat = dt.datetime.now() + dt.timedelta(seconds=-10) exp = iat + dt.timedelta(seconds=5) payload = {"sub": "1234567890", "name": "John Doe", "iat": iat, "exp": exp} token = jwt.encode(payload) routes = [Route("/auth-required", method="GET", handler=test_handler)] components = [ SettingsComponent(app_settings), JWTComponent(), JWTIdentityComponent(), ] middleware = [ResponseRendererMiddleware(), JWTAuthMiddleware()] app = App(routes=routes, components=components, middleware=middleware) client = testing.TestClient(app) response = client.get("/auth-required", headers={"Authorization": f"Bearer {token}"}) assert 401 == response.status_code content = response.json() assert "error_message" in content assert content.get("status") == 401
def test_middleware_white_listing(app_settings, testing_token): def test_handler(jwt_identity: JWTIdentity): if jwt_identity is None: return "No user token present" return jwt_identity.id routes = [Route("/whitelisted", method="GET", handler=test_handler)] components = [ SettingsComponent({ **app_settings, "JWT_AUTH_WHITELIST": ["test_handler"] }), JWTComponent(), JWTIdentityComponent(), ] middleware = [ResponseRendererMiddleware(), JWTAuthMiddleware()] app = App(routes=routes, components=components, middleware=middleware) client = testing.TestClient(app) response = client.get("/whitelisted", headers={"Authorization": f"Bearer {testing_token}"}) unauthenticated = client.get("/whitelisted") assert 200 == response.status_code assert "1234567890" in response.data assert 200 == unauthenticated.status_code assert "No user token present" in unauthenticated.data
def test_test_client_raises_an_error_if_given_both_data_and_json(): # Given that I have a test client client = testing.TestClient(app) # When I try to pass it both data and json params # Then a RuntimeError should be raised with pytest.raises(RuntimeError): client.get("/", data={}, json={})
def test_complex_apps_can_render_the_swagger_ui(): # Given that I have a complex app # When I visit its docs uri response = testing.TestClient(app).get("/docs") # Then I should get back a successful response assert response.status_code == 200 assert response.headers["content-type"] == "text/html" assert app.reverse_uri("schema") in response.data
def test_complex_apps_can_return_openapi_document(): # Given that I have a complex app # When I visit its schema uri response = testing.TestClient(app).get("/schema.json") # Then I should get back a successful response assert response.status_code == 200 with open("tests/openapi/fixtures/complex.json") as f: assert response.json() == json.load(f)
def test_empty_app_can_return_openapi_document(): # Given that I have an empty app app = App(routes=[ Route("/schema.json", OpenAPIHandler( Metadata( title="empty application", description="an application that doesn't do anything", version="0.1.0", contact=Contact(name="Jim Gordon", ), )), name="schema"), ]) # When I visit its schema uri response = testing.TestClient(app).get("/schema.json") # Then I should get back a successful response assert response.status_code == 200 assert response.json() == { "openapi": "3.0.1", "info": { "title": "empty application", "description": "an application that doesn't do anything", "version": "0.1.0", "contact": { "name": "Jim Gordon", }, }, "paths": { "/schema.json": { "get": { "tags": [], "operationId": "schema", "summary": "Generates an OpenAPI v3 document.", "description": "", "deprecated": False, "parameters": [], "responses": { "200": { "description": "A successful response.", "content": {}, }, }, } } }, "components": { "schemas": {}, "securitySchemes": {}, }, }
def test_apps_session_cookies_expire(): # Given that I have an app with a cookie store that immediately expires session cookies cookie_store = CookieStore(b"secret", cookie_ttl=0) def set_username(username: str, session: Session) -> None: session["username"] = username def get_username(session: Session) -> Optional[str]: return session.get("username") app = App( components=[ SessionComponent(cookie_store), ], middleware=[ SessionMiddleware(cookie_store), ResponseRendererMiddleware(), ], routes=[ Route("/set-username/{username}", set_username), Route("/get-username", get_username), ], ) # And a client for that app client = testing.TestClient(app) # When I make a request to a handler that stores session data response = client.get(app.reverse_uri("set_username", username="******")) # Then I should get back a successful response assert response.status_code == 200 # And the response should contain my session cookie cookie = cookies.SimpleCookie() for data in response.headers.get_all("set-cookie"): cookie.load(data.replace("SameSite=Strict", "")) assert "__sess__" in cookie # When I make another request with that same cookie session_cookie = cookie.output(attrs=[], header="") response = client.get(app.reverse_uri("get_username"), headers={ "cookie": session_cookie, }) # Then I should get back nothing assert response.json() is None
def test_claims_required_attaches_values(app_settings): @claims_required({"admin": True}) def test_handler(): return "Handler called" routes = [Route("/claims", method="GET", handler=test_handler)] components = [SettingsComponent(app_settings)] middleware = [ResponseRendererMiddleware()] app = App(routes=routes, components=components, middleware=middleware) client = testing.TestClient(app) response = client.get("/claims") assert 200 == response.status_code assert "admin" in test_handler.claims assert test_handler.claims.get("admin") is True assert "Handler called" in response.data
def test_middleware_raises_401_error(app_settings): def test_handler(): return "Handler called" routes = [Route("/auth-required", method="GET", handler=test_handler)] components = [ SettingsComponent(app_settings), JWTComponent(), JWTIdentityComponent(), ] middleware = [ResponseRendererMiddleware(), JWTAuthMiddleware()] app = App(routes=routes, components=components, middleware=middleware) client = testing.TestClient(app) response = client.get("/auth-required") assert 401 == response.status_code
def test_test_client_auth(): # Given that I have a test client client = testing.TestClient(app) # When I make a request without auth response = client.get("/") # Then I should get a 403 back assert response.status_code == 403 assert response.data == '{"error": "Forbidden"}' # When I make a request with auth def auth(request): request.headers["authorization"] = "Bearer authorized" return request response = client.get("/", auth=auth) # Then I should get back a 200 assert response.status_code == 200
def test_JWT_claims_options_raises_error(app_settings, testing_token): def test_handler(jwt_identity: JWTIdentity): if jwt_identity is None: return "No user token present" return jwt_identity.id jwt = JWT(key=app_settings.get("JWT_SECRET_KEY"), alg="HS256") mod_token = jwt.encode({ **jwt.decode(testing_token), **{ "iss": "https://molten.com" } }) routes = [Route("/claim_options", method="GET", handler=test_handler)] components = [ SettingsComponent({ **app_settings, "JWT_CLAIMS_OPTIONS": { "iss": { "essential": True, "values": ["https://example.com", "https://example.org"], } }, }), JWTComponent(), JWTIdentityComponent(), ] middleware = [ResponseRendererMiddleware(), JWTAuthMiddleware()] app = App(routes=routes, components=components, middleware=middleware) client = testing.TestClient(app) missing_claim_response = client.get( "/claim_options", headers={"Authorization": f"Bearer {testing_token}"}) wrong_claim_value_response = client.get( "/claim_options", headers={"Authorization": f"Bearer {mod_token}"}) assert 401 == missing_claim_response.status_code assert 401 == wrong_claim_value_response.status_code
def test_claims_required_raises_error(app_settings, testing_token): @claims_required({"admin": True}) def test_handler(): return "Handler called" routes = [Route("/claims", method="GET", handler=test_handler)] components = [ SettingsComponent(app_settings), JWTComponent(), JWTIdentityComponent(), ] middleware = [ResponseRendererMiddleware(), JWTAuthMiddleware()] app = App(routes=routes, components=components, middleware=middleware) client = testing.TestClient(app) response = client.get("/claims", headers={"Authorization": f"Bearer {testing_token}"}) assert 403 == response.status_code
def test_middleware_anonymous_user_support(app_settings): @allow_anonymous def test_handler(): return "Handler called" routes = [Route("/auth-maybe", method="GET", handler=test_handler)] components = [ SettingsComponent(app_settings), JWTComponent(), JWTIdentityComponent(), ] middleware = [ResponseRendererMiddleware(), JWTAuthMiddleware()] app = App(routes=routes, components=components, middleware=middleware) client = testing.TestClient(app) response = client.get("/auth-maybe") assert 200 == response.status_code assert "Handler called" in response.data
def test_identity_extract_jwt_from_cookie(app_settings): def test_auth(jwt: JWT): cookie_name = "molten_auth_cookie" cookie_value = jwt.encode({"sub": 123456, "name": "spiderman"}) auth_response = Response(HTTP_200) auth_response.set_cookie(Cookie(cookie_name, cookie_value)) return auth_response def test_cookie(jwt_identity: JWTIdentity): if jwt_identity is None: return "Didn't work" return f"Hello {jwt_identity.name} your sub id is {jwt_identity.sub}" routes = [ Route("/auth", method="POST", handler=test_auth), Route("/cookie", method="GET", handler=test_cookie), ] components = [ SettingsComponent({ **app_settings, **{ "JWT_AUTH_COOKIE": "molten_auth_cookie" } }), JWTComponent(), JWTIdentityComponent(), ] app = App(routes=routes, components=components) client = testing.TestClient(app) auth_response = client.post("/auth") cookie_value = auth_response.headers.get_all("set-cookie")[0] assert "molten_auth_cookie" in cookie_value cookie_response = client.get("/cookie", headers={"cookie": cookie_value}) assert "123456" in cookie_response.data assert "spiderman" in cookie_response.data
def test_middleware_token_validation_passes(app_settings, testing_token): def test_handler(jwt_identity: JWTIdentity): if jwt_identity is None: return "No user token present" return jwt_identity.id routes = [Route("/auth-required", method="GET", handler=test_handler)] components = [ SettingsComponent(app_settings), JWTComponent(), JWTIdentityComponent(), ] middleware = [ResponseRendererMiddleware(), JWTAuthMiddleware()] app = App(routes=routes, components=components, middleware=middleware) client = testing.TestClient(app) response = client.get("/auth-required", headers={"Authorization": f"Bearer {testing_token}"}) assert 200 == response.status_code assert "1234567890" in response.data
def test_app_can_render_mail_templates(): mail = Mail( user="******", password="******", port=587, use_tls=True, suppress_send=True, ) mail.send = MagicMock(return_value=None) def template_handler(mail_templates: MailTemplates) -> Response: mail.send_message( subject="Test email", html=mail_templates.render("test_template.html", name="Molten"), recipients=["*****@*****.**"], ) return Response(HTTP_204, content="") app = App( components=[MailTemplatesComponent("./tests/mail_templates")], routes=[Route("/", template_handler, name="index")], ) client = testing.TestClient(app) # Given that a handler will use templating # When constructing and email response = client.get(app.reverse_uri("index")) # Then I should get back a successfull response assert response.status_code == 204 # and the handler should have called the Mail object # with the string value of the rendered template mail_msg = mail.send.call_args[0][0] assert "<th>Hey there Molten</th>" in mail_msg.html
def test_missing_auth_cookie(app_settings): def test_cookie(jwt_identity: JWTIdentity): if jwt_identity is None: return "Didn't work" return f"Hello {jwt_identity.name} your sub id is {jwt_identity.sub}" routes = [Route("/cookie", method="GET", handler=test_cookie)] components = [ SettingsComponent({ **app_settings, **{ "JWT_AUTH_COOKIE": "molten_auth_cookie" } }), JWTComponent(), JWTIdentityComponent(), ] app = App(routes=routes, components=components) client = testing.TestClient(app) cookie_response = client.get("/cookie") assert "Didn't work" in cookie_response.data
app = App(components=[ TOMLSettingsComponent("tests/contrib/fixtures/sqlalchemy_settings.toml"), SQLAlchemyEngineComponent(), SQLAlchemySessionComponent(), ], middleware=[ ResponseRendererMiddleware([JSONRenderer()]), SQLAlchemyMiddleware(), ], routes=[ Route("/todos", create_todo, method="POST"), Route("/todos/{todo_id}", get_todo), Route("/no-db", no_db), ]) client = testing.TestClient(app) def initdb(engine_data: EngineData): Base.metadata.create_all(engine_data.engine) resolver = app.injector.get_resolver() resolver.resolve(initdb)() def test_can_create_and_retrieve_todos(): # When I make a request to create a todo response = client.post( app.reverse_uri("create_todo"), json={"description": "test"},
def client(app): """Creates a testing client""" return testing.TestClient(app)
def client(): return testing.TestClient(app)
def client(test_app): return testing.TestClient(test_app)