|
3 | 3 | from types import SimpleNamespace |
4 | 4 | from unittest.mock import AsyncMock |
5 | 5 |
|
| 6 | +import httpx |
6 | 7 | import pytest |
7 | | -from fastapi import Request |
8 | | -from lnbits.core.models import User |
| 8 | +from fastapi import FastAPI, Request |
| 9 | +from fastapi.responses import JSONResponse |
| 10 | +from lnbits.core.models import Account, User |
| 11 | +from lnbits.decorators import check_account_exists, check_user_exists |
| 12 | +from lnbits.settings import settings |
9 | 13 |
|
10 | 14 | from .. import views |
11 | 15 | from ..models import ExtensionSettings, PaymentsFilters, ProxiesFilters |
@@ -38,3 +42,36 @@ async def test_frontend_serializes_user_for_template(monkeypatch): |
38 | 42 | context = await views.index(request, user) |
39 | 43 | assert json.loads(context["user"])["id"] == user.id |
40 | 44 | assert User.model_validate_json(context["user"]).created_at == now |
| 45 | + |
| 46 | + |
| 47 | +@pytest.mark.asyncio |
| 48 | +@pytest.mark.parametrize("is_super_user", [True, False]) |
| 49 | +async def test_page_dependencies_supply_full_user_and_enforce_superuser(monkeypatch, is_super_user): |
| 50 | + monkeypatch.setattr(settings, "super_user", "owner") |
| 51 | + monkeypatch.setattr(settings, "lnbits_admin_users", []) |
| 52 | + account = Account(id="owner" if is_super_user else "other", password_hash="test-only") |
| 53 | + user = User(id=account.id, super_user=is_super_user, created_at=account.created_at, updated_at=account.updated_at) |
| 54 | + app = FastAPI() |
| 55 | + app.include_router(views.reverse_proxy_generic_router) |
| 56 | + # Preserve the real superuser guard, including its Account return type. |
| 57 | + app.dependency_overrides[check_account_exists] = lambda: account |
| 58 | + app.dependency_overrides[check_user_exists] = lambda: user |
| 59 | + renderer = SimpleNamespace(TemplateResponse=lambda name, context: JSONResponse(json.loads(context["user"]))) |
| 60 | + monkeypatch.setattr(views, "reverse_proxy_renderer", lambda: renderer) |
| 61 | + monkeypatch.setattr(views, "get_settings", AsyncMock(return_value=ExtensionSettings())) |
| 62 | + cleanup = AsyncMock() |
| 63 | + monkeypatch.setattr(views, "cleanup_expired_proxies_and_sync_caddy", cleanup) |
| 64 | + |
| 65 | + async with httpx.AsyncClient(transport=httpx.ASGITransport(app=app), base_url="http://test") as client: |
| 66 | + response = await client.get("/") |
| 67 | + |
| 68 | + if not is_super_user: |
| 69 | + assert response.status_code == 403 |
| 70 | + cleanup.assert_not_awaited() |
| 71 | + return |
| 72 | + assert response.status_code == 200 |
| 73 | + payload = response.json() |
| 74 | + assert payload["wallets"] == [] |
| 75 | + assert payload["extensions"] == [] |
| 76 | + assert payload["super_user"] is True |
| 77 | + assert "password_hash" not in payload |
0 commit comments