fixup!
This commit is contained in:
+15
-9
@@ -230,7 +230,7 @@ async def get_user(
|
|||||||
else:
|
else:
|
||||||
account = account_or_id
|
account = account_or_id
|
||||||
extensions = await get_user_active_extensions_ids(account.id, conn)
|
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(
|
return User(
|
||||||
id=account.id,
|
id=account.id,
|
||||||
email=account.email,
|
email=account.email,
|
||||||
@@ -508,27 +508,33 @@ async def delete_unused_wallets(
|
|||||||
|
|
||||||
|
|
||||||
async def get_wallet(
|
async def get_wallet(
|
||||||
wallet_id: str, conn: Optional[Connection] = None
|
wallet_id: str, deleted: Optional[bool] = None, conn: Optional[Connection] = None
|
||||||
) -> Optional[Wallet]:
|
) -> Optional[Wallet]:
|
||||||
|
where = "AND deleted = :deleted" if deleted is not None else ""
|
||||||
return await (conn or db).fetchone(
|
return await (conn or db).fetchone(
|
||||||
"""
|
f"""
|
||||||
SELECT *, COALESCE((
|
SELECT *, COALESCE((
|
||||||
SELECT balance FROM balances WHERE wallet_id = wallets.id
|
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,
|
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(
|
return await (conn or db).fetchall(
|
||||||
"""
|
f"""
|
||||||
SELECT *, COALESCE((
|
SELECT *, COALESCE((
|
||||||
SELECT balance FROM balances WHERE wallet_id = wallets.id
|
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,
|
Wallet,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
icon="content_copy"
|
icon="content_copy"
|
||||||
size="sm"
|
size="sm"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
class="q-ml-xs"
|
||||||
@click="copyText(props.row.id)"
|
@click="copyText(props.row.id)"
|
||||||
>
|
>
|
||||||
<q-tooltip>Copy Wallet ID</q-tooltip>
|
<q-tooltip>Copy Wallet ID</q-tooltip>
|
||||||
@@ -45,6 +46,7 @@
|
|||||||
v-if="!props.row.deleted"
|
v-if="!props.row.deleted"
|
||||||
:wallet_id="props.row.id"
|
:wallet_id="props.row.id"
|
||||||
:callback="topupCallback"
|
:callback="topupCallback"
|
||||||
|
class="q-ml-xs"
|
||||||
></lnbits-update-balance>
|
></lnbits-update-balance>
|
||||||
<q-btn
|
<q-btn
|
||||||
round
|
round
|
||||||
@@ -52,6 +54,7 @@
|
|||||||
icon="vpn_key"
|
icon="vpn_key"
|
||||||
size="sm"
|
size="sm"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
class="q-ml-xs"
|
||||||
@click="copyText(props.row.adminkey)"
|
@click="copyText(props.row.adminkey)"
|
||||||
>
|
>
|
||||||
<q-tooltip>Copy Admin Key</q-tooltip>
|
<q-tooltip>Copy Admin Key</q-tooltip>
|
||||||
@@ -62,6 +65,7 @@
|
|||||||
icon="vpn_key"
|
icon="vpn_key"
|
||||||
size="sm"
|
size="sm"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
|
class="q-ml-xs"
|
||||||
@click="copyText(props.row.inkey)"
|
@click="copyText(props.row.inkey)"
|
||||||
>
|
>
|
||||||
<q-tooltip>Copy Invoice Key</q-tooltip>
|
<q-tooltip>Copy Invoice Key</q-tooltip>
|
||||||
@@ -72,6 +76,7 @@
|
|||||||
icon="toggle_off"
|
icon="toggle_off"
|
||||||
size="sm"
|
size="sm"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
|
class="q-ml-xs"
|
||||||
@click="undeleteUserWallet(props.row.user, props.row.id)"
|
@click="undeleteUserWallet(props.row.user, props.row.id)"
|
||||||
>
|
>
|
||||||
<q-tooltip>Undelete Wallet</q-tooltip>
|
<q-tooltip>Undelete Wallet</q-tooltip>
|
||||||
@@ -81,6 +86,7 @@
|
|||||||
icon="delete"
|
icon="delete"
|
||||||
size="sm"
|
size="sm"
|
||||||
color="negative"
|
color="negative"
|
||||||
|
class="q-ml-xs"
|
||||||
@click="deleteUserWallet(props.row.user, props.row.id, props.row.deleted)"
|
@click="deleteUserWallet(props.row.user, props.row.id, props.row.deleted)"
|
||||||
>
|
>
|
||||||
<q-tooltip>Delete Wallet</q-tooltip>
|
<q-tooltip>Delete Wallet</q-tooltip>
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ include "users/_createWalletDialog.html" %}
|
|||||||
icon="content_copy"
|
icon="content_copy"
|
||||||
size="sm"
|
size="sm"
|
||||||
color="primary"
|
color="primary"
|
||||||
|
class="q-ml-xs"
|
||||||
@click="copyText(props.row.id)"
|
@click="copyText(props.row.id)"
|
||||||
>
|
>
|
||||||
<q-tooltip>Copy User ID</q-tooltip>
|
<q-tooltip>Copy User ID</q-tooltip>
|
||||||
@@ -71,6 +72,7 @@ include "users/_createWalletDialog.html" %}
|
|||||||
icon="build"
|
icon="build"
|
||||||
size="sm"
|
size="sm"
|
||||||
:color="props.row.is_admin ? 'primary' : 'grey'"
|
:color="props.row.is_admin ? 'primary' : 'grey'"
|
||||||
|
class="q-ml-xs"
|
||||||
@click="toggleAdmin(props.row.id)"
|
@click="toggleAdmin(props.row.id)"
|
||||||
>
|
>
|
||||||
<q-tooltip>Toggle Admin</q-tooltip>
|
<q-tooltip>Toggle Admin</q-tooltip>
|
||||||
@@ -81,6 +83,7 @@ include "users/_createWalletDialog.html" %}
|
|||||||
icon="build"
|
icon="build"
|
||||||
size="sm"
|
size="sm"
|
||||||
color="positive"
|
color="positive"
|
||||||
|
class="q-ml-xs"
|
||||||
>
|
>
|
||||||
<q-tooltip>Super User</q-tooltip>
|
<q-tooltip>Super User</q-tooltip>
|
||||||
</q-btn>
|
</q-btn>
|
||||||
@@ -98,6 +101,7 @@ include "users/_createWalletDialog.html" %}
|
|||||||
icon="delete"
|
icon="delete"
|
||||||
size="sm"
|
size="sm"
|
||||||
color="negative"
|
color="negative"
|
||||||
|
class="q-ml-xs"
|
||||||
@click="deleteUser(props.row.id, props)"
|
@click="deleteUser(props.row.id, props)"
|
||||||
>
|
>
|
||||||
<q-tooltip>Delete User</q-tooltip>
|
<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.transaction_count"></q-td>
|
||||||
<q-td auto-width v-text="props.row.username"></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.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>
|
</q-tr>
|
||||||
</template>
|
</template>
|
||||||
</q-table>
|
</q-table>
|
||||||
|
|||||||
@@ -113,33 +113,28 @@ async def api_install_extension(data: CreateExtension):
|
|||||||
) from exc
|
) from exc
|
||||||
|
|
||||||
|
|
||||||
@extension_router.get("/{ext_id}/details", dependencies=[Depends(check_user_exists)])
|
@extension_router.get("/{ext_id}/details")
|
||||||
async def api_extension_details(
|
async def api_extension_details(
|
||||||
ext_id: str,
|
ext_id: str,
|
||||||
details_link: str,
|
details_link: str,
|
||||||
):
|
):
|
||||||
|
all_releases = await InstallableExtension.get_extension_releases(ext_id)
|
||||||
|
|
||||||
try:
|
release = next((r for r in all_releases if r.details_link == details_link), None)
|
||||||
all_releases = await InstallableExtension.get_extension_releases(ext_id)
|
if not release:
|
||||||
|
|
||||||
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)
|
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
HTTPStatus.INTERNAL_SERVER_ERROR,
|
status_code=HTTPStatus.NOT_FOUND, detail="Release not found"
|
||||||
f"Failed to get details for extension {ext_id}.",
|
)
|
||||||
) from exc
|
|
||||||
|
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")
|
@extension_router.put("/{ext_id}/sell")
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ from ...utils.exchange_rates import allowed_currencies, currencies
|
|||||||
from ..crud import (
|
from ..crud import (
|
||||||
create_account,
|
create_account,
|
||||||
create_wallet,
|
create_wallet,
|
||||||
get_account,
|
|
||||||
get_dbversions,
|
get_dbversions,
|
||||||
get_installed_extensions,
|
get_installed_extensions,
|
||||||
get_user,
|
get_user,
|
||||||
@@ -231,10 +230,9 @@ async def service_worker(request: Request):
|
|||||||
@generic_router.get("/manifest/{usr}.webmanifest")
|
@generic_router.get("/manifest/{usr}.webmanifest")
|
||||||
async def manifest(request: Request, usr: str):
|
async def manifest(request: Request, usr: str):
|
||||||
host = urlparse(str(request.url)).netloc
|
host = urlparse(str(request.url)).netloc
|
||||||
account = await get_account(usr)
|
user = await get_user(usr)
|
||||||
if not account:
|
if not user:
|
||||||
raise HTTPException(status_code=HTTPStatus.NOT_FOUND)
|
raise HTTPException(status_code=HTTPStatus.NOT_FOUND)
|
||||||
user = await get_user(account)
|
|
||||||
return {
|
return {
|
||||||
"short_name": settings.lnbits_site_title,
|
"short_name": settings.lnbits_site_title,
|
||||||
"name": settings.lnbits_site_title + " Wallet",
|
"name": settings.lnbits_site_title + " Wallet",
|
||||||
@@ -325,7 +323,7 @@ async def node(request: Request, user: User = Depends(check_admin)):
|
|||||||
"user": user.json(),
|
"user": user.json(),
|
||||||
"settings": settings.dict(),
|
"settings": settings.dict(),
|
||||||
"balance": balance,
|
"balance": balance,
|
||||||
"wallets": user.wallets[0].dict(),
|
"wallets": user.wallets[0].json(),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ from lnbits.core.crud import (
|
|||||||
update_admin_settings,
|
update_admin_settings,
|
||||||
)
|
)
|
||||||
from lnbits.core.models import (
|
from lnbits.core.models import (
|
||||||
Account,
|
|
||||||
AccountFilters,
|
AccountFilters,
|
||||||
|
AccountOverview,
|
||||||
CreateTopup,
|
CreateTopup,
|
||||||
User,
|
User,
|
||||||
Wallet,
|
Wallet,
|
||||||
@@ -40,7 +40,7 @@ users_router = APIRouter(prefix="/users/api/v1", dependencies=[Depends(check_adm
|
|||||||
)
|
)
|
||||||
async def api_get_users(
|
async def api_get_users(
|
||||||
filters: Filters = Depends(parse_filters(AccountFilters)),
|
filters: Filters = Depends(parse_filters(AccountFilters)),
|
||||||
) -> Page[Account]:
|
) -> Page[AccountOverview]:
|
||||||
return await get_accounts(filters=filters)
|
return await get_accounts(filters=filters)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -337,6 +337,12 @@ window.LNbits = {
|
|||||||
.join('')
|
.join('')
|
||||||
return hashHex
|
return hashHex
|
||||||
},
|
},
|
||||||
|
formatDate: function (timestamp) {
|
||||||
|
return Quasar.date.formatDate(
|
||||||
|
new Date(timestamp * 1000),
|
||||||
|
'YYYY-MM-DD HH:mm'
|
||||||
|
)
|
||||||
|
},
|
||||||
formatCurrency: function (value, currency) {
|
formatCurrency: function (value, currency) {
|
||||||
return new Intl.NumberFormat(window.LOCALE, {
|
return new Intl.NumberFormat(window.LOCALE, {
|
||||||
style: 'currency',
|
style: 'currency',
|
||||||
|
|||||||
@@ -205,6 +205,9 @@ window.app = Vue.createApp({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
formatDate: function (value) {
|
||||||
|
return LNbits.utils.formatDate(value)
|
||||||
|
},
|
||||||
formatSat: function (value) {
|
formatSat: function (value) {
|
||||||
return LNbits.utils.formatSat(Math.floor(value / 1000))
|
return LNbits.utils.formatSat(Math.floor(value / 1000))
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user