from base64 import b64encode from wsgiref.validate import validator import pytest import paste from paste import authenticate from ..common_wsgi import call_app @pytest.fixture def app(): @validator @authenticate @validator def app(_, start_response): start_response("200 OK", [("Content-Type", "text/plain")]) return [b"Hello, world!"] return app @pytest.mark.parametrize("method", ["GET", "HEAD"]) def test_unauthenticated_request(app, method, monkeypatch): monkeypatch.delattr(paste, "check_token") environ = {"REQUEST_METHOD": method} response = call_app(app, environ) assert response.data == b"Hello, world!" assert response.status == "200 OK" assert ("Content-Type", "text/plain") in response.headers @pytest.mark.parametrize("method", ["GET", "HEAD"]) def test_unauthenticated_request_with_key(app, method, monkeypatch): monkeypatch.delattr(paste, "check_token") environ = { "REQUEST_METHOD": method, "paste.db_conn": None, "HTTP_AUTHORIZATION": "ApiKey AAAA", } response = call_app(app, environ) assert response.data == b"Hello, world!" assert response.status == "200 OK" assert ("Content-Type", "text/plain") in response.headers @pytest.mark.parametrize("method", ["POST", "PUT", "DELETE"]) def test_authenticate_no_header(app, method, monkeypatch): monkeypatch.delattr(paste, "check_token") environ = {"REQUEST_METHOD": method} response = call_app(app, environ) assert response.data == b"401 Unauthorized\n" assert response.status == "401 Unauthorized" assert ("Content-Type", "text/plain") in response.headers assert ("WWW-Authenticate", "APIKey") in response.headers @pytest.mark.parametrize("method", ["POST", "PUT", "DELETE"]) @pytest.mark.parametrize("key", ["ApiKey AAAA", "APIKey AAA", "APIKey AAAA", "AAAA"]) def test_authenticate_malformed_key(app, method, key, monkeypatch): monkeypatch.delattr(paste, "check_token") environ = {"REQUEST_METHOD": method, "HTTP_AUTHORIZATION": key} response = call_app(app, environ) assert response.data == b"401 Unauthorized\n" assert response.status == "401 Unauthorized" assert ("Content-Type", "text/plain") in response.headers assert ("WWW-Authenticate", "APIKey") in response.headers @pytest.mark.parametrize("method", ["POST", "PUT", "DELETE"]) def test_authenticate_check_token_fail(app, method, monkeypatch): check_token_called = False token = b"test" environ = { "REQUEST_METHOD": method, "paste.db_conn": object(), "HTTP_AUTHORIZATION": f"APIKey {b64encode(token).decode()}", } def check_token(conn, tok): nonlocal check_token_called assert conn == environ["paste.db_conn"] assert tok == token check_token_called = True return False monkeypatch.setattr(paste, "check_token", check_token) response = call_app(app, environ) assert check_token_called assert response.data == b"401 Unauthorized\n" assert response.status == "401 Unauthorized" assert ("Content-Type", "text/plain") in response.headers assert ("WWW-Authenticate", "APIKey") in response.headers @pytest.mark.parametrize("method", ["POST", "PUT", "DELETE"]) def test_authenticate_check_token_success(app, method, monkeypatch): check_token_called = False token = b"test" environ = { "REQUEST_METHOD": method, "paste.db_conn": object(), "HTTP_AUTHORIZATION": f"APIKey {b64encode(token).decode()}", } def check_token(conn, tok): nonlocal check_token_called assert conn == environ["paste.db_conn"] assert tok == token check_token_called = True return True monkeypatch.setattr(paste, "check_token", check_token) response = call_app(app, environ) assert check_token_called assert response.data == b"Hello, world!" assert response.status == "200 OK" assert ("Content-Type", "text/plain") in response.headers