This commit is contained in:
dni ⚡ 2024-09-30 09:23:44 +02:00 committed by Vlad Stan
parent 6f10b21016
commit 06385c14d8
8 changed files with 59 additions and 38 deletions

View File

@ -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,
)

View File

@ -37,6 +37,7 @@
icon="content_copy"
size="sm"
color="primary"
class="q-ml-xs"
@click="copyText(props.row.id)"
>
<q-tooltip>Copy Wallet ID</q-tooltip>
@ -45,6 +46,7 @@
v-if="!props.row.deleted"
:wallet_id="props.row.id"
:callback="topupCallback"
class="q-ml-xs"
></lnbits-update-balance>
<q-btn
round
@ -52,6 +54,7 @@
icon="vpn_key"
size="sm"
color="primary"
class="q-ml-xs"
@click="copyText(props.row.adminkey)"
>
<q-tooltip>Copy Admin Key</q-tooltip>
@ -62,6 +65,7 @@
icon="vpn_key"
size="sm"
color="secondary"
class="q-ml-xs"
@click="copyText(props.row.inkey)"
>
<q-tooltip>Copy Invoice Key</q-tooltip>
@ -72,6 +76,7 @@
icon="toggle_off"
size="sm"
color="secondary"
class="q-ml-xs"
@click="undeleteUserWallet(props.row.user, props.row.id)"
>
<q-tooltip>Undelete Wallet</q-tooltip>
@ -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)"
>
<q-tooltip>Delete Wallet</q-tooltip>

View File

@ -61,6 +61,7 @@ include "users/_createWalletDialog.html" %}
icon="content_copy"
size="sm"
color="primary"
class="q-ml-xs"
@click="copyText(props.row.id)"
>
<q-tooltip>Copy User ID</q-tooltip>
@ -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)"
>
<q-tooltip>Toggle Admin</q-tooltip>
@ -81,6 +83,7 @@ include "users/_createWalletDialog.html" %}
icon="build"
size="sm"
color="positive"
class="q-ml-xs"
>
<q-tooltip>Super User</q-tooltip>
</q-btn>
@ -98,6 +101,7 @@ include "users/_createWalletDialog.html" %}
icon="delete"
size="sm"
color="negative"
class="q-ml-xs"
@click="deleteUser(props.row.id, props)"
>
<q-tooltip>Delete User</q-tooltip>
@ -111,7 +115,10 @@ include "users/_createWalletDialog.html" %}
<q-td auto-width v-text="props.row.transaction_count"></q-td>
<q-td auto-width v-text="props.row.username"></q-td>
<q-td auto-width v-text="props.row.email"></q-td>
<q-td auto-width v-text="props.row.last_payment"></q-td>
<q-td
auto-width
v-text="formatDate(props.row.last_payment)"
></q-td>
</q-tr>
</template>
</q-table>

View File

@ -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")

View File

@ -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(),
},
)

View File

@ -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)

View File

@ -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',

View File

@ -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))
},