feat: event proposal and approval workflow #9
1 changed files with 49 additions and 58 deletions
refactor: consolidate create and propose endpoints into single POST /events
Some checks failed
lint.yml / refactor: consolidate create and propose endpoints into single POST /events (pull_request) Failing after 0s
Some checks failed
lint.yml / refactor: consolidate create and propose endpoints into single POST /events (pull_request) Failing after 0s
Remove separate /events/propose endpoint. POST /events now uses
invoice key (any user) and determines approval status based on:
- LNbits admin → auto-approved
- auto_approve setting → auto-approved
- Otherwise → proposed (requires admin approval)
Separate PUT /events/{id} for updates (admin key, event owner).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
commit
4d91426e82
81
views_api.py
81
views_api.py
|
|
@ -105,13 +105,45 @@ async def api_events_all(
|
||||||
|
|
||||||
|
|
||||||
@events_api_router.post("/api/v1/events")
|
@events_api_router.post("/api/v1/events")
|
||||||
@events_api_router.put("/api/v1/events/{event_id}")
|
|
||||||
async def api_event_create(
|
async def api_event_create(
|
||||||
data: CreateEvent,
|
data: CreateEvent,
|
||||||
wallet: WalletTypeInfo = Depends(require_admin_key),
|
wallet: WalletTypeInfo = Depends(require_invoice_key),
|
||||||
event_id: str | None = None,
|
|
||||||
):
|
):
|
||||||
if event_id:
|
"""
|
||||||
|
Create a new event. Any authenticated user can create events.
|
||||||
|
Admin-created events are auto-approved. Non-admin events require
|
||||||
|
approval unless auto_approve is enabled in extension settings.
|
||||||
|
"""
|
||||||
|
if not data.wallet:
|
||||||
|
data.wallet = wallet.wallet.id
|
||||||
|
|
||||||
|
from lnbits.settings import settings
|
||||||
|
|
||||||
|
ext_settings = await get_settings()
|
||||||
|
user_id = wallet.wallet.user
|
||||||
|
is_admin = (
|
||||||
|
user_id == settings.super_user
|
||||||
|
or user_id in settings.lnbits_admin_users
|
||||||
|
)
|
||||||
|
if not is_admin and not ext_settings.auto_approve:
|
||||||
|
data.status = "proposed"
|
||||||
|
|
||||||
|
event = await create_event(data)
|
||||||
|
|
||||||
|
# Publish to Nostr if approved
|
||||||
|
if event.status == "approved":
|
||||||
|
await _publish_or_delete_nostr_event(event)
|
||||||
|
|
||||||
|
return event.dict()
|
||||||
|
|
||||||
|
|
||||||
|
@events_api_router.put("/api/v1/events/{event_id}")
|
||||||
|
async def api_event_update(
|
||||||
|
event_id: str,
|
||||||
|
data: CreateEvent,
|
||||||
|
wallet: WalletTypeInfo = Depends(require_admin_key),
|
||||||
|
):
|
||||||
|
"""Update an existing event. Requires admin key (event owner)."""
|
||||||
event = await get_event(event_id)
|
event = await get_event(event_id)
|
||||||
if not event:
|
if not event:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -129,25 +161,6 @@ async def api_event_create(
|
||||||
# Republish to Nostr if event is approved (kind 31922 is replaceable)
|
# Republish to Nostr if event is approved (kind 31922 is replaceable)
|
||||||
if event.status == "approved" and event.nostr_event_id:
|
if event.status == "approved" and event.nostr_event_id:
|
||||||
await _publish_or_delete_nostr_event(event)
|
await _publish_or_delete_nostr_event(event)
|
||||||
else:
|
|
||||||
if not data.wallet:
|
|
||||||
data.wallet = wallet.wallet.id
|
|
||||||
# Check if approval is required for non-admin users
|
|
||||||
from lnbits.settings import settings
|
|
||||||
|
|
||||||
ext_settings = await get_settings()
|
|
||||||
user_id = wallet.wallet.user
|
|
||||||
is_admin = (
|
|
||||||
user_id == settings.super_user
|
|
||||||
or user_id in settings.lnbits_admin_users
|
|
||||||
)
|
|
||||||
if not is_admin and not ext_settings.auto_approve:
|
|
||||||
data.status = "proposed"
|
|
||||||
event = await create_event(data)
|
|
||||||
|
|
||||||
# Publish to Nostr if auto-approved (admin-created)
|
|
||||||
if event.status == "approved":
|
|
||||||
await _publish_or_delete_nostr_event(event)
|
|
||||||
|
|
||||||
return event.dict()
|
return event.dict()
|
||||||
|
|
||||||
|
|
@ -201,28 +214,6 @@ async def api_form_delete(
|
||||||
#########Event Approval##########
|
#########Event Approval##########
|
||||||
|
|
||||||
|
|
||||||
@events_api_router.post("/api/v1/events/propose")
|
|
||||||
async def api_event_propose(
|
|
||||||
data: CreateEvent,
|
|
||||||
wallet: WalletTypeInfo = Depends(require_invoice_key),
|
|
||||||
):
|
|
||||||
"""
|
|
||||||
Propose a new event for admin approval.
|
|
||||||
Requires invoice key (any authenticated user, not admin-only).
|
|
||||||
Auto-approved if the admin has enabled auto_approve in settings.
|
|
||||||
"""
|
|
||||||
ext_settings = await get_settings()
|
|
||||||
data.status = "approved" if ext_settings.auto_approve else "proposed"
|
|
||||||
data.wallet = wallet.wallet.id
|
|
||||||
event = await create_event(data)
|
|
||||||
|
|
||||||
# Publish to Nostr if auto-approved
|
|
||||||
if event.status == "approved":
|
|
||||||
await _publish_or_delete_nostr_event(event)
|
|
||||||
|
|
||||||
return event.dict()
|
|
||||||
|
|
||||||
|
|
||||||
@events_api_router.get("/api/v1/events/pending")
|
@events_api_router.get("/api/v1/events/pending")
|
||||||
async def api_events_pending(
|
async def api_events_pending(
|
||||||
admin: Account = Depends(check_admin),
|
admin: Account = Depends(check_admin),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue