mirror of
https://github.com/lnbits/lnbits-legend.git
synced 2024-11-19 18:11:30 +01:00
eb73daffe9
* [FEAT] Node Managment feat: node dashboard channels and transactions fix: update channel variables better types refactor ui add onchain balances and backend_name mock values for fake wallet remove app tab start implementing peers and channel management peer and channel management implement channel closing add channel states, better errors seperate payments and invoices on transactions tab display total channel balance feat: optional public page feat: show node address fix: port conversion feat: details dialog on transactions fix: peer info without alias fix: rename channel balances small improvements to channels tab feat: pagination on transactions tab test caching transactions refactor: move WALLET into wallets module fix: backwards compatibility refactor: move get_node_class to nodes modules post merge bundle fundle feat: disconnect peer feat: initial lnd support only use filtered channels for total balance adjust closing logic add basic node tests add setting for disabling transactions tab revert unnecessary changes add tests for invoices and payments improve payment and invoice implementations the previously used invoice fixture has a session scope, but a new invoice is required tests and bug fixes for channels api use query instead of body in channel delete delete requests should generally not use a body take node id through path instead of body for delete endpoint add peer management tests more tests for errors improve error handling rename id and pubkey to peer_id for consistency remove dead code fix http status codes make cache keys safer cache node public info comments for node settings rename node prop in frontend adjust tests to new status codes cln: use amount_msat instead of value for onchain balance turn transactions tab off by default enable transactions in tests only allow super user to create or delete fix prop name in admin navbar --------- Co-authored-by: jacksn <jkranawetter05@gmail.com>
154 lines
4.5 KiB
Python
154 lines
4.5 KiB
Python
import os
|
|
import time
|
|
from http import HTTPStatus
|
|
from shutil import make_archive
|
|
from subprocess import Popen
|
|
from typing import Optional
|
|
from urllib.parse import urlparse
|
|
|
|
from fastapi import APIRouter, Depends
|
|
from fastapi.responses import FileResponse
|
|
from starlette.exceptions import HTTPException
|
|
|
|
from lnbits.core.crud import get_wallet
|
|
from lnbits.core.models import CreateTopup, User
|
|
from lnbits.core.services import (
|
|
get_balance_delta,
|
|
update_cached_settings,
|
|
update_wallet_balance,
|
|
)
|
|
from lnbits.decorators import check_admin, check_super_user
|
|
from lnbits.server import server_restart
|
|
from lnbits.settings import AdminSettings, UpdateSettings, settings
|
|
|
|
from .. import core_app_extra
|
|
from ..crud import delete_admin_settings, get_admin_settings, update_admin_settings
|
|
|
|
admin_router = APIRouter()
|
|
|
|
|
|
@admin_router.get(
|
|
"/admin/api/v1/audit",
|
|
name="Audit",
|
|
description="show the current balance of the node and the LNbits database",
|
|
dependencies=[Depends(check_admin)],
|
|
)
|
|
async def api_auditor():
|
|
try:
|
|
delta, node_balance, total_balance = await get_balance_delta()
|
|
return {
|
|
"delta_msats": int(delta),
|
|
"node_balance_msats": int(node_balance),
|
|
"lnbits_balance_msats": int(total_balance),
|
|
}
|
|
except Exception:
|
|
raise HTTPException(
|
|
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
|
|
detail="Could not audit balance.",
|
|
)
|
|
|
|
|
|
@admin_router.get("/admin/api/v1/settings/", response_model=Optional[AdminSettings])
|
|
async def api_get_settings(
|
|
user: User = Depends(check_admin),
|
|
) -> Optional[AdminSettings]:
|
|
admin_settings = await get_admin_settings(user.super_user)
|
|
return admin_settings
|
|
|
|
|
|
@admin_router.put(
|
|
"/admin/api/v1/settings/",
|
|
status_code=HTTPStatus.OK,
|
|
)
|
|
async def api_update_settings(data: UpdateSettings, user: User = Depends(check_admin)):
|
|
await update_admin_settings(data)
|
|
admin_settings = await get_admin_settings(user.super_user)
|
|
assert admin_settings, "Updated admin settings not found."
|
|
update_cached_settings(admin_settings.dict())
|
|
core_app_extra.register_new_ratelimiter()
|
|
return {"status": "Success"}
|
|
|
|
|
|
@admin_router.delete(
|
|
"/admin/api/v1/settings/",
|
|
status_code=HTTPStatus.OK,
|
|
dependencies=[Depends(check_super_user)],
|
|
)
|
|
async def api_delete_settings() -> None:
|
|
await delete_admin_settings()
|
|
server_restart.set()
|
|
|
|
|
|
@admin_router.get(
|
|
"/admin/api/v1/restart/",
|
|
status_code=HTTPStatus.OK,
|
|
dependencies=[Depends(check_super_user)],
|
|
)
|
|
async def api_restart_server() -> dict[str, str]:
|
|
server_restart.set()
|
|
return {"status": "Success"}
|
|
|
|
|
|
@admin_router.put(
|
|
"/admin/api/v1/topup/",
|
|
name="Topup",
|
|
status_code=HTTPStatus.OK,
|
|
dependencies=[Depends(check_super_user)],
|
|
)
|
|
async def api_topup_balance(data: CreateTopup) -> dict[str, str]:
|
|
try:
|
|
await get_wallet(data.id)
|
|
except Exception:
|
|
raise HTTPException(
|
|
status_code=HTTPStatus.FORBIDDEN, detail="wallet does not exist."
|
|
)
|
|
|
|
if settings.lnbits_backend_wallet_class == "VoidWallet":
|
|
raise HTTPException(
|
|
status_code=HTTPStatus.FORBIDDEN, detail="VoidWallet active"
|
|
)
|
|
|
|
await update_wallet_balance(wallet_id=data.id, amount=int(data.amount))
|
|
|
|
return {"status": "Success"}
|
|
|
|
|
|
@admin_router.get(
|
|
"/admin/api/v1/backup/",
|
|
status_code=HTTPStatus.OK,
|
|
dependencies=[Depends(check_super_user)],
|
|
response_class=FileResponse,
|
|
)
|
|
async def api_download_backup() -> FileResponse:
|
|
last_filename = "lnbits-backup"
|
|
filename = f"lnbits-backup-{int(time.time())}.zip"
|
|
db_url = settings.lnbits_database_url
|
|
pg_backup_filename = f"{settings.lnbits_data_folder}/lnbits-database.dmp"
|
|
is_pg = db_url and db_url.startswith("postgres://")
|
|
|
|
if is_pg:
|
|
p = urlparse(db_url)
|
|
command = (
|
|
f"pg_dump --host={p.hostname} "
|
|
f"--dbname={p.path.replace('/', '')} "
|
|
f"--username={p.username} "
|
|
"--no-password "
|
|
"--format=c "
|
|
f"--file={pg_backup_filename}"
|
|
)
|
|
proc = Popen(
|
|
command, shell=True, env={**os.environ, "PGPASSWORD": p.password or ""}
|
|
)
|
|
proc.wait()
|
|
|
|
make_archive(last_filename, "zip", settings.lnbits_data_folder)
|
|
|
|
# cleanup pg_dump file
|
|
if is_pg:
|
|
proc = Popen(f"rm {pg_backup_filename}", shell=True)
|
|
proc.wait()
|
|
|
|
return FileResponse(
|
|
path=f"{last_filename}.zip", filename=filename, media_type="application/zip"
|
|
)
|