fix(auth): persist sessions and lock remote setup
This commit is contained in:
@@ -7,7 +7,6 @@ Revises: 0001_v2_baseline
|
|||||||
from collections.abc import Sequence
|
from collections.abc import Sequence
|
||||||
|
|
||||||
import sqlalchemy as sa
|
import sqlalchemy as sa
|
||||||
|
|
||||||
from alembic import op
|
from alembic import op
|
||||||
|
|
||||||
revision: str = "0002_sessions"
|
revision: str = "0002_sessions"
|
||||||
|
|||||||
+2
-2
@@ -31,7 +31,7 @@ def make_settings(tmp_path: Path) -> Any:
|
|||||||
local_source_roots=(sources,),
|
local_source_roots=(sources,),
|
||||||
restore_roots=(restores,),
|
restore_roots=(restores,),
|
||||||
master_key_file=key,
|
master_key_file=key,
|
||||||
public_base_url="https://testserver",
|
public_base_url="https://127.0.0.1:8000",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ async def app_client(tmp_path: Path) -> AsyncIterator[tuple[AsyncClient, Any]]:
|
|||||||
app_module = importlib.import_module("backup_tool.api.app")
|
app_module = importlib.import_module("backup_tool.api.app")
|
||||||
app = app_module.create_app(settings)
|
app = app_module.create_app(settings)
|
||||||
async with AsyncClient(
|
async with AsyncClient(
|
||||||
transport=ASGITransport(app=app), base_url="https://testserver"
|
transport=ASGITransport(app=app), base_url="https://127.0.0.1:8000"
|
||||||
) as client:
|
) as client:
|
||||||
yield client, settings
|
yield client, settings
|
||||||
await app.state.engine.dispose()
|
await app.state.engine.dispose()
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ EXPECTED_TABLES = {
|
|||||||
"restores",
|
"restores",
|
||||||
"schedules",
|
"schedules",
|
||||||
"secrets",
|
"secrets",
|
||||||
|
"sessions",
|
||||||
"sources",
|
"sources",
|
||||||
"users",
|
"users",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,8 +80,12 @@ async def test_remote_setup_without_configured_bootstrap_fails_closed(tmp_path)
|
|||||||
)
|
)
|
||||||
command.upgrade(cli.build_alembic_config(settings), "head")
|
command.upgrade(cli.build_alembic_config(settings), "head")
|
||||||
app = app_module.create_app(settings)
|
app = app_module.create_app(settings)
|
||||||
async with AsyncClient(transport=ASGITransport(app=app), base_url=settings.public_base_url) as client:
|
async with AsyncClient(
|
||||||
response = await client.post("/api/v2/setup", json={"username": "admin", "password": PASSWORD})
|
transport=ASGITransport(app=app), base_url=settings.public_base_url
|
||||||
|
) as client:
|
||||||
|
response = await client.post(
|
||||||
|
"/api/v2/setup", json={"username": "admin", "password": PASSWORD}
|
||||||
|
)
|
||||||
assert response.status_code == 403
|
assert response.status_code == 403
|
||||||
assert response.json()["code"] == "bootstrap_required"
|
assert response.json()["code"] == "bootstrap_required"
|
||||||
await app.state.engine.dispose()
|
await app.state.engine.dispose()
|
||||||
@@ -122,10 +126,13 @@ async def test_logout_revocation_survives_app_restart(tmp_path) -> None:
|
|||||||
local_source_roots=(roots[2],),
|
local_source_roots=(roots[2],),
|
||||||
restore_roots=(roots[3],),
|
restore_roots=(roots[3],),
|
||||||
master_key_file=key,
|
master_key_file=key,
|
||||||
|
public_base_url="https://127.0.0.1:8000",
|
||||||
)
|
)
|
||||||
command.upgrade(cli.build_alembic_config(settings), "head")
|
command.upgrade(cli.build_alembic_config(settings), "head")
|
||||||
app = app_module.create_app(settings)
|
app = app_module.create_app(settings)
|
||||||
async with AsyncClient(transport=ASGITransport(app=app), base_url=settings.public_base_url) as client:
|
async with AsyncClient(
|
||||||
|
transport=ASGITransport(app=app), base_url=settings.public_base_url
|
||||||
|
) as client:
|
||||||
setup = await client.post("/api/v2/setup", json={"username": "admin", "password": PASSWORD})
|
setup = await client.post("/api/v2/setup", json={"username": "admin", "password": PASSWORD})
|
||||||
assert setup.status_code == 201
|
assert setup.status_code == 201
|
||||||
copied_cookie = client.cookies.get("backup_tool_session")
|
copied_cookie = client.cookies.get("backup_tool_session")
|
||||||
@@ -137,7 +144,11 @@ async def test_logout_revocation_survives_app_restart(tmp_path) -> None:
|
|||||||
await app.state.engine.dispose()
|
await app.state.engine.dispose()
|
||||||
|
|
||||||
restarted = app_module.create_app(settings)
|
restarted = app_module.create_app(settings)
|
||||||
async with AsyncClient(transport=ASGITransport(restarted), base_url=settings.public_base_url) as client:
|
async with AsyncClient(
|
||||||
rejected = await client.get("/api/v2/auth/session", headers={"Cookie": f"backup_tool_session={copied_cookie}"})
|
transport=ASGITransport(restarted), base_url=settings.public_base_url
|
||||||
|
) as client:
|
||||||
|
rejected = await client.get(
|
||||||
|
"/api/v2/auth/session", headers={"Cookie": f"backup_tool_session={copied_cookie}"}
|
||||||
|
)
|
||||||
assert rejected.status_code == 401
|
assert rejected.status_code == 401
|
||||||
await restarted.state.engine.dispose()
|
await restarted.state.engine.dispose()
|
||||||
|
|||||||
Reference in New Issue
Block a user