From 8edbd2b8947622feb549012da5ee00644a5cbea2 Mon Sep 17 00:00:00 2001 From: Arc Date: Mon, 13 Jul 2026 13:29:17 +0100 Subject: [PATCH] Revert "make simpler" This reverts commit 0c60ad4f3b0591275de56f75a68e23c6dccf7b28. --- lnbits/core/wasm_ext/api/host.py | 16 +++++-- lnbits/core/wasm_ext/wasm/invoke.py | 1 + tests/unit/test_wasm_extension_host_wallet.py | 48 +++++++++++++++++++ 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/lnbits/core/wasm_ext/api/host.py b/lnbits/core/wasm_ext/api/host.py index 367fe8c8a..e3f208956 100644 --- a/lnbits/core/wasm_ext/api/host.py +++ b/lnbits/core/wasm_ext/api/host.py @@ -65,6 +65,7 @@ class ExtensionHostAPI: access_token: str | None = None, context: str = "user", owner_id: str | None = None, + wallet_id: str | None = None, invocation_id: str | None = None, runtime_limits: dict[str, int] | None = None, ) -> None: @@ -74,6 +75,7 @@ class ExtensionHostAPI: self.access_token = access_token self.context = context self.owner_id = sha256s(user_id) if user_id else owner_id + self.wallet_id = wallet_id self.invocation_id = invocation_id self.runtime_limits = runtime_limits or {} from .utils import ExtensionAPIUtils @@ -379,15 +381,19 @@ class ExtensionHostAPI: from lnbits.core.services.payments import pay_invoice from lnbits.exceptions import PaymentError - if not self.user_id: + wallet = await get_wallet(request.wallet_id) + if wallet is None: + raise PermissionError("Paying invoices from this wallet is not allowed.") + if self.user_id: + if wallet.user != self.user_id: + raise PermissionError( + "Paying invoices from this wallet is not allowed." + ) + elif not (self.context == "event" and request.wallet_id == self.wallet_id): raise PermissionError( "Paying an invoice requires an authenticated user context." ) - wallet = await get_wallet(request.wallet_id) - if wallet is None or wallet.user != self.user_id: - raise PermissionError("Paying invoices from this wallet is not allowed.") - try: payment_request = request.payment_request if _looks_like_lnurl_pay_target(payment_request): diff --git a/lnbits/core/wasm_ext/wasm/invoke.py b/lnbits/core/wasm_ext/wasm/invoke.py index a13c968be..01c1c405f 100644 --- a/lnbits/core/wasm_ext/wasm/invoke.py +++ b/lnbits/core/wasm_ext/wasm/invoke.py @@ -83,6 +83,7 @@ async def invoke_wasm_extension_export( access_token=access_token, context=context, owner_id=owner_id, + wallet_id=wallet_id, invocation_id=invocation.id, runtime_limits=limits, ) diff --git a/tests/unit/test_wasm_extension_host_wallet.py b/tests/unit/test_wasm_extension_host_wallet.py index 4ab30ee50..00ad078ea 100644 --- a/tests/unit/test_wasm_extension_host_wallet.py +++ b/tests/unit/test_wasm_extension_host_wallet.py @@ -50,3 +50,51 @@ async def test_wasm_wallet_pay_invoice_resolves_ln_address(mocker): assert calls["lnurl"] == ("alice@example.com", 21_000, "winner") assert calls["pay_invoice"]["payment_request"] == "lnbc1resolved" assert calls["pay_invoice"]["max_sat"] == 21 + + +@pytest.mark.anyio +async def test_wasm_wallet_pay_invoice_allows_event_wallet_only(mocker): + async def get_wallet(wallet_id: str): + return SimpleNamespace(user="other-user") + + async def pay_invoice(**kwargs): + return SimpleNamespace( + checking_id="checking", + payment_hash="hash", + status="success", + amount=-1_000, + fee=0, + pending=False, + success=True, + ) + + mocker.patch("lnbits.core.crud.wallets.get_wallet", get_wallet) + mocker.patch("lnbits.core.services.payments.pay_invoice", pay_invoice) + + api = ExtensionHostAPI( + "demoext", + ["wallet.pay_invoice"], + context="event", + owner_id="owner", + wallet_id="wallet1", + ) + allowed = await api.wallet_pay_invoice( + PayInvoiceRequest( + wallet_id="wallet1", + payment_request="lnbc1invoice", + max_sat=None, + description="", + ) + ) + + assert allowed.ok is True + + with pytest.raises(PermissionError, match="authenticated user context"): + await api.wallet_pay_invoice( + PayInvoiceRequest( + wallet_id="wallet2", + payment_request="lnbc1invoice", + max_sat=None, + description="", + ) + )