diff --git a/lnbits/core/crud.py b/lnbits/core/crud.py
index 99e61a4d5..217998059 100644
--- a/lnbits/core/crud.py
+++ b/lnbits/core/crud.py
@@ -246,7 +246,7 @@ async def get_user(
else:
account = account_or_id
extensions = await get_user_active_extensions_ids(account.id, conn)
- wallets = await get_wallets(account.id, conn)
+ wallets = await get_wallets(account.id, False, conn=conn)
return User(
id=account.id,
email=account.email,
@@ -524,27 +524,33 @@ async def delete_unused_wallets(
async def get_wallet(
- wallet_id: str, conn: Optional[Connection] = None
+ wallet_id: str, deleted: Optional[bool] = None, conn: Optional[Connection] = None
) -> Optional[Wallet]:
+ where = "AND deleted = :deleted" if deleted is not None else ""
return await (conn or db).fetchone(
- """
+ f"""
SELECT *, COALESCE((
SELECT balance FROM balances WHERE wallet_id = wallets.id
- ), 0) AS balance_msat FROM wallets WHERE id = :wallet
+ ), 0) AS balance_msat FROM wallets
+ WHERE id = :wallet {where}
""",
- {"wallet": wallet_id},
+ {"wallet": wallet_id, "deleted": deleted},
Wallet,
)
-async def get_wallets(user_id: str, conn: Optional[Connection] = None) -> list[Wallet]:
+async def get_wallets(
+ user_id: str, deleted: Optional[bool] = None, conn: Optional[Connection] = None
+) -> list[Wallet]:
+ where = "AND deleted = :deleted" if deleted is not None else ""
return await (conn or db).fetchall(
- """
+ f"""
SELECT *, COALESCE((
SELECT balance FROM balances WHERE wallet_id = wallets.id
- ), 0) AS balance_msat FROM wallets WHERE "user" = :user
+ ), 0) AS balance_msat FROM wallets
+ WHERE "user" = :user {where}
""",
- {"user": user_id},
+ {"user": user_id, "deleted": deleted},
Wallet,
)
diff --git a/lnbits/core/templates/users/_walletDialog.html b/lnbits/core/templates/users/_walletDialog.html
index 527285d88..1ff7a7497 100644
--- a/lnbits/core/templates/users/_walletDialog.html
+++ b/lnbits/core/templates/users/_walletDialog.html
@@ -37,6 +37,7 @@
icon="content_copy"
size="sm"
color="primary"
+ class="q-ml-xs"
@click="copyText(props.row.id)"
>
Copy Wallet ID
@@ -45,6 +46,7 @@
v-if="!props.row.deleted"
:wallet_id="props.row.id"
:callback="topupCallback"
+ class="q-ml-xs"
>
Copy Admin Key
@@ -62,6 +65,7 @@
icon="vpn_key"
size="sm"
color="secondary"
+ class="q-ml-xs"
@click="copyText(props.row.inkey)"
>
Copy Invoice Key
@@ -72,6 +76,7 @@
icon="toggle_off"
size="sm"
color="secondary"
+ class="q-ml-xs"
@click="undeleteUserWallet(props.row.user, props.row.id)"
>
Undelete Wallet
@@ -81,6 +86,7 @@
icon="delete"
size="sm"
color="negative"
+ class="q-ml-xs"
@click="deleteUserWallet(props.row.user, props.row.id, props.row.deleted)"
>
Delete Wallet
diff --git a/lnbits/core/templates/users/index.html b/lnbits/core/templates/users/index.html
index d524b2646..ef0239448 100644
--- a/lnbits/core/templates/users/index.html
+++ b/lnbits/core/templates/users/index.html
@@ -61,6 +61,7 @@ include "users/_createWalletDialog.html" %}
icon="content_copy"
size="sm"
color="primary"
+ class="q-ml-xs"
@click="copyText(props.row.id)"
>
Copy User ID
@@ -71,6 +72,7 @@ include "users/_createWalletDialog.html" %}
icon="build"
size="sm"
:color="props.row.is_admin ? 'primary' : 'grey'"
+ class="q-ml-xs"
@click="toggleAdmin(props.row.id)"
>
Toggle Admin
@@ -81,6 +83,7 @@ include "users/_createWalletDialog.html" %}
icon="build"
size="sm"
color="positive"
+ class="q-ml-xs"
>
Super User
@@ -98,6 +101,7 @@ include "users/_createWalletDialog.html" %}
icon="delete"
size="sm"
color="negative"
+ class="q-ml-xs"
@click="deleteUser(props.row.id, props)"
>
Delete User
@@ -111,7 +115,10 @@ include "users/_createWalletDialog.html" %}
-
+
diff --git a/lnbits/core/views/extension_api.py b/lnbits/core/views/extension_api.py
index f5d939722..f41ea89f9 100644
--- a/lnbits/core/views/extension_api.py
+++ b/lnbits/core/views/extension_api.py
@@ -113,33 +113,28 @@ async def api_install_extension(data: CreateExtension):
) from exc
-@extension_router.get("/{ext_id}/details", dependencies=[Depends(check_user_exists)])
+@extension_router.get("/{ext_id}/details")
async def api_extension_details(
ext_id: str,
details_link: str,
):
+ all_releases = await InstallableExtension.get_extension_releases(ext_id)
- try:
- all_releases = await InstallableExtension.get_extension_releases(ext_id)
-
- release = next(
- (r for r in all_releases if r.details_link == details_link), None
- )
- assert release, "Details not found for release"
-
- release_details = await ExtensionRelease.fetch_release_details(details_link)
- assert release_details, "Cannot fetch details for release"
- release_details["icon"] = release.icon
- release_details["repo"] = release.repo
- return release_details
- except AssertionError as exc:
- raise HTTPException(HTTPStatus.BAD_REQUEST, str(exc)) from exc
- except Exception as exc:
- logger.warning(exc)
+ release = next((r for r in all_releases if r.details_link == details_link), None)
+ if not release:
raise HTTPException(
- HTTPStatus.INTERNAL_SERVER_ERROR,
- f"Failed to get details for extension {ext_id}.",
- ) from exc
+ status_code=HTTPStatus.NOT_FOUND, detail="Release not found"
+ )
+
+ release_details = await ExtensionRelease.fetch_release_details(details_link)
+ if not release_details:
+ raise HTTPException(
+ status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
+ detail="Cannot fetch details for release",
+ )
+ release_details["icon"] = release.icon
+ release_details["repo"] = release.repo
+ return release_details
@extension_router.put("/{ext_id}/sell")
diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py
index 4c4f0ada6..707ae360d 100644
--- a/lnbits/core/views/generic.py
+++ b/lnbits/core/views/generic.py
@@ -24,7 +24,6 @@ from ...utils.exchange_rates import allowed_currencies, currencies
from ..crud import (
create_account,
create_wallet,
- get_account,
get_dbversions,
get_installed_extensions,
get_user,
@@ -231,10 +230,9 @@ async def service_worker(request: Request):
@generic_router.get("/manifest/{usr}.webmanifest")
async def manifest(request: Request, usr: str):
host = urlparse(str(request.url)).netloc
- account = await get_account(usr)
- if not account:
+ user = await get_user(usr)
+ if not user:
raise HTTPException(status_code=HTTPStatus.NOT_FOUND)
- user = await get_user(account)
return {
"short_name": settings.lnbits_site_title,
"name": settings.lnbits_site_title + " Wallet",
@@ -325,7 +323,7 @@ async def node(request: Request, user: User = Depends(check_admin)):
"user": user.json(),
"settings": settings.dict(),
"balance": balance,
- "wallets": user.wallets[0].dict(),
+ "wallets": user.wallets[0].json(),
},
)
diff --git a/lnbits/core/views/user_api.py b/lnbits/core/views/user_api.py
index 4f51753b3..0f874b7af 100644
--- a/lnbits/core/views/user_api.py
+++ b/lnbits/core/views/user_api.py
@@ -17,8 +17,8 @@ from lnbits.core.crud import (
update_admin_settings,
)
from lnbits.core.models import (
- Account,
AccountFilters,
+ AccountOverview,
CreateTopup,
User,
Wallet,
@@ -40,7 +40,7 @@ users_router = APIRouter(prefix="/users/api/v1", dependencies=[Depends(check_adm
)
async def api_get_users(
filters: Filters = Depends(parse_filters(AccountFilters)),
-) -> Page[Account]:
+) -> Page[AccountOverview]:
return await get_accounts(filters=filters)
diff --git a/lnbits/static/js/base.js b/lnbits/static/js/base.js
index 66fd4c190..50d4d6167 100644
--- a/lnbits/static/js/base.js
+++ b/lnbits/static/js/base.js
@@ -337,6 +337,12 @@ window.LNbits = {
.join('')
return hashHex
},
+ formatDate: function (timestamp) {
+ return Quasar.date.formatDate(
+ new Date(timestamp * 1000),
+ 'YYYY-MM-DD HH:mm'
+ )
+ },
formatCurrency: function (value, currency) {
return new Intl.NumberFormat(window.LOCALE, {
style: 'currency',
diff --git a/lnbits/static/js/users.js b/lnbits/static/js/users.js
index c32427881..f5d65119e 100644
--- a/lnbits/static/js/users.js
+++ b/lnbits/static/js/users.js
@@ -205,6 +205,9 @@ window.app = Vue.createApp({
})
},
methods: {
+ formatDate: function (value) {
+ return LNbits.utils.formatDate(value)
+ },
formatSat: function (value) {
return LNbits.utils.formatSat(Math.floor(value / 1000))
},