refactor: include admin extension into core

This commit is contained in:
Vlad Stan 2022-12-08 15:41:52 +02:00
parent 61c3476ba7
commit d15782521d
21 changed files with 349 additions and 391 deletions

View file

@ -15,15 +15,11 @@ from fastapi.staticfiles import StaticFiles
from loguru import logger
from lnbits.core.tasks import register_task_listeners
from lnbits.settings import (
check_admin_settings,
get_wallet_class,
set_wallet_class,
settings,
)
from lnbits.settings import get_wallet_class, set_wallet_class, settings
from .commands import migrate_databases
from .core import core_app
from .core.services import check_admin_settings
from .core.views.generic import core_html_routes
from .helpers import (
get_css_vendored,

View file

@ -6,6 +6,7 @@ db = Database("database")
core_app: APIRouter = APIRouter()
from .views.admin_api import * # noqa
from .views.api import * # noqa
from .views.generic import * # noqa
from .views.public_api import * # noqa

View file

@ -8,10 +8,18 @@ from loguru import logger
from lnbits import bolt11
from lnbits.db import COCKROACH, POSTGRES, Connection
from lnbits.settings import settings
from lnbits.settings import readonly_variables, settings
from . import db
from .models import BalanceCheck, Payment, User, Wallet
from .models import (
AdminSettings,
BalanceCheck,
Payment,
SuperSettings,
UpdateSettings,
User,
Wallet,
)
# accounts
# --------
@ -564,3 +572,75 @@ async def get_balance_notify(
(wallet_id,),
)
return row[0] if row else None
# admin
# --------
async def get_super_settings() -> Optional[SuperSettings]:
row = await db.fetchone("SELECT * FROM settings")
if not row:
return None
return SuperSettings(**row)
async def get_admin_settings(is_super_user: bool = False) -> Optional[AdminSettings]:
sets = await get_super_settings()
if not sets:
return None
row_dict = dict(sets)
row_dict.pop("super_user")
admin_settings = AdminSettings(
super_user=is_super_user,
lnbits_allowed_funding_sources=settings.lnbits_allowed_funding_sources,
**row_dict,
)
return admin_settings
async def delete_admin_settings():
await db.execute("DELETE FROM settings")
async def update_admin_settings(data: UpdateSettings):
q, values = get_q_and_values(data)
await db.execute(f"UPDATE settings SET {q}", (values,)) # type: ignore
def get_q_and_values(data):
keys = []
values = []
for key, value in data.items():
setattr(settings, key, value)
keys.append(f"{key} = ?")
if type(value) == list:
value = ",".join(value)
values.append(value)
return ", ".join(keys), values
async def create_admin_settings():
account = await create_account()
settings.super_user = account.id
keys = []
values = ""
for key, value in settings.dict(exclude_none=True).items():
if not key in readonly_variables:
keys.append(key)
if type(value) == list:
joined = ",".join(value)
values += f"'{joined}'"
if type(value) == int or type(value) == float:
values += str(value)
if type(value) == bool:
values += "true" if value else "false"
if type(value) == str:
value = value.replace("'", "")
values += f"'{value}'"
values += ","
q = ", ".join(keys)
v = values.rstrip(",")
sql = f"INSERT INTO settings ({q}) VALUES ({v})"
await db.execute(sql)

View file

@ -188,3 +188,71 @@ async def m005_balance_check_balance_notify(db):
);
"""
)
async def m006_create_admin_settings_table(db):
await db.execute(
"""
CREATE TABLE IF NOT EXISTS settings (
super_user TEXT,
lnbits_admin_extensions TEXT,
lnbits_admin_users TEXT,
lnbits_allowed_users TEXT,
lnbits_disabled_extensions TEXT,
lnbits_site_title TEXT,
lnbits_site_tagline TEXT,
lnbits_site_description TEXT,
lnbits_default_wallet_name TEXT,
lnbits_theme_options TEXT,
lnbits_custom_logo TEXT,
lnbits_ad_space TEXT,
lnbits_ad_space_title TEXT,
lnbits_ad_space_enabled BOOLEAN,
lnbits_force_https TEXT,
lnbits_reserve_fee_min TEXT,
lnbits_reserve_fee_percent TEXT,
lnbits_service_fee TEXT,
lnbits_hide_api TEXT,
lnbits_denomination TEXT,
lnbits_backend_wallet_class TEXT,
lnbits_endpoint TEXT,
lnbits_key TEXT,
fake_wallet_secret TEXT,
cliche_endpoint TEXT,
corelightning_rpc TEXT,
eclair_url TEXT,
eclair_pass TEXT,
lnd_cert TEXT,
lnd_admin_macaroon TEXT,
lnd_invoice_macaroon TEXT,
lnd_rest_endpoint TEXT,
lnd_rest_cert TEXT,
lnd_rest_macaroon TEXT,
lnd_rest_macaroon_encrypted TEXT,
lnd_grpc_endpoint TEXT,
lnd_grpc_cert TEXT,
lnd_grpc_port INTEGER,
lnd_grpc_admin_macaroon TEXT,
lnd_grpc_invoice_macaroon TEXT,
lnd_grpc_macaroon TEXT,
lnd_grpc_macaroon_encrypted TEXT,
lnpay_api_endpoint TEXT,
lnpay_api_key TEXT,
lnpay_wallet_key TEXT,
lntxbot_api_endpoint TEXT,
lntxbot_key TEXT,
opennode_api_endpoint TEXT,
opennode_key TEXT,
spark_url TEXT,
spark_token TEXT,
boltz_network TEXT,
boltz_url TEXT,
boltz_mempool_space_url TEXT,
boltz_mempool_space_url_ws TEXT,
lntips_api_endpoint TEXT,
lntips_api_key TEXT,
lntips_admin_key TEXT,
lntips_invoice_key TEXT
);
"""
)

View file

@ -5,9 +5,10 @@ from sqlite3 import Row
from typing import Dict, List, NamedTuple, Optional
from ecdsa import SECP256k1, SigningKey # type: ignore
from fastapi import Query
from lnurl import encode as lnurl_encode # type: ignore
from loguru import logger
from pydantic import BaseModel
from pydantic import BaseModel, Extra, validator
from lnbits.db import Connection
from lnbits.helpers import url_for
@ -198,3 +199,91 @@ class BalanceCheck(BaseModel):
@classmethod
def from_row(cls, row: Row):
return cls(wallet=row["wallet"], service=row["service"], url=row["url"])
# admin
# --------
class UpdateSettings(BaseModel, extra=Extra.forbid):
@validator(
"lnbits_admin_users",
"lnbits_allowed_users",
"lnbits_theme_options",
"lnbits_disabled_extensions",
"lnbits_admin_extensions",
pre=True,
)
def validate(cls, val):
if type(val) == str:
val = val.split(",") if val else []
return val
lnbits_backend_wallet_class: str = Query(None)
lnbits_admin_users: List[str] = Query(None)
lnbits_allowed_users: List[str] = Query(None)
lnbits_admin_extensions: List[str] = Query(None)
lnbits_disabled_extensions: List[str] = Query(None)
lnbits_theme_options: List[str] = Query(None)
lnbits_force_https: bool = Query(None)
lnbits_reserve_fee_min: int = Query(None, ge=0)
lnbits_reserve_fee_percent: float = Query(None, ge=0)
lnbits_service_fee: float = Query(None, ge=0)
lnbits_hide_api: bool = Query(None)
lnbits_site_title: str = Query(None)
lnbits_site_tagline: str = Query(None)
lnbits_site_description: str = Query(None)
lnbits_default_wallet_name: str = Query(None)
lnbits_denomination: str = Query(None)
lnbits_custom_logo: str = Query(None)
lnbits_ad_space: str = Query(None)
lnbits_ad_space_title: str = Query(None)
lnbits_ad_space_enabled: bool = Query(None)
# funding sources
fake_wallet_secret: str = Query(None)
lnbits_endpoint: str = Query(None)
lnbits_key: str = Query(None)
cliche_endpoint: str = Query(None)
corelightning_rpc: str = Query(None)
eclair_url: str = Query(None)
eclair_pass: str = Query(None)
lnd_rest_endpoint: str = Query(None)
lnd_rest_cert: str = Query(None)
lnd_rest_macaroon: str = Query(None)
lnd_rest_macaroon_encrypted: str = Query(None)
lnd_cert: str = Query(None)
lnd_admin_macaroon: str = Query(None)
lnd_invoice_macaroon: str = Query(None)
lnd_grpc_endpoint: str = Query(None)
lnd_grpc_cert: str = Query(None)
lnd_grpc_port: int = Query(None, ge=0)
lnd_grpc_admin_macaroon: str = Query(None)
lnd_grpc_invoice_macaroon: str = Query(None)
lnd_grpc_macaroon: str = Query(None)
lnd_grpc_macaroon_encrypted: str = Query(None)
lnpay_api_endpoint: str = Query(None)
lnpay_api_key: str = Query(None)
lnpay_wallet_key: str = Query(None)
lntxbot_api_endpoint: str = Query(None)
lntxbot_key: str = Query(None)
opennode_api_endpoint: str = Query(None)
opennode_key: str = Query(None)
spark_url: str = Query(None)
spark_token: str = Query(None)
lntips_api_endpoint: str = Query(None)
lntips_api_key: str = Query(None)
lntips_admin_key: str = Query(None)
lntips_invoice_key: str = Query(None)
boltz_mempool_space_url: str = Query(None)
boltz_mempool_space_url_ws: str = Query(None)
boltz_network: str = Query(None)
boltz_url: str = Query(None)
class SuperSettings(UpdateSettings):
super_user: str
class AdminSettings(UpdateSettings):
super_user: bool
lnbits_allowed_funding_sources: Optional[List[str]]

View file

@ -21,14 +21,16 @@ from lnbits.decorators import (
)
from lnbits.helpers import url_for, urlsafe_short_hash
from lnbits.requestvars import g
from lnbits.settings import FAKE_WALLET, get_wallet_class, settings
from lnbits.settings import FAKE_WALLET, get_wallet_class, readonly_variables, settings
from lnbits.wallets.base import PaymentResponse, PaymentStatus
from . import db
from .crud import (
check_internal,
create_admin_settings,
create_payment,
delete_wallet_payment,
get_super_settings,
get_wallet,
get_wallet_payment,
update_payment_details,
@ -385,3 +387,63 @@ def fee_reserve(amount_msat: int) -> int:
reserve_min = settings.lnbits_reserve_fee_min
reserve_percent = settings.lnbits_reserve_fee_percent
return max(int(reserve_min), int(amount_msat * reserve_percent / 100.0))
async def update_wallet_balance(wallet_id: str, amount: int):
internal_id = f"internal_{urlsafe_short_hash()}"
payment = await create_payment(
wallet_id=wallet_id,
checking_id=internal_id,
payment_request="admin_internal",
payment_hash="admin_internal",
amount=amount * 1000,
memo="Admin top up",
pending=False,
)
# manually send this for now
from lnbits.tasks import internal_invoice_queue
await internal_invoice_queue.put(internal_id)
return payment
async def check_admin_settings():
if settings.lnbits_admin_ui:
sets = await get_super_settings()
if not sets:
# create new settings if table is empty
logger.warning(
"settings empty. inserting new settings and creating admin account"
)
await create_admin_settings()
logger.warning("initialized settings from enviroment variables.")
sets = await get_super_settings()
if sets:
for key, value in sets.dict().items():
if not key in readonly_variables:
try:
setattr(settings, key, value)
except:
logger.error(f"error overriding setting: {key}, value: {value}")
# printing settings for debugging
logger.debug(f"Admin settings:")
for key, value in settings.dict(exclude_none=True).items():
logger.debug(f"{key}: {value}")
http = "https" if settings.lnbits_force_https else "http"
admin_url = (
f"{http}://{settings.host}:{settings.port}/wallet?usr={settings.super_user}"
)
logger.success(f"✔️ Access admin user account at: {admin_url}")
# callback for saas
if (
settings.lnbits_saas_callback
and settings.lnbits_saas_secret
and settings.lnbits_saas_instance_id
):
settings.send_admin_user_to_saas()

View file

@ -1,34 +1,31 @@
from http import HTTPStatus
from typing import Optional
from fastapi import Body, Query
from fastapi import Body
from fastapi.params import Depends
from starlette.exceptions import HTTPException
from lnbits.core.crud import get_wallet
from lnbits.core.models import User
from lnbits.core.models import AdminSettings, UpdateSettings, User
from lnbits.core.services import update_wallet_balance
from lnbits.decorators import check_admin
from lnbits.extensions.admin import admin_ext
from lnbits.extensions.admin.models import AdminSettings, UpdateSettings
from lnbits.server import server_restart
from .crud import (
delete_admin_settings,
get_admin_settings,
update_admin_settings,
update_wallet_balance,
)
from .. import core_app
from ..crud import delete_admin_settings, get_admin_settings, update_admin_settings
@admin_ext.get(
"/api/v1/restart/", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
@core_app.get(
"/admin/api/v1/restart/",
status_code=HTTPStatus.OK,
dependencies=[Depends(check_admin)],
)
async def api_restart_server() -> dict[str, str]:
server_restart.set()
return {"status": "Success"}
@admin_ext.get("/api/v1/settings/")
@core_app.get("/admin/api/v1/settings/")
async def api_get_settings(
user: User = Depends(check_admin), # type: ignore
) -> Optional[AdminSettings]:
@ -36,10 +33,12 @@ async def api_get_settings(
return admin_settings
@admin_ext.put(
"/api/v1/topup/", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
@core_app.put(
"/admin/api/v1/topup/",
status_code=HTTPStatus.OK,
dependencies=[Depends(check_admin)],
)
async def api_update_balance(
async def api_topup_balance(
id: str = Body(...), amount: int = Body(...)
) -> dict[str, str]:
try:
@ -54,16 +53,20 @@ async def api_update_balance(
return {"status": "Success"}
@admin_ext.put(
"/api/v1/settings/", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
@core_app.put(
"/admin/api/v1/settings/",
status_code=HTTPStatus.OK,
dependencies=[Depends(check_admin)],
)
async def api_update_settings(data: UpdateSettings):
await update_admin_settings(data)
return {"status": "Success"}
@admin_ext.delete(
"/api/v1/settings/", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
@core_app.delete(
"/admin/api/v1/settings/",
status_code=HTTPStatus.OK,
dependencies=[Depends(check_admin)],
)
async def api_delete_settings() -> dict[str, str]:
await delete_admin_settings()

View file

@ -13,9 +13,9 @@ from starlette.responses import HTMLResponse, JSONResponse
from lnbits.core import db
from lnbits.core.models import User
from lnbits.decorators import check_user_exists
from lnbits.decorators import check_admin, check_user_exists
from lnbits.helpers import template_renderer, url_for
from lnbits.settings import settings
from lnbits.settings import get_wallet_class, settings
from ...helpers import get_valid_extensions
from ..crud import (
@ -307,3 +307,19 @@ async def manifest(usr: str):
for wallet in user.wallets
],
}
@core_html_routes.get("/admin", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_admin)): # type: ignore
WALLET = get_wallet_class()
_, balance = await WALLET.status()
return template_renderer().TemplateResponse(
"admin/index.html",
{
"request": request,
"user": user.dict(),
"settings": settings.dict(),
"balance": balance,
},
)

View file

@ -1,12 +0,0 @@
# Admin Extension
## Dashboard to manage LNbits from the UI
With AdminUI you can manage your LNbits from the UI
![AdminUI](https://i.imgur.com/BIyLkyG.png)
## Before you start
**This extension doesn't discard the need for the `.env` file!**
In the .env file, set the `LNBITS_ADMIN_USERS` variable to include at least your user id.

View file

@ -1,16 +0,0 @@
from fastapi import APIRouter
from lnbits.db import Database
from lnbits.helpers import template_renderer
db = Database("ext_admin")
admin_ext: APIRouter = APIRouter(prefix="/admin", tags=["admin"])
def admin_renderer():
return template_renderer(["lnbits/extensions/admin/templates"])
from .views import * # noqa
from .views_api import * # noqa

View file

@ -1,6 +0,0 @@
{
"name": "Admin",
"short_description": "Manage your LNbits install",
"icon": "build",
"contributors": ["benarc"]
}

View file

@ -1,93 +0,0 @@
from typing import Optional
from lnbits.core.crud import create_account, create_payment
from lnbits.helpers import urlsafe_short_hash
from lnbits.settings import readonly_variables, settings
from lnbits.tasks import internal_invoice_queue
from . import db
from .models import AdminSettings, SuperSettings, UpdateSettings
async def update_wallet_balance(wallet_id: str, amount: int):
internal_id = f"internal_{urlsafe_short_hash()}"
payment = await create_payment(
wallet_id=wallet_id,
checking_id=internal_id,
payment_request="admin_internal",
payment_hash="admin_internal",
amount=amount * 1000,
memo="Admin top up",
pending=False,
)
# manually send this for now
await internal_invoice_queue.put(internal_id)
return payment
async def get_super_settings() -> Optional[SuperSettings]:
row = await db.fetchone("SELECT * FROM admin.settings")
if not row:
return None
return SuperSettings(**row)
async def get_admin_settings(is_super_user: bool = False) -> Optional[AdminSettings]:
sets = await get_super_settings()
if not sets:
return None
row_dict = dict(sets)
row_dict.pop("super_user")
admin_settings = AdminSettings(
super_user=is_super_user,
lnbits_allowed_funding_sources=settings.lnbits_allowed_funding_sources,
**row_dict,
)
return admin_settings
async def delete_admin_settings():
await db.execute("DELETE FROM admin.settings")
async def update_admin_settings(data: UpdateSettings):
q, values = get_q_and_values(data)
await db.execute(f"UPDATE admin.settings SET {q}", (values,)) # type: ignore
def get_q_and_values(data):
keys = []
values = []
for key, value in data.items():
setattr(settings, key, value)
keys.append(f"{key} = ?")
if type(value) == list:
value = ",".join(value)
values.append(value)
return ", ".join(keys), values
async def create_admin_settings():
account = await create_account()
settings.super_user = account.id
keys = []
values = ""
for key, value in settings.dict(exclude_none=True).items():
if not key in readonly_variables:
keys.append(key)
if type(value) == list:
joined = ",".join(value)
values += f"'{joined}'"
if type(value) == int or type(value) == float:
values += str(value)
if type(value) == bool:
values += "true" if value else "false"
if type(value) == str:
value = value.replace("'", "")
values += f"'{value}'"
values += ","
q = ", ".join(keys)
v = values.rstrip(",")
sql = f"INSERT INTO admin.settings ({q}) VALUES ({v})"
await db.execute(sql)

View file

@ -1,66 +0,0 @@
async def m001_create_admin_settings_table(db):
await db.execute(
"""
CREATE TABLE IF NOT EXISTS admin.settings (
super_user TEXT,
lnbits_admin_extensions TEXT,
lnbits_admin_users TEXT,
lnbits_allowed_users TEXT,
lnbits_disabled_extensions TEXT,
lnbits_site_title TEXT,
lnbits_site_tagline TEXT,
lnbits_site_description TEXT,
lnbits_default_wallet_name TEXT,
lnbits_theme_options TEXT,
lnbits_custom_logo TEXT,
lnbits_ad_space TEXT,
lnbits_ad_space_title TEXT,
lnbits_ad_space_enabled BOOLEAN,
lnbits_force_https TEXT,
lnbits_reserve_fee_min TEXT,
lnbits_reserve_fee_percent TEXT,
lnbits_service_fee TEXT,
lnbits_hide_api TEXT,
lnbits_denomination TEXT,
lnbits_backend_wallet_class TEXT,
lnbits_endpoint TEXT,
lnbits_key TEXT,
fake_wallet_secret TEXT,
cliche_endpoint TEXT,
corelightning_rpc TEXT,
eclair_url TEXT,
eclair_pass TEXT,
lnd_cert TEXT,
lnd_admin_macaroon TEXT,
lnd_invoice_macaroon TEXT,
lnd_rest_endpoint TEXT,
lnd_rest_cert TEXT,
lnd_rest_macaroon TEXT,
lnd_rest_macaroon_encrypted TEXT,
lnd_grpc_endpoint TEXT,
lnd_grpc_cert TEXT,
lnd_grpc_port INTEGER,
lnd_grpc_admin_macaroon TEXT,
lnd_grpc_invoice_macaroon TEXT,
lnd_grpc_macaroon TEXT,
lnd_grpc_macaroon_encrypted TEXT,
lnpay_api_endpoint TEXT,
lnpay_api_key TEXT,
lnpay_wallet_key TEXT,
lntxbot_api_endpoint TEXT,
lntxbot_key TEXT,
opennode_api_endpoint TEXT,
opennode_key TEXT,
spark_url TEXT,
spark_token TEXT,
boltz_network TEXT,
boltz_url TEXT,
boltz_mempool_space_url TEXT,
boltz_mempool_space_url_ws TEXT,
lntips_api_endpoint TEXT,
lntips_api_key TEXT,
lntips_admin_key TEXT,
lntips_invoice_key TEXT
);
"""
)

View file

@ -1,90 +0,0 @@
from typing import List, Optional
from fastapi import Query
from pydantic import BaseModel, Extra, validator
class UpdateSettings(BaseModel, extra=Extra.forbid):
@validator(
"lnbits_admin_users",
"lnbits_allowed_users",
"lnbits_theme_options",
"lnbits_disabled_extensions",
"lnbits_admin_extensions",
pre=True,
)
def validate(cls, val):
if type(val) == str:
val = val.split(",") if val else []
return val
lnbits_backend_wallet_class: str = Query(None)
lnbits_admin_users: List[str] = Query(None)
lnbits_allowed_users: List[str] = Query(None)
lnbits_admin_extensions: List[str] = Query(None)
lnbits_disabled_extensions: List[str] = Query(None)
lnbits_theme_options: List[str] = Query(None)
lnbits_force_https: bool = Query(None)
lnbits_reserve_fee_min: int = Query(None, ge=0)
lnbits_reserve_fee_percent: float = Query(None, ge=0)
lnbits_service_fee: float = Query(None, ge=0)
lnbits_hide_api: bool = Query(None)
lnbits_site_title: str = Query(None)
lnbits_site_tagline: str = Query(None)
lnbits_site_description: str = Query(None)
lnbits_default_wallet_name: str = Query(None)
lnbits_denomination: str = Query(None)
lnbits_custom_logo: str = Query(None)
lnbits_ad_space: str = Query(None)
lnbits_ad_space_title: str = Query(None)
lnbits_ad_space_enabled: bool = Query(None)
# funding sources
fake_wallet_secret: str = Query(None)
lnbits_endpoint: str = Query(None)
lnbits_key: str = Query(None)
cliche_endpoint: str = Query(None)
corelightning_rpc: str = Query(None)
eclair_url: str = Query(None)
eclair_pass: str = Query(None)
lnd_rest_endpoint: str = Query(None)
lnd_rest_cert: str = Query(None)
lnd_rest_macaroon: str = Query(None)
lnd_rest_macaroon_encrypted: str = Query(None)
lnd_cert: str = Query(None)
lnd_admin_macaroon: str = Query(None)
lnd_invoice_macaroon: str = Query(None)
lnd_grpc_endpoint: str = Query(None)
lnd_grpc_cert: str = Query(None)
lnd_grpc_port: int = Query(None, ge=0)
lnd_grpc_admin_macaroon: str = Query(None)
lnd_grpc_invoice_macaroon: str = Query(None)
lnd_grpc_macaroon: str = Query(None)
lnd_grpc_macaroon_encrypted: str = Query(None)
lnpay_api_endpoint: str = Query(None)
lnpay_api_key: str = Query(None)
lnpay_wallet_key: str = Query(None)
lntxbot_api_endpoint: str = Query(None)
lntxbot_key: str = Query(None)
opennode_api_endpoint: str = Query(None)
opennode_key: str = Query(None)
spark_url: str = Query(None)
spark_token: str = Query(None)
lntips_api_endpoint: str = Query(None)
lntips_api_key: str = Query(None)
lntips_admin_key: str = Query(None)
lntips_invoice_key: str = Query(None)
boltz_mempool_space_url: str = Query(None)
boltz_mempool_space_url_ws: str = Query(None)
boltz_network: str = Query(None)
boltz_url: str = Query(None)
class SuperSettings(UpdateSettings):
super_user: str
class AdminSettings(UpdateSettings):
super_user: bool
lnbits_allowed_funding_sources: Optional[List[str]]

View file

@ -1,28 +0,0 @@
from fastapi import Request
from fastapi.params import Depends
from fastapi.templating import Jinja2Templates
from starlette.responses import HTMLResponse
from lnbits.core.models import User
from lnbits.decorators import check_admin
from lnbits.settings import get_wallet_class, settings
from . import admin_ext, admin_renderer
templates = Jinja2Templates(directory="templates")
@admin_ext.get("/", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_admin)): # type: ignore
WALLET = get_wallet_class()
_, balance = await WALLET.status()
return admin_renderer().TemplateResponse(
"admin/index.html",
{
"request": request,
"user": user.dict(),
"settings": settings.dict(),
"balance": balance,
},
)

View file

@ -9,6 +9,8 @@ import httpx
from loguru import logger
from pydantic import BaseSettings, Field, validator
# from .core.crud import create_admin_settings, get_super_settings
def list_parse_fallback(v):
try:
@ -199,54 +201,6 @@ def set_cli_settings(**kwargs):
setattr(settings, key, value)
async def check_admin_settings():
if settings.lnbits_admin_ui:
# if not imported here, circular import error
from lnbits.extensions.admin.crud import (
create_admin_settings,
get_super_settings,
)
sets = await get_super_settings()
if not sets:
# create new settings if table is empty
logger.warning(
"admin.settings empty. inserting new settings and creating admin account"
)
await create_admin_settings()
logger.warning("initialized admin.settings from enviroment variables.")
sets = await get_super_settings()
if sets:
for key, value in sets.dict().items():
if not key in readonly_variables:
try:
setattr(settings, key, value)
except:
logger.error(f"error overriding setting: {key}, value: {value}")
# printing settings for debugging
logger.debug(f"Admin settings:")
for key, value in settings.dict(exclude_none=True).items():
logger.debug(f"{key}: {value}")
http = "https" if settings.lnbits_force_https else "http"
admin_url = (
f"{http}://{settings.host}:{settings.port}/wallet?usr={settings.super_user}"
)
logger.success(f"✔️ Access admin user account at: {admin_url}")
# callback for saas
if (
settings.lnbits_saas_callback
and settings.lnbits_saas_secret
and settings.lnbits_saas_instance_id
):
send_admin_user_to_saas()
wallets_module = importlib.import_module("lnbits.wallets")
FAKE_WALLET = getattr(wallets_module, "FakeWallet")()