Enhances super user experience with Castle wallet

Simplifies the user experience for super users by automatically using the Castle wallet for transactions, removing the need to configure a separate user wallet.

This change streamlines the workflow for super users by:
- Automatically assigning the Castle wallet to super users
- Hiding the user wallet configuration options in the UI
- Reloading user wallet settings to reflect the Castle wallet
This commit is contained in:
padreug 2025-10-22 15:11:00 +02:00
parent f1ada5e290
commit cb7e4ee555
3 changed files with 57 additions and 14 deletions

View file

@ -176,6 +176,10 @@ window.app = Vue.createApp({
}) })
this.settingsDialog.show = false this.settingsDialog.show = false
await this.loadSettings() await this.loadSettings()
// Reload user wallet to reflect castle wallet for super user
if (this.isSuperUser) {
await this.loadUserWallet()
}
} catch (error) { } catch (error) {
LNbits.utils.notifyApiError(error) LNbits.utils.notifyApiError(error)
} finally { } finally {

View file

@ -17,7 +17,7 @@
<p class="q-mb-none">Track expenses, receivables, and balances for the collective</p> <p class="q-mb-none">Track expenses, receivables, and balances for the collective</p>
</div> </div>
<div class="col-auto"> <div class="col-auto">
<q-btn flat round icon="account_balance_wallet" @click="showUserWalletDialog"> <q-btn v-if="!isSuperUser" flat round icon="account_balance_wallet" @click="showUserWalletDialog">
<q-tooltip>Configure Your Wallet</q-tooltip> <q-tooltip>Configure Your Wallet</q-tooltip>
</q-btn> </q-btn>
<q-btn v-if="isSuperUser" flat round icon="settings" @click="showSettingsDialog"> <q-btn v-if="isSuperUser" flat round icon="settings" @click="showSettingsDialog">
@ -50,7 +50,7 @@
</div> </div>
</q-banner> </q-banner>
<q-banner v-if="castleWalletConfigured && !userWalletConfigured" class="bg-orange text-white" rounded> <q-banner v-if="castleWalletConfigured && !userWalletConfigured && !isSuperUser" class="bg-orange text-white" rounded>
<template v-slot:avatar> <template v-slot:avatar>
<q-icon name="account_balance_wallet" color="white"></q-icon> <q-icon name="account_balance_wallet" color="white"></q-icon>
</template> </template>
@ -106,13 +106,13 @@
<q-btn <q-btn
color="primary" color="primary"
@click="expenseDialog.show = true" @click="expenseDialog.show = true"
:disable="!castleWalletConfigured || !userWalletConfigured" :disable="!castleWalletConfigured || (!userWalletConfigured && !isSuperUser)"
> >
Add Expense Add Expense
<q-tooltip v-if="!castleWalletConfigured"> <q-tooltip v-if="!castleWalletConfigured">
Castle wallet must be configured first Castle wallet must be configured first
</q-tooltip> </q-tooltip>
<q-tooltip v-if="castleWalletConfigured && !userWalletConfigured"> <q-tooltip v-if="castleWalletConfigured && !userWalletConfigured && !isSuperUser">
You must configure your wallet first You must configure your wallet first
</q-tooltip> </q-tooltip>
</q-btn> </q-btn>
@ -344,20 +344,27 @@
<q-form @submit="submitUserWallet" class="q-gutter-md"> <q-form @submit="submitUserWallet" class="q-gutter-md">
<div class="text-h6 q-mb-md">Configure Your Wallet</div> <div class="text-h6 q-mb-md">Configure Your Wallet</div>
<q-input <q-select
filled filled
dense dense
v-model.trim="userWalletDialog.userWalletId" emit-value
label="Your Wallet ID *" v-model="userWalletDialog.userWalletId"
placeholder="Enter your wallet ID" :options="g.user.walletOptions"
></q-input> label="Your Wallet *"
></q-select>
<div class="text-caption text-grey"> <div class="text-caption text-grey">
This is the wallet you'll use for Castle transactions. You can find your wallet ID in the LNbits wallet settings. Select the wallet you'll use for Castle transactions.
</div> </div>
<div class="row q-mt-lg"> <div class="row q-mt-lg">
<q-btn unelevated color="primary" type="submit" :loading="userWalletDialog.loading"> <q-btn
unelevated
color="primary"
type="submit"
:loading="userWalletDialog.loading"
:disable="!userWalletDialog.userWalletId"
>
Save Wallet Save Wallet
</q-btn> </q-btn>
<q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn> <q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn>

View file

@ -59,13 +59,26 @@ async def check_castle_wallet_configured() -> str:
async def check_user_wallet_configured(user_id: str) -> str: async def check_user_wallet_configured(user_id: str) -> str:
"""Ensure user has configured their wallet, return wallet_id""" """Ensure user has configured their wallet, return wallet_id"""
settings = await get_user_wallet(user_id) from lnbits.settings import settings as lnbits_settings
if not settings or not settings.user_wallet_id:
# If user is super user, use the castle wallet
if user_id == lnbits_settings.super_user:
castle_settings = await get_settings("admin")
if castle_settings and castle_settings.castle_wallet_id:
return castle_settings.castle_wallet_id
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail="Castle wallet not configured. Please configure the Castle wallet in settings.",
)
# For regular users, check their personal wallet
user_wallet = await get_user_wallet(user_id)
if not user_wallet or not user_wallet.user_wallet_id:
raise HTTPException( raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST, status_code=HTTPStatus.BAD_REQUEST,
detail="You must configure your wallet in settings before using this feature.", detail="You must configure your wallet in settings before using this feature.",
) )
return settings.user_wallet_id return user_wallet.user_wallet_id
# ===== UTILITY ENDPOINTS ===== # ===== UTILITY ENDPOINTS =====
@ -529,6 +542,16 @@ async def api_get_user_wallet(
user: User = Depends(check_user_exists), user: User = Depends(check_user_exists),
) -> UserWalletSettings: ) -> UserWalletSettings:
"""Get current user's wallet settings""" """Get current user's wallet settings"""
from lnbits.settings import settings as lnbits_settings
# If user is super user, return the castle wallet
if user.id == lnbits_settings.super_user:
castle_settings = await get_settings("admin")
if castle_settings and castle_settings.castle_wallet_id:
return UserWalletSettings(user_wallet_id=castle_settings.castle_wallet_id)
return UserWalletSettings()
# For regular users, get their personal wallet
settings = await get_user_wallet(user.id) settings = await get_user_wallet(user.id)
# Return empty settings if not configured (so UI can show setup screen) # Return empty settings if not configured (so UI can show setup screen)
if not settings: if not settings:
@ -542,6 +565,15 @@ async def api_update_user_wallet(
user: User = Depends(check_user_exists), user: User = Depends(check_user_exists),
) -> UserWalletSettings: ) -> UserWalletSettings:
"""Update current user's wallet settings""" """Update current user's wallet settings"""
from lnbits.settings import settings as lnbits_settings
# Super user cannot set their wallet separately - it's always the castle wallet
if user.id == lnbits_settings.super_user:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN,
detail="Super user wallet is automatically set to the Castle wallet. Update Castle settings instead.",
)
if not data.user_wallet_id: if not data.user_wallet_id:
raise HTTPException( raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST, status_code=HTTPStatus.BAD_REQUEST,