From c1e66fbf7fd15f10b682033695bbac013b5c16dd Mon Sep 17 00:00:00 2001 From: Padreug Date: Mon, 27 Apr 2026 11:27:21 +0200 Subject: [PATCH] fix: use check_admin for approval endpoints, not require_admin_key require_admin_key only checks that the API key is a wallet admin key, which ANY user has. check_admin verifies the user is a LNbits admin (super_user or lnbits_admin_users). JS updated to omit API key on admin endpoints, relying on session cookie auth instead. Co-Authored-By: Claude Opus 4.6 (1M context) --- static/js/index.js | 12 ++++-------- views_api.py | 19 ++++++++++--------- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/static/js/index.js b/static/js/index.js index 458c29e..b3b6ba3 100644 --- a/static/js/index.js +++ b/static/js/index.js @@ -122,8 +122,7 @@ window.app = Vue.createApp({ LNbits.api .request( 'PUT', - '/events/api/v1/events/' + eventId + '/approve', - this.g.user.wallets[0].adminkey + '/events/api/v1/events/' + eventId + '/approve' ) .then(() => { this.$q.notify({ @@ -145,8 +144,7 @@ window.app = Vue.createApp({ LNbits.api .request( 'PUT', - '/events/api/v1/events/' + eventId + '/reject', - this.g.user.wallets[0].adminkey + '/events/api/v1/events/' + eventId + '/reject' ) .then(() => { this.$q.notify({ @@ -207,8 +205,7 @@ window.app = Vue.createApp({ LNbits.api .request( 'GET', - '/events/api/v1/events/all', - this.g.user.wallets[0].adminkey + '/events/api/v1/events/all' ) .then(response => { this.events = response.data.map(obj => { @@ -236,8 +233,7 @@ window.app = Vue.createApp({ LNbits.api .request( 'GET', - '/events/api/v1/events/pending', - this.g.user.wallets[0].adminkey + '/events/api/v1/events/pending' ) .then(response => { this.pendingEvents = response.data.map(obj => { diff --git a/views_api.py b/views_api.py index b363009..e9977d4 100644 --- a/views_api.py +++ b/views_api.py @@ -3,9 +3,10 @@ from http import HTTPStatus from fastapi import APIRouter, Depends, Query from lnbits.core.crud import get_standalone_payment, get_user -from lnbits.core.models import WalletTypeInfo +from lnbits.core.models import Account, WalletTypeInfo from lnbits.core.services import create_invoice from lnbits.decorators import ( + check_admin, require_admin_key, require_invoice_key, ) @@ -65,9 +66,9 @@ async def api_events_public(): @events_api_router.get("/api/v1/events/all") async def api_events_all( - wallet: WalletTypeInfo = Depends(require_admin_key), + admin: Account = Depends(check_admin), ): - """Get all events across all wallets. Admin only.""" + """Get all events across all wallets. LNbits admin only.""" from .crud import get_all_events events = await get_all_events() @@ -161,9 +162,9 @@ async def api_event_propose( @events_api_router.get("/api/v1/events/pending") async def api_events_pending( - wallet: WalletTypeInfo = Depends(require_admin_key), + admin: Account = Depends(check_admin), ): - """Get all proposed events awaiting approval. Admin only.""" + """Get all proposed events awaiting approval. LNbits admin only.""" events = await get_pending_events() return [event.dict() for event in events] @@ -171,9 +172,9 @@ async def api_events_pending( @events_api_router.put("/api/v1/events/{event_id}/approve") async def api_event_approve( event_id: str, - wallet: WalletTypeInfo = Depends(require_admin_key), + admin: Account = Depends(check_admin), ): - """Approve a proposed event. Admin only.""" + """Approve a proposed event. LNbits admin only.""" event = await get_event(event_id) if not event: raise HTTPException( @@ -192,9 +193,9 @@ async def api_event_approve( @events_api_router.put("/api/v1/events/{event_id}/reject") async def api_event_reject( event_id: str, - wallet: WalletTypeInfo = Depends(require_admin_key), + admin: Account = Depends(check_admin), ): - """Reject a proposed event. Admin only.""" + """Reject a proposed event. LNbits admin only.""" event = await get_event(event_id) if not event: raise HTTPException(