Merge remote-tracking branch 'lnbits/FinalAdminUI' into FinalAdminUI

This commit is contained in:
Tiago vasconcelos 2022-10-12 19:05:53 +01:00
commit de6a77e750
7 changed files with 67 additions and 31 deletions

View file

@ -64,7 +64,7 @@ def create_app() -> FastAPI:
# TODO: why those 2? # TODO: why those 2?
g().config = settings g().config = settings
# g().base_url = f"http://{settings.host}:{settings.port}" g().base_url = f"http://{settings.host}:{settings.port}"
app.add_middleware(GZipMiddleware, minimum_size=1000) app.add_middleware(GZipMiddleware, minimum_size=1000)

View file

@ -6,6 +6,9 @@ async def m001_create_admin_settings_table(db):
debug TEXT, debug TEXT,
host TEXT, host TEXT,
port INTEGER, port INTEGER,
lnbits_saas_instance_id TEXT,
lnbits_saas_callback TEXT,
lnbits_saas_secret TEXT,
lnbits_path TEXT, lnbits_path TEXT,
lnbits_commit TEXT, lnbits_commit TEXT,
lnbits_admin_users TEXT, lnbits_admin_users TEXT,

View file

@ -369,10 +369,10 @@
topupWallet() { topupWallet() {
LNbits.api LNbits.api
.request( .request(
'POST', 'PUT',
'/admin/api/v1/topup/?usr=' + this.g.user.id, '/admin/api/v1/topup/?usr=' + this.g.user.id,
this.wallet.id, this.g.user.wallets[0].adminkey,
this.wallet.amount this.wallet
) )
.then(response => { .then(response => {
this.$q.notify({ this.$q.notify({

View file

@ -1,7 +1,6 @@
from http import HTTPStatus from http import HTTPStatus
from fastapi import Body, Depends, Request from fastapi import Body, Depends, Query
from loguru import logger
from starlette.exceptions import HTTPException from starlette.exceptions import HTTPException
from lnbits.core.crud import get_wallet from lnbits.core.crud import get_wallet
@ -9,52 +8,50 @@ from lnbits.core.models import User
from lnbits.decorators import check_admin from lnbits.decorators import check_admin
from lnbits.extensions.admin import admin_ext from lnbits.extensions.admin import admin_ext
from lnbits.extensions.admin.models import UpdateSettings from lnbits.extensions.admin.models import UpdateSettings
from lnbits.requestvars import g
from lnbits.server import server_restart from lnbits.server import server_restart
from lnbits.settings import settings
from .crud import delete_settings, update_settings, update_wallet_balance from .crud import delete_settings, update_settings, update_wallet_balance
@admin_ext.get("/api/v1/restart/", status_code=HTTPStatus.OK) @admin_ext.get(
async def api_restart_server(user: User = Depends(check_admin)): "/api/v1/restart/", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
)
async def api_restart_server() -> dict[str, str]:
server_restart.set() server_restart.set()
return {"status": "Success"} return {"status": "Success"}
@admin_ext.put("/api/v1/topup/", status_code=HTTPStatus.OK) @admin_ext.put(
"/api/v1/topup/", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
)
async def api_update_balance( async def api_update_balance(
wallet_id, topup_amount: int, user: User = Depends(check_admin) id: str = Body(...), amount: int = Body(...)
): ) -> dict[str, str]:
try: try:
wallet = await get_wallet(wallet_id) await get_wallet(id)
except: except:
raise HTTPException( raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="wallet does not exist." status_code=HTTPStatus.FORBIDDEN, detail="wallet does not exist."
) )
await update_wallet_balance(wallet_id=wallet_id, amount=int(topup_amount)) await update_wallet_balance(wallet_id=id, amount=int(amount))
return {"status": "Success"} return {"status": "Success"}
@admin_ext.put("/api/v1/settings/", status_code=HTTPStatus.OK) @admin_ext.put(
"/api/v1/settings/", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
)
async def api_update_settings( async def api_update_settings(
user: User = Depends(check_admin),
data: UpdateSettings = Body(...), data: UpdateSettings = Body(...),
): ):
settings = await update_settings(data) settings = await update_settings(data)
return {"status": "Success", "settings": settings.dict()} return {"status": "Success", "settings": settings.dict()}
@admin_ext.delete("/api/v1/settings/", status_code=HTTPStatus.OK) @admin_ext.delete(
async def api_delete_settings( "/api/v1/settings/", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
user: User = Depends(check_admin), )
): async def api_delete_settings() -> dict[str, str]:
await delete_settings() await delete_settings()
return {"status": "Success"} return {"status": "Success"}
@admin_ext.get("/api/v1/backup/", status_code=HTTPStatus.OK)
async def api_backup(user: User = Depends(check_admin)):
return {"status": "not implemented"}

View file

@ -52,6 +52,7 @@ def main(ctx, port: int, host: str, ssl_keyfile: str, ssl_certfile: str, reload:
port=port, port=port,
host=host, host=host,
reload=reload, reload=reload,
forwarded_allow_ips="*",
ssl_keyfile=ssl_keyfile, ssl_keyfile=ssl_keyfile,
ssl_certfile=ssl_certfile, ssl_certfile=ssl_certfile,
**d **d

View file

@ -5,6 +5,7 @@ from os import path
from sqlite3 import Row from sqlite3 import Row
from typing import List, Optional from typing import List, Optional
import httpx
from loguru import logger from loguru import logger
from pydantic import BaseSettings, Field, validator from pydantic import BaseSettings, Field, validator
@ -12,7 +13,7 @@ from pydantic import BaseSettings, Field, validator
def list_parse_fallback(v): def list_parse_fallback(v):
try: try:
return json.loads(v) return json.loads(v)
except Exception as e: except Exception:
replaced = v.replace(" ", "") replaced = v.replace(" ", "")
if replaced: if replaced:
return replaced.split(",") return replaced.split(",")
@ -34,6 +35,11 @@ class Settings(BaseSettings):
lnbits_path: str = Field(default=".") lnbits_path: str = Field(default=".")
lnbits_commit: str = Field(default="unknown") lnbits_commit: str = Field(default="unknown")
# saas
lnbits_saas_callback: Optional[str] = Field(default=None)
lnbits_saas_secret: Optional[str] = Field(default=None)
lnbits_saas_instance_id: Optional[str] = Field(default=None)
# users # users
lnbits_admin_users: List[str] = Field(default=[]) lnbits_admin_users: List[str] = Field(default=[])
lnbits_allowed_users: List[str] = Field(default=[]) lnbits_allowed_users: List[str] = Field(default=[])
@ -230,11 +236,40 @@ async def check_admin_settings():
http = "https" if settings.lnbits_force_https else "http" http = "https" if settings.lnbits_force_https else "http"
user = settings.lnbits_admin_users[0] user = settings.lnbits_admin_users[0]
logger.warning(
f" ✔️ Access admin user account at: {http}://{settings.host}:{settings.port}/wallet?usr={user}" admin_url = (
f"{http}://{settings.host}:{settings.port}/wallet?usr={user}"
) )
logger.warning(f"✔️ Access admin user account at: {admin_url}")
if (
settings.lnbits_saas_callback
and settings.lnbits_saas_secret
and settings.lnbits_saas_instance_id
):
with httpx.Client() as client:
headers = {
"Content-Type": "application/json; charset=utf-8",
"X-API-KEY": settings.lnbits_saas_secret,
}
payload = {
"instance_id": settings.lnbits_saas_instance_id,
"adminuser": user,
}
try:
client.post(
settings.lnbits_saas_callback,
headers=headers,
json=payload,
)
logger.warning("sent admin user to saas application")
except: except:
logger.warning("admin.settings tables does not exist.") logger.error(
f"error sending admin user to saas: {settings.lnbits_saas_callback}"
)
except:
logger.error("admin.settings tables does not exist.")
raise raise

View file

@ -19,7 +19,6 @@ from .base import (
class FakeWallet(Wallet): class FakeWallet(Wallet):
queue: asyncio.Queue = asyncio.Queue(0)
secret: str = settings.fake_wallet_secret secret: str = settings.fake_wallet_secret
privkey: str = hashlib.pbkdf2_hmac( privkey: str = hashlib.pbkdf2_hmac(
"sha256", "sha256",
@ -98,6 +97,7 @@ class FakeWallet(Wallet):
return PaymentStatus(None) return PaymentStatus(None)
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]: async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
self.queue: asyncio.Queue = asyncio.Queue(0)
while True: while True:
value: Invoice = await self.queue.get() value: Invoice = await self.queue.get()
yield value.payment_hash yield value.payment_hash