fixup frontend and routes

This commit is contained in:
dni ⚡ 2022-10-05 09:19:07 +02:00
parent 90243060f4
commit 4e8374ed6d
5 changed files with 109 additions and 37 deletions

View file

@ -2,10 +2,11 @@ from typing import List
from lnbits.core.crud import create_payment from lnbits.core.crud import create_payment
from lnbits.helpers import urlsafe_short_hash from lnbits.helpers import urlsafe_short_hash
from lnbits.settings import Settings from lnbits.settings import Settings, read_only_variables
from lnbits.tasks import internal_invoice_queue from lnbits.tasks import internal_invoice_queue
from . import db from . import db
from .models import UpdateSettings
async def update_wallet_balance(wallet_id: str, amount: int) -> str: async def update_wallet_balance(wallet_id: str, amount: int) -> str:
@ -25,10 +26,28 @@ async def update_wallet_balance(wallet_id: str, amount: int) -> str:
await internal_invoice_queue.put(internal_id) await internal_invoice_queue.put(internal_id)
async def update_settings(user: str, **kwargs) -> Settings: async def update_settings(data: UpdateSettings) -> Settings:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) fields = []
# print("UPDATE", q) for key, value in data.dict(exclude_none=True).items():
await db.execute(f'UPDATE admin.settings SET {q}') if not key in read_only_variables:
row = await db.fetchone('SELECT * FROM admin.settings') if type(value) == list:
joined = ",".join(value)
fields.append(f"{key} = '{joined}'")
if type(value) == int or type(value) == float:
fields.append(f"{key} = {value}")
if type(value) == bool:
fields.append(f"{key} = {'true' if value else 'false'}")
if type(value) == str:
value = value.replace("'", "")
fields.append(f"{key} = '{value}'")
q = ", ".join(fields)
print("UPDATE", q)
await db.execute(f"UPDATE admin.settings SET {q}")
row = await db.fetchone("SELECT * FROM admin.settings")
assert row, "Newly updated settings couldn't be retrieved" assert row, "Newly updated settings couldn't be retrieved"
return Settings(**row) if row else None return Settings(**row) if row else None
async def delete_settings():
await db.execute("DELETE FROM admin.settings")

View file

@ -1,10 +1,9 @@
from sqlite3 import Row
from typing import List, Optional
from fastapi import Query from fastapi import Query
from pydantic import BaseModel, Field from pydantic import BaseModel
class UpdateSettings(BaseModel): class UpdateSettings(BaseModel):
lnbits_backend_wallet_class: str = Query(None)
lnbits_admin_users: str = Query(None) lnbits_admin_users: str = Query(None)
lnbits_allowed_users: str = Query(None) lnbits_allowed_users: str = Query(None)
lnbits_admin_ext: str = Query(None) lnbits_admin_ext: str = Query(None)
@ -15,11 +14,11 @@ class UpdateSettings(BaseModel):
lnbits_reserve_fee_percent: float = Query(None, ge=0) lnbits_reserve_fee_percent: float = Query(None, ge=0)
lnbits_service_fee: float = Query(None, ge=0) lnbits_service_fee: float = Query(None, ge=0)
lnbits_hide_api: bool = Query(None) lnbits_hide_api: bool = Query(None)
lnbits_site_title: str = Query("LNbits") lnbits_site_title: str = Query(None)
lnbits_site_tagline: str = Query("free and open-source lightning wallet") lnbits_site_tagline: str = Query(None)
lnbits_site_description: str = Query(None) lnbits_site_description: str = Query(None)
lnbits_default_wallet_name: str = Query("LNbits wallet") lnbits_default_wallet_name: str = Query(None)
lnbits_denomination: str = Query("sats") lnbits_denomination: str = Query(None)
lnbits_theme: str = Query(None) lnbits_theme: str = Query(None)
lnbits_custom_logo: str = Query(None) lnbits_custom_logo: str = Query(None)
lnbits_ad_space: str = Query(None) lnbits_ad_space: str = Query(None)

View file

@ -24,6 +24,7 @@
<p>Active Funding<small> (Requires server restart)</small></p> <p>Active Funding<small> (Requires server restart)</small></p>
<q-select <q-select
filled filled
name="lnbits_backend_wallet_class"
v-model="data.settings.lnbits_backend_wallet_class" v-model="data.settings.lnbits_backend_wallet_class"
hint="Select the active funding wallet" hint="Select the active funding wallet"
:options="data.settings.lnbits_allowed_funding_sources" :options="data.settings.lnbits_allowed_funding_sources"
@ -37,6 +38,7 @@
dense dense
type="number" type="number"
filled filled
name="lnbits_reserve_fee_min"
v-model="data.settings.lnbits_reserve_fee_min" v-model="data.settings.lnbits_reserve_fee_min"
label="Reserve fee in msats" label="Reserve fee in msats"
></q-input> ></q-input>
@ -46,6 +48,7 @@
dense dense
type="number" type="number"
filled filled
name="lnbits_reserve_fee_percent"
v-model="data.settings.lnbits_reserve_fee_percent" v-model="data.settings.lnbits_reserve_fee_percent"
label="Reserve fee in percent" label="Reserve fee in percent"
step="0.1" step="0.1"

View file

