Replace basic auth with session login
This commit is contained in:
+49
-22
@@ -1,6 +1,5 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import time
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
@@ -15,16 +14,18 @@ from resume_agent.webapp import create_app
|
||||
|
||||
TEST_USERNAME = "resume-user"
|
||||
TEST_PASSWORD = "test-password"
|
||||
TEST_AUTHORIZATION = "Basic " + base64.b64encode(
|
||||
f"{TEST_USERNAME}:{TEST_PASSWORD}".encode()
|
||||
).decode()
|
||||
TEST_AUTH_HEADERS = {"Authorization": TEST_AUTHORIZATION}
|
||||
|
||||
|
||||
class TestClient(RawTestClient):
|
||||
def __init__(self, app: Any, **kwargs: Any) -> None:
|
||||
headers = {**TEST_AUTH_HEADERS, **kwargs.pop("headers", {})}
|
||||
super().__init__(app, headers=headers, **kwargs)
|
||||
def __enter__(self) -> TestClient:
|
||||
super().__enter__()
|
||||
response = self.post(
|
||||
"/login",
|
||||
data={"username": TEST_USERNAME, "password": TEST_PASSWORD, "next": "/"},
|
||||
follow_redirects=False,
|
||||
)
|
||||
assert response.status_code == 303
|
||||
return self
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
@@ -133,19 +134,47 @@ def test_authentication_protects_ui_api_static_and_editor(tmp_path: Path) -> Non
|
||||
|
||||
with RawTestClient(app) as client:
|
||||
assert client.get("/healthz").status_code == 200
|
||||
for path in ("/", "/api/status", "/favicon.ico", "/cv/"):
|
||||
response = client.get(path)
|
||||
assert response.status_code == 401
|
||||
assert response.headers["www-authenticate"].startswith("Basic ")
|
||||
wrong = client.get(
|
||||
"/api/status",
|
||||
headers={"Authorization": "Basic " + base64.b64encode(b"wrong:wrong").decode()},
|
||||
login_page = client.get("/login")
|
||||
assert login_page.status_code == 200
|
||||
assert "Welcome back" in login_page.text
|
||||
|
||||
assert client.get("/", follow_redirects=False).status_code == 303
|
||||
api_response = client.get("/api/status")
|
||||
assert api_response.status_code == 401
|
||||
assert api_response.json()["detail"].startswith("Your session has expired")
|
||||
assert client.get("/favicon.ico", follow_redirects=False).status_code == 303
|
||||
assert client.get("/cv/", follow_redirects=False).status_code == 303
|
||||
|
||||
wrong = client.post(
|
||||
"/login",
|
||||
data={"username": "wrong", "password": "wrong", "next": "/"},
|
||||
follow_redirects=False,
|
||||
)
|
||||
assert wrong.status_code == 401
|
||||
assert client.get("/", headers=TEST_AUTH_HEADERS).status_code == 200
|
||||
assert client.get("/api/status", headers=TEST_AUTH_HEADERS).status_code == 200
|
||||
assert client.get("/favicon.ico", headers=TEST_AUTH_HEADERS).status_code == 200
|
||||
assert client.get("/cv/", headers=TEST_AUTH_HEADERS).status_code == 200
|
||||
assert "username or password is incorrect" in wrong.text
|
||||
|
||||
signed_in = client.post(
|
||||
"/login",
|
||||
data={
|
||||
"username": TEST_USERNAME,
|
||||
"password": TEST_PASSWORD,
|
||||
"next": "https://attacker.example/steal",
|
||||
},
|
||||
follow_redirects=False,
|
||||
)
|
||||
assert signed_in.status_code == 303
|
||||
assert signed_in.headers["location"] == "/"
|
||||
assert "httponly" in signed_in.headers["set-cookie"].lower()
|
||||
assert "samesite=strict" in signed_in.headers["set-cookie"].lower()
|
||||
assert client.get("/").status_code == 200
|
||||
assert client.get("/api/status").status_code == 200
|
||||
assert client.get("/favicon.ico").status_code == 200
|
||||
assert client.get("/cv/").status_code == 200
|
||||
|
||||
signed_out = client.post("/logout", follow_redirects=False)
|
||||
assert signed_out.status_code == 303
|
||||
assert signed_out.headers["location"] == "/login"
|
||||
assert client.get("/api/status").status_code == 401
|
||||
|
||||
|
||||
def test_missing_authentication_configuration_fails_closed(
|
||||
@@ -416,9 +445,7 @@ def test_revision_chat_updates_tailored_outputs(tmp_path: Path) -> None:
|
||||
download = client.get("/api/download/resume-ohmycv.md")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.json()["package"]["changes_made"] == [
|
||||
"Made the summary more direct."
|
||||
]
|
||||
assert response.json()["package"]["changes_made"] == ["Made the summary more direct."]
|
||||
assert "Updated and re-audited" in response.json()["reply"]
|
||||
assert download.status_code == 200
|
||||
assert "[F013]" not in download.text
|
||||
|
||||
Reference in New Issue
Block a user