Files
2026-06-15 18:59:43 -04:00

177 lines
6.1 KiB
Python

from pathlib import Path
from fastapi.testclient import TestClient
from reyna_cli.web import WebSettings, create_app, normalize_args, RunRequest, run_web_server
from reyna_cli.tts import TTSError, _custom_tts
def test_web_health_without_auth_config():
app = create_app(
WebSettings(
auth_enabled=True,
dev_auth=False,
session_secret="",
authentik_issuer="https://auth.reynafamily.com/application/o/reyna-cli-web/",
client_id=None,
client_secret=None,
basic_user=None,
basic_password=None,
public_url=None,
command_timeout=5,
output_limit=1000,
workdir=Path.cwd(),
)
)
client = TestClient(app)
response = client.get("/healthz")
assert response.status_code == 200
assert response.json()["auth_enabled"] is True
assert response.json()["oidc_configured"] is False
def test_web_index_renders_with_dev_auth():
app = create_app(
WebSettings(
auth_enabled=True,
dev_auth=True,
session_secret="dev-secret",
authentik_issuer="https://auth.reynafamily.com/application/o/reyna-cli-web/",
client_id=None,
client_secret=None,
basic_user=None,
basic_password=None,
public_url=None,
command_timeout=5,
output_limit=1000,
workdir=Path.cwd(),
)
)
client = TestClient(app)
response = client.get("/")
assert response.status_code == 200
assert "Reyna CLI Web" in response.text
assert "doctor --json" in response.text
def test_web_refuses_dev_auth_on_lan_bind(monkeypatch, tmp_path):
monkeypatch.setenv("HERMES_ENV_PATH", str(tmp_path / "missing.env"))
monkeypatch.setenv("REYNA_WEB_DEV_AUTH", "1")
monkeypatch.delenv("REYNA_WEB_ALLOW_INSECURE_LAN", raising=False)
try:
run_web_server(host="0.0.0.0", port=8765)
except SystemExit as exc:
assert "Refusing to run" in str(exc)
else:
raise AssertionError("LAN dev-auth server was allowed")
def test_web_refuses_lan_bind_without_oidc_config(monkeypatch, tmp_path):
monkeypatch.setenv("HERMES_ENV_PATH", str(tmp_path / "missing.env"))
monkeypatch.delenv("REYNA_WEB_DEV_AUTH", raising=False)
monkeypatch.delenv("REYNA_WEB_AUTH_CLIENT_ID", raising=False)
monkeypatch.delenv("REYNA_WEB_AUTH_CLIENT_SECRET", raising=False)
monkeypatch.delenv("REYNA_WEB_BASIC_USER", raising=False)
monkeypatch.delenv("REYNA_WEB_BASIC_PASSWORD", raising=False)
monkeypatch.delenv("REYNA_WEB_SESSION_SECRET", raising=False)
try:
run_web_server(host="0.0.0.0", port=8765)
except SystemExit as exc:
assert "without configured authentication" in str(exc)
else:
raise AssertionError("LAN server without OIDC config was allowed")
def test_web_basic_auth_protects_index():
app = create_app(
WebSettings(
auth_enabled=True,
dev_auth=False,
session_secret="basic-secret",
authentik_issuer="https://auth.reynafamily.com/application/o/reyna-cli-web/",
client_id=None,
client_secret=None,
basic_user="adolfo",
basic_password="correct-password",
public_url=None,
command_timeout=5,
output_limit=1000,
workdir=Path.cwd(),
)
)
client = TestClient(app)
unauthenticated = client.get("/")
assert unauthenticated.status_code == 401
assert unauthenticated.headers["www-authenticate"] == 'Basic realm="Reyna CLI Web"'
authenticated = client.get("/", auth=("adolfo", "correct-password"))
assert authenticated.status_code == 200
assert "HTTP Basic auth" in authenticated.text
def test_web_allows_lan_bind_with_basic_auth(monkeypatch, tmp_path):
monkeypatch.setenv("HERMES_ENV_PATH", str(tmp_path / "missing.env"))
called = {}
def fake_run(app_path, host, port, reload):
called.update({"app_path": app_path, "host": host, "port": port, "reload": reload})
monkeypatch.delenv("REYNA_WEB_DEV_AUTH", raising=False)
monkeypatch.delenv("REYNA_WEB_AUTH_CLIENT_ID", raising=False)
monkeypatch.delenv("REYNA_WEB_AUTH_CLIENT_SECRET", raising=False)
monkeypatch.setenv("REYNA_WEB_BASIC_USER", "adolfo")
monkeypatch.setenv("REYNA_WEB_BASIC_PASSWORD", "correct-password")
monkeypatch.setattr("uvicorn.run", fake_run)
run_web_server(host="0.0.0.0", port=8765)
assert called["host"] == "0.0.0.0"
def test_web_api_run_uses_argument_vector(monkeypatch):
app = create_app(
WebSettings(
auth_enabled=False,
dev_auth=False,
session_secret="dev-secret",
authentik_issuer="https://auth.reynafamily.com/application/o/reyna-cli-web/",
client_id=None,
client_secret=None,
basic_user=None,
basic_password=None,
public_url=None,
command_timeout=5,
output_limit=1000,
workdir=Path.cwd(),
)
)
def fake_run(args, settings):
return {"ok": True, "args": args, "exit_code": 0, "stdout": "done", "stderr": ""}
monkeypatch.setattr("reyna_cli.web.run_reyna_cli", fake_run)
client = TestClient(app)
response = client.post("/api/run", json={"command": "doctor --json"})
assert response.status_code == 200
payload = response.json()
assert payload["ok"] is True
assert payload["args"] == ["doctor", "--json"]
assert payload["stdout"] == "done"
def test_normalize_args_refuses_nested_server():
try:
normalize_args(RunRequest(command="--help web"))
except Exception as exc:
assert getattr(exc, "status_code", None) == 400
else:
raise AssertionError("nested web command was not rejected")
def test_custom_tts_rejects_raw_text_placeholder(tmp_path):
try:
_custom_tts("hello", tmp_path / "audio", "printf {raw_text}", None)
except TTSError as exc:
assert "raw_text" in str(exc)
else:
raise AssertionError("raw_text placeholder was not rejected")