@ -4,8 +4,12 @@
<div class="col q-gutter-y-md"> <div class="col q-gutter-y-md">
<q-btn label="Save" flat @click="updateSettings"></q-btn> <q-btn label="Save" flat @click="updateSettings"></q-btn>
<q-btn label="Restart server" flat @click="restartServer"></q-btn> <q-btn label="Restart server" flat @click="restartServer"></q-btn>
<q-btn label="Reset to defaults" flat @click="restartServer"></q-btn> <q-btn label="Reset to defaults" flat @click="deleteSettings"></q-btn>
<q-btn label="Download Database Backup" flat @click="restartServer"></q-btn> <q-btn
label="Download Database Backup"
flat
@click="downloadBackup"
></q-btn>
</div> </div>
</div> </div>
<div class="row q-col-gutter-md justify-center"> <div class="row q-col-gutter-md justify-center">
@ -37,7 +41,7 @@
</q-tabs> </q-tabs>
</div> </div>
</div> </div>
<q-form> <q-form name="settings_form" id="settings_form">
<q-tab-panels v-model="tab" animated> <q-tab-panels v-model="tab" animated>
{% include "admin/_tab_funding.html" %} {% include {% include "admin/_tab_funding.html" %} {% include
"admin/_tab_users.html" %} {% include "admin/_tab_server.html" %} {% "admin/_tab_users.html" %} {% include "admin/_tab_server.html" %} {%
@ -111,8 +115,7 @@
LNbits.api LNbits.api
.request( .request(
'GET', 'GET',
'/admin/api/v1/admin/restart/', '/admin/api/v1/restart/?usr=' + this.g.user.id,
this.g.user.wallets[0].adminkey
) )
.then(response => { .then(response => {
this.$q.notify({ this.$q.notify({
@ -129,8 +132,7 @@
LNbits.api LNbits.api
.request( .request(
'POST', 'POST',
'/admin/api/v1/admin/topup/', '/admin/api/v1/topup/?usr=' + this.g.user.id,
this.g.user.wallets[0].adminkey,
this.wallet.id, this.wallet.id,
this.wallet.amount, this.wallet.amount,
) )
@ -151,11 +153,18 @@
}) })
}, },
updateSettings() { updateSettings() {
let data = {} const formElement = document.getElementById('settings_form');
const formData = new FormData(formElement);
const data = {};
formData.forEach((value, key) => (data[key] = value));
// only for debugging
for (const [key, value] of formData) {
console.log(`${key}: ${value}\n`);
}
LNbits.api LNbits.api
.request( .request(
'PUT', 'PUT',
'/admin/api/v1/admin/', '/admin/api/v1/settings/?usr=' + this.g.user.id,
this.g.user.wallets[0].adminkey, this.g.user.wallets[0].adminkey,
data data
) )
@ -169,6 +178,40 @@
.catch(function (error) { .catch(function (error) {
LNbits.utils.notifyApiError(error) LNbits.utils.notifyApiError(error)
}); });
},
deleteSettings() {
LNbits.api
.request(
'DELETE',
'/admin/api/v1/settings/?usr=' + this.g.user.id
)
.then(response => {
this.$q.notify({
type: 'positive',
message: 'Success! Restored settings to defaults, restart required!',
icon: null
})
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
});
},
downloadBackup() {
LNbits.api
.request(
'GET',
'/admin/api/v1/backup/?usr=' + this.g.user.id
)
.then(response => {
this.$q.notify({
type: 'positive',
message: 'Success! Database backup request, download starts soon!',
icon: null
})
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
});
} }
} }
}) })

View file

@ -1,7 +1,7 @@
from http import HTTPStatus from http import HTTPStatus
from loguru import logger
from fastapi import Body, Depends, Request from fastapi import Body, Depends, Request
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
@ -13,18 +13,16 @@ from lnbits.requestvars import g
from lnbits.server import server_restart from lnbits.server import server_restart
from lnbits.settings import settings from lnbits.settings import settings
from .crud import update_settings, update_wallet_balance from .crud import delete_settings, update_settings, update_wallet_balance
@admin_ext.get("/api/v1/admin/restart/", status_code=HTTPStatus.OK) @admin_ext.get("/api/v1/restart/", status_code=HTTPStatus.OK)
async def api_restart_server( async def api_restart_server(user: User = Depends(check_admin)):
user: User = Depends(check_admin)
):
server_restart.set() server_restart.set()
return {"status": "Success"} return {"status": "Success"}
@admin_ext.put("/api/v1/admin/topup/", status_code=HTTPStatus.OK) @admin_ext.put("/api/v1/topup/", status_code=HTTPStatus.OK)
async def api_update_balance( async def api_update_balance(
wallet_id, topup_amount: int, user: User = Depends(check_admin) wallet_id, topup_amount: int, user: User = Depends(check_admin)
): ):
@ -32,7 +30,7 @@ async def api_update_balance(
wallet = await get_wallet(wallet_id) wallet = await get_wallet(wallet_id)
except: except:
raise HTTPException( raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="wallet: {wallet_id} 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=wallet_id, amount=int(topup_amount))
@ -40,13 +38,23 @@ async def api_update_balance(
return {"status": "Success"} return {"status": "Success"}
@admin_ext.put("/api/v1/admin/", status_code=HTTPStatus.OK) @admin_ext.put("/api/v1/settings/", status_code=HTTPStatus.OK)
async def api_update_admin( async def api_update_settings(
request: Request,
user: User = Depends(check_admin), user: User = Depends(check_admin),
data: UpdateSettings = Body(...), data: UpdateSettings = Body(...),
): ):
updated = await update_settings(data) await update_settings(data)
g().settings = g().settings.copy(update=updated.dict())
return {"status": "Success"} return {"status": "Success"}
@admin_ext.delete("/api/v1/settings/", status_code=HTTPStatus.OK)
async def api_delete_settings(
user: User = Depends(check_admin),
):
await delete_settings()
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"}