38 lines
1.6 KiB
Python
38 lines
1.6 KiB
Python
from __future__ import annotations
|
|
|
|
import importlib
|
|
from datetime import UTC, datetime, timedelta
|
|
|
|
import pytest
|
|
|
|
PASSWORD = "correct horse battery staple"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_remote_setup_requires_bootstrap_secret(tmp_path) -> None:
|
|
conftest = importlib.import_module("conftest")
|
|
app_module = importlib.import_module("backup_tool.api.app")
|
|
settings = conftest.make_settings(tmp_path).model_copy(
|
|
update={"public_base_url": "https://backup.example.test", "bootstrap_secret": "bootstrap"}
|
|
)
|
|
cli = importlib.import_module("backup_tool.cli")
|
|
from alembic import command
|
|
from httpx import ASGITransport, AsyncClient
|
|
|
|
command.upgrade(cli.build_alembic_config(settings), "head")
|
|
app = app_module.create_app(settings)
|
|
async with AsyncClient(transport=ASGITransport(app=app), base_url="https://backup.example.test") as client:
|
|
denied = await client.post("/api/v2/setup", json={"username": "admin", "password": PASSWORD})
|
|
assert denied.status_code == 403
|
|
accepted = await client.post("/api/v2/setup", json={"username": "admin", "password": PASSWORD, "bootstrap_secret": "bootstrap"})
|
|
assert accepted.status_code == 201
|
|
await app.state.engine.dispose()
|
|
|
|
|
|
def test_expired_session_is_rejected(tmp_path) -> None:
|
|
auth = importlib.import_module("backup_tool.security.auth")
|
|
key = tmp_path / "master.key"
|
|
key.write_bytes(b"x" * 32)
|
|
expired = auth.sign_session("user", "csrf", key, expires_at=datetime.now(UTC) - timedelta(seconds=1), session_id="session")
|
|
assert auth.verify_session(expired, key) is None
|