feat: add cookie sessions and backend role authorization
This commit is contained in:
@@ -9,14 +9,35 @@ from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
|
||||
import httpx
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.models.auth import User
|
||||
from app.services.auth import PASSWORD_HASHER
|
||||
|
||||
|
||||
@contextmanager
|
||||
def server(engine):
|
||||
def server(engine, *, authenticate=True):
|
||||
with socket.socket() as socket_:
|
||||
socket_.bind(("127.0.0.1", 0))
|
||||
port = socket_.getsockname()[1]
|
||||
environment = {**os.environ, "DATABASE_URL": engine.url.render_as_string(hide_password=False)}
|
||||
environment = {
|
||||
**os.environ,
|
||||
"DATABASE_URL": engine.url.render_as_string(hide_password=False),
|
||||
"APP_ENV": "test",
|
||||
"AUTH_COOKIE_SECURE": "false",
|
||||
}
|
||||
if authenticate:
|
||||
with Session(engine) as db:
|
||||
if db.scalar(select(User.id).where(User.username == "http_admin")) is None:
|
||||
db.add(
|
||||
User(
|
||||
username="http_admin",
|
||||
password_hash=PASSWORD_HASHER.hash("test-password-123"),
|
||||
role="admin",
|
||||
)
|
||||
)
|
||||
db.commit()
|
||||
backend = Path(__file__).resolve().parents[1]
|
||||
process = subprocess.Popen(
|
||||
[
|
||||
@@ -38,6 +59,7 @@ def server(engine):
|
||||
)
|
||||
try:
|
||||
with httpx.Client(base_url=f"http://127.0.0.1:{port}", timeout=2) as client:
|
||||
client.headers["Origin"] = "http://localhost:5173"
|
||||
deadline = time.monotonic() + 15
|
||||
while time.monotonic() < deadline:
|
||||
if process.poll() is not None:
|
||||
@@ -50,6 +72,13 @@ def server(engine):
|
||||
time.sleep(0.05)
|
||||
else:
|
||||
raise AssertionError("默认后端未在时限内就绪")
|
||||
if authenticate:
|
||||
login = client.post(
|
||||
"/api/auth/login",
|
||||
json={"username": "http_admin", "password": "test-password-123"},
|
||||
)
|
||||
assert login.status_code == 200, login.text
|
||||
client.headers["X-CSRF-Token"] = login.json()["csrf_token"]
|
||||
yield client
|
||||
finally:
|
||||
process.terminate()
|
||||
@@ -107,3 +136,21 @@ def test_retrieval_run_persists_across_restart(migrated_database):
|
||||
assert run["results"][0]["knowledge_id"] == item["id"]
|
||||
with server(migrated_database) as client:
|
||||
assert client.get(f"/api/retrieval/runs/{run['run_id']}").json() == run
|
||||
|
||||
|
||||
def test_session_and_logout_survive_http_restart(migrated_database):
|
||||
from app.services.auth import COOKIE_NAME
|
||||
|
||||
with server(migrated_database, authenticate=False) as client:
|
||||
payload = {"username": "http_user", "password": "test-password-123"}
|
||||
assert client.post("/api/auth/register", json=payload).status_code == 201
|
||||
response = client.post("/api/auth/login", json=payload)
|
||||
cookie = client.cookies.get(COOKIE_NAME)
|
||||
token = response.json()["csrf_token"]
|
||||
with server(migrated_database, authenticate=False) as client:
|
||||
client.cookies.set(COOKIE_NAME, cookie)
|
||||
assert client.get("/api/auth/me").json()["username"] == "http_user"
|
||||
assert client.post("/api/auth/logout", headers={"X-CSRF-Token": token}).status_code == 204
|
||||
with server(migrated_database, authenticate=False) as client:
|
||||
client.cookies.set(COOKIE_NAME, cookie)
|
||||
assert client.get("/api/auth/me").status_code == 401
|
||||
|
||||
Reference in New Issue
Block a user