From 947dc50d2e6598e52e36d86741d6c12a9cd6b67d Mon Sep 17 00:00:00 2001
From: Gene Takavic <80261724+iWarpBTC@users.noreply.github.com>
Date: Mon, 12 Sep 2022 17:14:24 +0200
Subject: [PATCH 001/691] readme update
---
lnbits/extensions/boltcards/README.md | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/lnbits/extensions/boltcards/README.md b/lnbits/extensions/boltcards/README.md
index f9c59409..a7302906 100644
--- a/lnbits/extensions/boltcards/README.md
+++ b/lnbits/extensions/boltcards/README.md
@@ -10,18 +10,17 @@ This extension allows you to link your Bolt Card (or other compatible NXP NTAG d
## About the keys
-Up to five 16-byte keys can be stored on the card, numbered from 00 to 04. In the empty state they all should be set to zeros (00000000000000000000000000000000). For this extension only two keys need to be set:
+Up to five 16-byte keys can be stored on the card, numbered from 00 to 04. In the empty state they all should be set to zeros (00000000000000000000000000000000). For this extension only two keys need to be set, but for the security reasons all five keys should be changed from default (empty) state. The keys directly needed by this extension are:
-One for encrypting the card UID and the counter (p parameter), let's called it meta key, key #01 or K1.
+- One for encrypting the card UID and the counter (p parameter), let's called it meta key, key #01 or K1.
-One for calculating CMAC (c parameter), let's called it file key, key #02 or K2.
+- One for calculating CMAC (c parameter), let's called it file key, key #02 or K2.
-The key #00, K0 (also know as auth key) is skipped to be use as authentification key. Is not needed by this extension, but can be filled in order to write the keys in cooperation with bolt-nfc-android-app.
+The key #00, K0 (also know as auth key) is skipped to be used as authentification key. It is not needed by this extension, but should be filled in order to write the keys in cooperation with bolt-nfc-android-app. In this case also K3 is set to same value as K1 and K4 as K2, so all keys are changed from default values. Keep that in your mind in case you need to reset the keys manually.
***Always backup all keys that you're trying to write on the card. Without them you may not be able to change them in the future!***
## Setting the card - bolt-nfc-android-app (easy way)
-So far, regarding the keys, the app can only write a new key set on an empty card (with zero keys). **When you write non zero (and 'non debug') keys, they can't be rewrite with this app.** You have to do it on your computer.
- Read the card with the app. Note UID so you can fill it in the extension later.
- Write the link on the card. It shoud be like `YOUR_LNBITS_DOMAIN/boltcards/api/v1/scan/{external_id}`
@@ -35,10 +34,10 @@ So far, regarding the keys, the app can only write a new key set on an empty car
- If on an Android device with a newish version of Chrome, you can click the icon next to the input and tap your card to autofill this field.
- Advanced Options
- Card Keys (k0, k1, k2) will be automatically generated if not explicitly set.
- - Set to 16 bytes of 0s (00000000000000000000000000000000) to leave the keys in debug mode.
- - GENERATE KEY button fill the keys randomly. If there is "debug" in the card name, a debug set of keys is filled instead.
+ - Set to 16 bytes of 0s (00000000000000000000000000000000) to leave the keys in default state.
+ - GENERATE KEY button fill the keys randomly. If there is "debug" in the card name, a debug set of keys is filled instead.
- Click CREATE CARD button
-- Click the QR code button next to a card to view its details. You can scan the QR code with the Android app to import the keys.
+- Click the QR code button next to a card to view its details. Backup the keys! You can scan the QR code with the Android app to import the keys.
- Click the "KEYS / AUTH LINK" button to copy the auth URL to the clipboard. You can then paste this into the Android app to import the keys.
- Tap the NFC card to write the keys to the card.
@@ -48,7 +47,7 @@ Follow the guide.
The URI should be `lnurlw://YOUR-DOMAIN.COM/boltcards/api/v1/scan/{YOUR_card_external_id}?p=00000000000000000000000000000000&c=0000000000000000`
-Then fill up the card parameters in the extension. Card Auth key (K0) can be omitted. Initical counter can be 0.
+Then fill up the card parameters in the extension. Card Auth key (K0) can be filled just for the record. Initical counter can be 0.
## Setting the card - android NXP app (hard way)
- If you don't know the card ID, use NXP TagInfo app to find it out.
From e1eb0895890c068a29ee32f4fe7910698522da0e Mon Sep 17 00:00:00 2001
From: Gene Takavic <80261724+iWarpBTC@users.noreply.github.com>
Date: Mon, 12 Sep 2022 22:44:22 +0200
Subject: [PATCH 002/691] readme minor changes
---
lnbits/extensions/boltcards/README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lnbits/extensions/boltcards/README.md b/lnbits/extensions/boltcards/README.md
index a7302906..8e093f3e 100644
--- a/lnbits/extensions/boltcards/README.md
+++ b/lnbits/extensions/boltcards/README.md
@@ -34,7 +34,7 @@ The key #00, K0 (also know as auth key) is skipped to be used as authentificatio
- If on an Android device with a newish version of Chrome, you can click the icon next to the input and tap your card to autofill this field.
- Advanced Options
- Card Keys (k0, k1, k2) will be automatically generated if not explicitly set.
- - Set to 16 bytes of 0s (00000000000000000000000000000000) to leave the keys in default state.
+ - Set to 16 bytes of 0s (00000000000000000000000000000000) to leave the keys in default (empty) state.
- GENERATE KEY button fill the keys randomly. If there is "debug" in the card name, a debug set of keys is filled instead.
- Click CREATE CARD button
- Click the QR code button next to a card to view its details. Backup the keys! You can scan the QR code with the Android app to import the keys.
@@ -47,7 +47,7 @@ Follow the guide.
The URI should be `lnurlw://YOUR-DOMAIN.COM/boltcards/api/v1/scan/{YOUR_card_external_id}?p=00000000000000000000000000000000&c=0000000000000000`
-Then fill up the card parameters in the extension. Card Auth key (K0) can be filled just for the record. Initical counter can be 0.
+Then fill up the card parameters in the extension. Card Auth key (K0) can be filled in the extension just for the record. Initical counter can be 0.
## Setting the card - android NXP app (hard way)
- If you don't know the card ID, use NXP TagInfo app to find it out.
From 3660d96295ea75be08cd1e55b7899da60cd66eb9 Mon Sep 17 00:00:00 2001
From: Gene Takavic
Date: Tue, 20 Sep 2022 15:53:57 +0200
Subject: [PATCH 003/691] rename setting app + delete msg
---
lnbits/extensions/boltcards/README.md | 6 +++---
lnbits/extensions/boltcards/static/js/index.js | 2 +-
lnbits/extensions/boltcards/templates/boltcards/index.html | 2 +-
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/lnbits/extensions/boltcards/README.md b/lnbits/extensions/boltcards/README.md
index 8e093f3e..c6d12311 100644
--- a/lnbits/extensions/boltcards/README.md
+++ b/lnbits/extensions/boltcards/README.md
@@ -6,7 +6,7 @@ This extension allows you to link your Bolt Card (or other compatible NXP NTAG d
**Disclaimer:** ***Use this only if you either know what you are doing or are a reckless lightning pioneer. Only you are responsible for all your sats, cards and other devices. Always backup all your card keys!***
-***In order to use this extension you need to be able to setup your own card.*** That means writing a URL template pointing to your LNBits instance, configuring some SUN (SDM) settings and optionally changing the card's keys. There's a [guide](https://www.whitewolftech.com/articles/payment-card/) to set it up with a card reader connected to your computer. It can be done (without setting the keys) with [TagWriter app by NXP](https://play.google.com/store/apps/details?id=com.nxp.nfc.tagwriter) Android app. Last but not least, an OSS android app by name [bolt-nfc-android-app](https://github.com/boltcard/bolt-nfc-android-app) is being developed for these purposes. It's available from Google Play [here](https://play.google.com/store/apps/details?id=com.lightningnfcapp).
+***In order to use this extension you need to be able to setup your own card.*** That means writing a URL template pointing to your LNBits instance, configuring some SUN (SDM) settings and optionally changing the card's keys. There's a [guide](https://www.whitewolftech.com/articles/payment-card/) to set it up with a card reader connected to your computer. It can be done (without setting the keys) with [TagWriter app by NXP](https://play.google.com/store/apps/details?id=com.nxp.nfc.tagwriter) Android app. Last but not least, an OSS android app by name [Boltcard NFC Card Creator](https://github.com/boltcard/bolt-nfc-android-app) is being developed for these purposes. It's available from Google Play [here](https://play.google.com/store/apps/details?id=com.lightningnfcapp).
## About the keys
@@ -16,11 +16,11 @@ Up to five 16-byte keys can be stored on the card, numbered from 00 to 04. In th
- One for calculating CMAC (c parameter), let's called it file key, key #02 or K2.
-The key #00, K0 (also know as auth key) is skipped to be used as authentification key. It is not needed by this extension, but should be filled in order to write the keys in cooperation with bolt-nfc-android-app. In this case also K3 is set to same value as K1 and K4 as K2, so all keys are changed from default values. Keep that in your mind in case you need to reset the keys manually.
+The key #00, K0 (also know as auth key) is skipped to be used as authentification key. It is not needed by this extension, but should be filled in order to write the keys in cooperation with Boltcard NFC Card Creator. In this case also K3 is set to same value as K1 and K4 as K2, so all keys are changed from default values. Keep that in your mind in case you need to reset the keys manually.
***Always backup all keys that you're trying to write on the card. Without them you may not be able to change them in the future!***
-## Setting the card - bolt-nfc-android-app (easy way)
+## Setting the card - Boltcard NFC Card Creator (easy way)
- Read the card with the app. Note UID so you can fill it in the extension later.
- Write the link on the card. It shoud be like `YOUR_LNBITS_DOMAIN/boltcards/api/v1/scan/{external_id}`
diff --git a/lnbits/extensions/boltcards/static/js/index.js b/lnbits/extensions/boltcards/static/js/index.js
index 11df222a..2ecde39d 100644
--- a/lnbits/extensions/boltcards/static/js/index.js
+++ b/lnbits/extensions/boltcards/static/js/index.js
@@ -398,7 +398,7 @@ new Vue({
let cards = _.findWhere(this.cards, {id: cardId})
LNbits.utils
- .confirmDialog('Are you sure you want to delete this card')
+ .confirmDialog('Are you sure you want to delete this card? Without access to the card keys you won\'t be able to reset them in the future!')
.onOk(function () {
LNbits.api
.request(
diff --git a/lnbits/extensions/boltcards/templates/boltcards/index.html b/lnbits/extensions/boltcards/templates/boltcards/index.html
index 55cc1e5e..3e07024c 100644
--- a/lnbits/extensions/boltcards/templates/boltcards/index.html
+++ b/lnbits/extensions/boltcards/templates/boltcards/index.html
@@ -370,7 +370,7 @@
bolt-nfc-android-appBoltcard NFC Card Creator)
From 632d35682d84c981b926ef47f8e6fc9d274b948e Mon Sep 17 00:00:00 2001
From: Gene Takavic
Date: Fri, 23 Sep 2022 15:17:21 +0200
Subject: [PATCH 004/691] payment notification webhook
---
lnbits/extensions/boltcards/crud.py | 6 +++--
lnbits/extensions/boltcards/lnurl.py | 23 ++++++++++++++++++-
lnbits/extensions/boltcards/migrations.py | 8 +++++++
lnbits/extensions/boltcards/models.py | 2 ++
.../extensions/boltcards/static/js/index.js | 8 +++++--
.../boltcards/templates/boltcards/index.html | 12 +++++++++-
6 files changed, 53 insertions(+), 6 deletions(-)
diff --git a/lnbits/extensions/boltcards/crud.py b/lnbits/extensions/boltcards/crud.py
index c541346e..39ee3f40 100644
--- a/lnbits/extensions/boltcards/crud.py
+++ b/lnbits/extensions/boltcards/crud.py
@@ -27,9 +27,10 @@ async def create_card(data: CreateCardData, wallet_id: str) -> Card:
k0,
k1,
k2,
- otp
+ otp,
+ webhook_url
)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
card_id,
@@ -45,6 +46,7 @@ async def create_card(data: CreateCardData, wallet_id: str) -> Card:
data.k1,
data.k2,
secrets.token_hex(16),
+ data.webhook_url,
),
)
card = await get_card(card_id)
diff --git a/lnbits/extensions/boltcards/lnurl.py b/lnbits/extensions/boltcards/lnurl.py
index 6fb9ad8d..be3e09d8 100644
--- a/lnbits/extensions/boltcards/lnurl.py
+++ b/lnbits/extensions/boltcards/lnurl.py
@@ -8,6 +8,7 @@ from io import BytesIO
from typing import Optional
from urllib.parse import urlparse
+import httpx
from embit import bech32, compact
from fastapi import Request
from fastapi.param_functions import Query
@@ -119,12 +120,32 @@ async def lnurl_callback(
invoice = bolt11.decode(pr)
hit = await spend_hit(id=hit.id, amount=int(invoice.amount_msat / 1000))
try:
- await pay_invoice(
+ payment_hash = await pay_invoice(
wallet_id=card.wallet,
payment_request=pr,
max_sat=card.tx_limit,
extra={"tag": "boltcard", "tag": hit.id},
)
+
+ if card.webhook_url:
+ async with httpx.AsyncClient() as client:
+ try:
+ r = await client.post(
+ card.webhook_url,
+ json={
+ "notification": "card_payment",
+ "payment_hash": payment_hash,
+ "payment_request": pr,
+ "card_external_id": card.external_id,
+ "card_name": card.card_name,
+ "amount": int(invoice.amount_msat / 1000),
+ },
+ timeout=40,
+ )
+ except Exception as exc:
+ # webhook fails shouldn't cause the lnurlw to fail since invoice is already paid
+ logger.error("Caught exception when dispatching webhook url:", exc)
+
return {"status": "OK"}
except:
return {"status": "ERROR", "reason": f"Payment failed"}
diff --git a/lnbits/extensions/boltcards/migrations.py b/lnbits/extensions/boltcards/migrations.py
index 08126013..25a59fdb 100644
--- a/lnbits/extensions/boltcards/migrations.py
+++ b/lnbits/extensions/boltcards/migrations.py
@@ -58,3 +58,11 @@ async def m001_initial(db):
);
"""
)
+
+
+async def m002_add_webhook(db):
+ await db.execute(
+ """
+ ALTER TABLE boltcards.cards ADD COLUMN webhook_url TEXT NOT NULL DEFAULT '';
+ """
+ )
diff --git a/lnbits/extensions/boltcards/models.py b/lnbits/extensions/boltcards/models.py
index 47ca1df0..8e6f77c9 100644
--- a/lnbits/extensions/boltcards/models.py
+++ b/lnbits/extensions/boltcards/models.py
@@ -30,6 +30,7 @@ class Card(BaseModel):
prev_k1: str
prev_k2: str
otp: str
+ webhook_url: str
time: int
def from_row(cls, row: Row) -> "Card":
@@ -56,6 +57,7 @@ class CreateCardData(BaseModel):
prev_k0: str = Query(ZERO_KEY)
prev_k1: str = Query(ZERO_KEY)
prev_k2: str = Query(ZERO_KEY)
+ webhook_url: str = Query(...)
class Hit(BaseModel):
diff --git a/lnbits/extensions/boltcards/static/js/index.js b/lnbits/extensions/boltcards/static/js/index.js
index 2ecde39d..e13c14fb 100644
--- a/lnbits/extensions/boltcards/static/js/index.js
+++ b/lnbits/extensions/boltcards/static/js/index.js
@@ -23,6 +23,7 @@ new Vue({
cardDialog: {
show: false,
data: {
+ webhook_url: '',
counter: 1,
k0: '',
k1: '',
@@ -270,7 +271,8 @@ new Vue({
k1: card.k1,
k2: card.k2,
k3: card.k1,
- k4: card.k2
+ k4: card.k2,
+ webhook_url: card.webhook_url
}
this.qrCodeDialog.show = true
},
@@ -398,7 +400,9 @@ new Vue({
let cards = _.findWhere(this.cards, {id: cardId})
LNbits.utils
- .confirmDialog('Are you sure you want to delete this card? Without access to the card keys you won\'t be able to reset them in the future!')
+ .confirmDialog(
+ "Are you sure you want to delete this card? Without access to the card keys you won't be able to reset them in the future!"
+ )
.onOk(function () {
LNbits.api
.request(
diff --git a/lnbits/extensions/boltcards/templates/boltcards/index.html b/lnbits/extensions/boltcards/templates/boltcards/index.html
index 3e07024c..f795e454 100644
--- a/lnbits/extensions/boltcards/templates/boltcards/index.html
+++ b/lnbits/extensions/boltcards/templates/boltcards/index.html
@@ -283,7 +283,7 @@
v-model="toggleAdvanced"
label="Show advanced options"
>
-
+
Zero if you don't know.
+
+
Lock key: {{ qrCodeDialog.data.k0 }}
Meta key: {{ qrCodeDialog.data.k1 }}
File key: {{ qrCodeDialog.data.k2 }}
+ Notification webhook: {{ qrCodeDialog.data.webhook_url
+ }}
Date: Fri, 23 Sep 2022 16:19:58 +0200
Subject: [PATCH 005/691] Update README.md
Updated for Boltcard NFC Card Creator v0.1.1
---
lnbits/extensions/boltcards/README.md | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/lnbits/extensions/boltcards/README.md b/lnbits/extensions/boltcards/README.md
index c6d12311..5140ecc2 100644
--- a/lnbits/extensions/boltcards/README.md
+++ b/lnbits/extensions/boltcards/README.md
@@ -21,10 +21,7 @@ The key #00, K0 (also know as auth key) is skipped to be used as authentificatio
***Always backup all keys that you're trying to write on the card. Without them you may not be able to change them in the future!***
## Setting the card - Boltcard NFC Card Creator (easy way)
-
-- Read the card with the app. Note UID so you can fill it in the extension later.
-- Write the link on the card. It shoud be like `YOUR_LNBITS_DOMAIN/boltcards/api/v1/scan/{external_id}`
- - `{external_id}` should be replaced with the External ID found in the LNBits dialog.
+Updated for v0.1.1
- Add new card in the extension.
- Set a max sats per transaction. Any transaction greater than this amount will be rejected.
@@ -32,14 +29,16 @@ The key #00, K0 (also know as auth key) is skipped to be used as authentificatio
- Set a card name. This is just for your reference inside LNBits.
- Set the card UID. This is the unique identifier on your NFC card and is 7 bytes.
- If on an Android device with a newish version of Chrome, you can click the icon next to the input and tap your card to autofill this field.
+ - Otherwise read it with the Android app (Advanced -> Read NFC) and paste it to the field.
- Advanced Options
- Card Keys (k0, k1, k2) will be automatically generated if not explicitly set.
- - Set to 16 bytes of 0s (00000000000000000000000000000000) to leave the keys in default (empty) state.
- - GENERATE KEY button fill the keys randomly. If there is "debug" in the card name, a debug set of keys is filled instead.
+ - Set to 16 bytes of 0s (00000000000000000000000000000000) to leave the keys in default (empty) state (this is unsecure).
+ - GENERATE KEY button fill the keys randomly.
- Click CREATE CARD button
-- Click the QR code button next to a card to view its details. Backup the keys! You can scan the QR code with the Android app to import the keys.
-- Click the "KEYS / AUTH LINK" button to copy the auth URL to the clipboard. You can then paste this into the Android app to import the keys.
-- Tap the NFC card to write the keys to the card.
+- Click the QR code button next to a card to view its details. Backup the keys now! They'll be comfortable in your password manager.
+ - Now you can scan the QR code with the Android app (Create Bolt Card -> SCAN QR CODE).
+ - Or you can Click the "KEYS / AUTH LINK" button to copy the auth URL to the clipboard. Then paste it into the Android app (Create Bolt Card -> PASTE AUTH URL).
+- Click WRITE CARD NOW and tap the NFC card to set it up. DO NOT REMOVE THE CARD PREMATURELY!
## Setting the card - computer (hard way)
@@ -69,4 +68,4 @@ Then fill up the card parameters in the extension. Card Auth key (K0) can be fil
- Save & Write
- Scan with compatible Wallet
-This app afaik cannot change the keys. If you cannot change them any other way, leave them empty in the extension dialog and remember you're not secure. Card Auth key (K0) can be omitted anyway. Initical counter can be 0.
+This app afaik cannot change the keys. If you cannot change them any other way, leave them empty in the extension dialog and remember you're not secured. Card Auth key (K0) can be omitted anyway. Initical counter can be 0.
From ea2d66fbd628681618dbd411f544f63ee8692a5f Mon Sep 17 00:00:00 2001
From: Gene Takavic
Date: Fri, 23 Sep 2022 17:11:19 +0200
Subject: [PATCH 006/691] refund notification
---
lnbits/extensions/boltcards/tasks.py | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/lnbits/extensions/boltcards/tasks.py b/lnbits/extensions/boltcards/tasks.py
index 1b51c98b..27929efc 100644
--- a/lnbits/extensions/boltcards/tasks.py
+++ b/lnbits/extensions/boltcards/tasks.py
@@ -2,12 +2,13 @@ import asyncio
import json
import httpx
+from loguru import logger
from lnbits.core import db as core_db
from lnbits.core.models import Payment
from lnbits.tasks import register_invoice_listener
-from .crud import create_refund, get_hit
+from .crud import create_refund, get_card, get_hit
async def wait_for_paid_invoices():
@@ -34,6 +35,25 @@ async def on_invoice_paid(payment: Payment) -> None:
)
await mark_webhook_sent(payment, 1)
+ card = await get_card(hit.card_id)
+ if card.webhook_url:
+ async with httpx.AsyncClient() as client:
+ try:
+ r = await client.post(
+ card.webhook_url,
+ json={
+ "notification": "card_refund",
+ "payment_hash": payment.payment_hash,
+ "payment_request": payment.bolt11,
+ "card_external_id": card.external_id,
+ "card_name": card.card_name,
+ "amount": int(payment.amount / 1000),
+ },
+ timeout=40,
+ )
+ except Exception as exc:
+ logger.error("Caught exception when dispatching webhook url:", exc)
+
async def mark_webhook_sent(payment: Payment, status: int) -> None:
payment.extra["wh_status"] = status
From 8b3af03519c06437325e32e78a71febf9f91d3a1 Mon Sep 17 00:00:00 2001
From: Gene Takavic
Date: Sun, 25 Sep 2022 17:01:22 +0200
Subject: [PATCH 007/691] webhook to pay_invoice
---
lnbits/core/services.py | 31 ++++++++++++++++-
lnbits/extensions/boltcards/lnurl.py | 42 ++++++++----------------
lnbits/extensions/boltcards/views_api.py | 5 ---
lnbits/extensions/withdraw/lnurl.py | 30 +++++++----------
4 files changed, 56 insertions(+), 52 deletions(-)
diff --git a/lnbits/core/services.py b/lnbits/core/services.py
index 10693f4b..aeb4f938 100644
--- a/lnbits/core/services.py
+++ b/lnbits/core/services.py
@@ -2,7 +2,7 @@ import asyncio
import json
from binascii import unhexlify
from io import BytesIO
-from typing import Dict, Optional, Tuple
+from typing import Dict, Optional, Tuple, Union
from urllib.parse import parse_qs, urlparse
import httpx
@@ -102,6 +102,7 @@ async def pay_invoice(
extra: Optional[Dict] = None,
description: str = "",
conn: Optional[Connection] = None,
+ webhook: Optional[Union[str, tuple]] = None,
) -> str:
"""
Pay a Lightning invoice.
@@ -231,6 +232,34 @@ async def pay_invoice(
f"didn't receive checking_id from backend, payment may be stuck in database: {temp_id}"
)
+ if type(webhook) is str:
+ webhook_url = webhook
+ elif type(webhook) is tuple:
+ webhook_url = webhook[0]
+ additionals = webhook[1]
+ else:
+ webhook_url = None
+
+ if webhook_url:
+ async with httpx.AsyncClient() as client:
+ try:
+ json = {
+ "payment_hash": invoice.payment_hash,
+ "payment_request": payment_request,
+ "amount": int(invoice.amount_msat / 1000),
+ }
+ if type(additionals) is dict:
+ json.update(additionals)
+
+ r = await client.post(
+ webhook_url,
+ json=json,
+ timeout=40,
+ )
+ except Exception as exc:
+ # webhook fails shouldn't cause the lnurlw to fail since invoice is already paid
+ logger.error("Caught exception when dispatching webhook url:", exc)
+
return invoice.payment_hash
diff --git a/lnbits/extensions/boltcards/lnurl.py b/lnbits/extensions/boltcards/lnurl.py
index be3e09d8..320b1666 100644
--- a/lnbits/extensions/boltcards/lnurl.py
+++ b/lnbits/extensions/boltcards/lnurl.py
@@ -1,19 +1,12 @@
-import base64
-import hashlib
-import hmac
import json
import secrets
from http import HTTPStatus
-from io import BytesIO
-from typing import Optional
from urllib.parse import urlparse
-import httpx
from embit import bech32, compact
from fastapi import Request
from fastapi.param_functions import Query
from fastapi.params import Depends, Query
-from lnurl import Lnurl, LnurlWithdrawResponse
from lnurl import encode as lnurl_encode # type: ignore
from lnurl.types import LnurlPayMetadata # type: ignore
from loguru import logger
@@ -34,7 +27,6 @@ from .crud import (
get_hit,
get_hits_today,
spend_hit,
- update_card,
update_card_counter,
update_card_otp,
)
@@ -120,32 +112,26 @@ async def lnurl_callback(
invoice = bolt11.decode(pr)
hit = await spend_hit(id=hit.id, amount=int(invoice.amount_msat / 1000))
try:
- payment_hash = await pay_invoice(
+ webhook = (
+ (
+ card.webhook_url,
+ {
+ "notification": "card_payment",
+ "card_external_id": card.external_id,
+ "card_name": card.card_name,
+ },
+ )
+ if card.webhook_url
+ else None
+ )
+ await pay_invoice(
wallet_id=card.wallet,
payment_request=pr,
max_sat=card.tx_limit,
extra={"tag": "boltcard", "tag": hit.id},
+ webhook=webhook,
)
- if card.webhook_url:
- async with httpx.AsyncClient() as client:
- try:
- r = await client.post(
- card.webhook_url,
- json={
- "notification": "card_payment",
- "payment_hash": payment_hash,
- "payment_request": pr,
- "card_external_id": card.external_id,
- "card_name": card.card_name,
- "amount": int(invoice.amount_msat / 1000),
- },
- timeout=40,
- )
- except Exception as exc:
- # webhook fails shouldn't cause the lnurlw to fail since invoice is already paid
- logger.error("Caught exception when dispatching webhook url:", exc)
-
return {"status": "OK"}
except:
return {"status": "ERROR", "reason": f"Payment failed"}
diff --git a/lnbits/extensions/boltcards/views_api.py b/lnbits/extensions/boltcards/views_api.py
index 7b8357cf..2fc11dbc 100644
--- a/lnbits/extensions/boltcards/views_api.py
+++ b/lnbits/extensions/boltcards/views_api.py
@@ -12,21 +12,16 @@ from lnbits.decorators import WalletTypeInfo, get_key_type, require_admin_key
from . import boltcards_ext
from .crud import (
create_card,
- create_hit,
delete_card,
enable_disable_card,
get_card,
- get_card_by_otp,
get_card_by_uid,
get_cards,
get_hits,
get_refunds,
update_card,
- update_card_counter,
- update_card_otp,
)
from .models import CreateCardData
-from .nxp424 import decryptSUN, getSunMAC
@boltcards_ext.get("/api/v1/cards")
diff --git a/lnbits/extensions/withdraw/lnurl.py b/lnbits/extensions/withdraw/lnurl.py
index 18a99599..3379fd17 100644
--- a/lnbits/extensions/withdraw/lnurl.py
+++ b/lnbits/extensions/withdraw/lnurl.py
@@ -3,7 +3,6 @@ import traceback
from datetime import datetime
from http import HTTPStatus
-import httpx
import shortuuid # type: ignore
from fastapi import HTTPException
from fastapi.param_functions import Query
@@ -115,29 +114,24 @@ async def api_lnurl_callback(
payment_request = pr
- payment_hash = await pay_invoice(
+ webhook = (
+ (
+ link.webhook_url,
+ {
+ "lnurlw": link.id,
+ },
+ )
+ if link.webhook_url
+ else None
+ )
+ await pay_invoice(
wallet_id=link.wallet,
payment_request=payment_request,
max_sat=link.max_withdrawable,
extra={"tag": "withdraw"},
+ webhook=webhook,
)
- if link.webhook_url:
- async with httpx.AsyncClient() as client:
- try:
- r = await client.post(
- link.webhook_url,
- json={
- "payment_hash": payment_hash,
- "payment_request": payment_request,
- "lnurlw": link.id,
- },
- timeout=40,
- )
- except Exception as exc:
- # webhook fails shouldn't cause the lnurlw to fail since invoice is already paid
- logger.error("Caught exception when dispatching webhook url:", exc)
-
return {"status": "OK"}
except Exception as e:
From 0bede387f5ed5620781c50b689fc7016ad5d15af Mon Sep 17 00:00:00 2001
From: Gene Takavic <80261724+iWarpBTC@users.noreply.github.com>
Date: Sun, 25 Sep 2022 18:11:25 +0200
Subject: [PATCH 008/691] webhook to pay_invoice/fix
---
lnbits/core/services.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/lnbits/core/services.py b/lnbits/core/services.py
index aeb4f938..4f937ec3 100644
--- a/lnbits/core/services.py
+++ b/lnbits/core/services.py
@@ -232,6 +232,7 @@ async def pay_invoice(
f"didn't receive checking_id from backend, payment may be stuck in database: {temp_id}"
)
+ additionals = None
if type(webhook) is str:
webhook_url = webhook
elif type(webhook) is tuple:
From 5c6cd70d3bf08720a094c4aac263f53c583664e9 Mon Sep 17 00:00:00 2001
From: Gene Takavic
Date: Mon, 26 Sep 2022 11:47:00 +0200
Subject: [PATCH 009/691] disabling card with just otp which is also part of
notify
---
lnbits/extensions/boltcards/crud.py | 10 ++++++++--
lnbits/extensions/boltcards/lnurl.py | 3 +++
lnbits/extensions/boltcards/views_api.py | 18 ++++++++++++++++++
3 files changed, 29 insertions(+), 2 deletions(-)
diff --git a/lnbits/extensions/boltcards/crud.py b/lnbits/extensions/boltcards/crud.py
index 39ee3f40..0724ea04 100644
--- a/lnbits/extensions/boltcards/crud.py
+++ b/lnbits/extensions/boltcards/crud.py
@@ -114,8 +114,14 @@ async def get_card_by_external_id(external_id: str) -> Optional[Card]:
return Card.parse_obj(card)
-async def get_card_by_otp(otp: str) -> Optional[Card]:
- row = await db.fetchone("SELECT * FROM boltcards.cards WHERE otp = ?", (otp,))
+async def get_card_by_otp(otp: str, half: bool = False) -> Optional[Card]:
+ if half and len(otp) == 16:
+ otp = "%" + otp
+ row = await db.fetchone(
+ "SELECT * FROM boltcards.cards WHERE otp LIKE ?", (otp,)
+ )
+ else:
+ row = await db.fetchone("SELECT * FROM boltcards.cards WHERE otp = ?", (otp,))
if not row:
return None
diff --git a/lnbits/extensions/boltcards/lnurl.py b/lnbits/extensions/boltcards/lnurl.py
index 320b1666..064bde2c 100644
--- a/lnbits/extensions/boltcards/lnurl.py
+++ b/lnbits/extensions/boltcards/lnurl.py
@@ -119,6 +119,9 @@ async def lnurl_callback(
"notification": "card_payment",
"card_external_id": card.external_id,
"card_name": card.card_name,
+ "card_otp": card.otp[
+ -16:
+ ], # actually only half of the OTP is sent (full otp reveals the keys)
},
)
if card.webhook_url
diff --git a/lnbits/extensions/boltcards/views_api.py b/lnbits/extensions/boltcards/views_api.py
index 2fc11dbc..d7f5cf7c 100644
--- a/lnbits/extensions/boltcards/views_api.py
+++ b/lnbits/extensions/boltcards/views_api.py
@@ -15,11 +15,13 @@ from .crud import (
delete_card,
enable_disable_card,
get_card,
+ get_card_by_otp,
get_card_by_uid,
get_cards,
get_hits,
get_refunds,
update_card,
+ update_card_otp,
)
from .models import CreateCardData
@@ -111,6 +113,22 @@ async def enable_card(
return card.dict()
+@boltcards_ext.post("/api/v1/disablecard")
+async def disble_card_with_otp(a):
+ if len(a) < 16:
+ raise HTTPException(detail="Invalid OTP.", status_code=HTTPStatus.BAD_REQUEST)
+ card = await get_card_by_otp(a, half=True)
+ if not card:
+ raise HTTPException(detail="No card found.", status_code=HTTPStatus.NOT_FOUND)
+
+ new_otp = secrets.token_hex(16)
+ await update_card_otp(new_otp, card.id)
+
+ card = await enable_disable_card(enable=False, id=card.id)
+
+ return {"status": "OK"}
+
+
@boltcards_ext.delete("/api/v1/cards/{card_id}")
async def api_card_delete(card_id, wallet: WalletTypeInfo = Depends(require_admin_key)):
card = await get_card(card_id)
From 3b70d45091e6d69aac04a207c59e1115eba8c76f Mon Sep 17 00:00:00 2001
From: callebtc <93376500+callebtc@users.noreply.github.com>
Date: Tue, 4 Oct 2022 09:56:15 +0200
Subject: [PATCH 010/691] .env variable for STARTUP_INVOICE_EXPIRY_CHECK
---
.env.example | 2 ++
lnbits/settings.py | 1 +
lnbits/tasks.py | 4 ++--
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/.env.example b/.env.example
index 93b82325..1c7d1529 100644
--- a/.env.example
+++ b/.env.example
@@ -32,6 +32,8 @@ LNBITS_SERVICE_FEE="0.0"
LNBITS_RESERVE_FEE_MIN=2000
# value in percent
LNBITS_RESERVE_FEE_PERCENT=1.0
+# check invoice expiry on every startup (can be slow on large instances)
+STARTUP_INVOICE_EXPIRY_CHECK=True
# Change theme
LNBITS_SITE_TITLE="LNbits"
diff --git a/lnbits/settings.py b/lnbits/settings.py
index 3f4e31cc..9fc3c197 100644
--- a/lnbits/settings.py
+++ b/lnbits/settings.py
@@ -64,6 +64,7 @@ PREFER_SECURE_URLS = env.bool("LNBITS_FORCE_HTTPS", default=True)
RESERVE_FEE_MIN = env.int("LNBITS_RESERVE_FEE_MIN", default=2000)
RESERVE_FEE_PERCENT = env.float("LNBITS_RESERVE_FEE_PERCENT", default=1.0)
SERVICE_FEE = env.float("LNBITS_SERVICE_FEE", default=0.0)
+STARTUP_INVOICE_EXPIRY_CHECK = env.bool("STARTUP_INVOICE_EXPIRY_CHECK", default=True)
try:
LNBITS_COMMIT = (
diff --git a/lnbits/tasks.py b/lnbits/tasks.py
index 94e43dcf..26758303 100644
--- a/lnbits/tasks.py
+++ b/lnbits/tasks.py
@@ -15,7 +15,7 @@ from lnbits.core.crud import (
get_standalone_payment,
)
from lnbits.core.services import redeem_lnurl_withdraw
-from lnbits.settings import WALLET
+from lnbits.settings import WALLET, STARTUP_INVOICE_EXPIRY_CHECK
from .core import db
@@ -144,7 +144,7 @@ async def check_pending_payments():
f"Task: pending check finished for {len(pending_payments)} payments (took {time.time() - start_time:0.3f} s)"
)
# we delete expired invoices once upon the first pending check
- if incoming:
+ if incoming and STARTUP_INVOICE_EXPIRY_CHECK:
logger.debug("Task: deleting all expired invoices")
start_time: float = time.time()
await delete_expired_invoices(conn=conn)
From 166530eb0c985575a140124fb4c9e5a23ee9e5a7 Mon Sep 17 00:00:00 2001
From: benarc
Date: Mon, 7 Mar 2022 05:03:32 +0000
Subject: [PATCH 011/691] Added old admin extension
---
.env.example | 12 +-
lnbits/extensions/admin/README.md | 11 +
lnbits/extensions/admin/__init__.py | 10 +
lnbits/extensions/admin/config.json | 6 +
lnbits/extensions/admin/crud.py | 59 ++
lnbits/extensions/admin/migrations.py | 256 ++++++++
lnbits/extensions/admin/models.py | 38 ++
.../admin/templates/admin/index.html | 565 ++++++++++++++++++
lnbits/extensions/admin/views.py | 20 +
lnbits/extensions/admin/views_api.py | 41 ++
10 files changed, 1013 insertions(+), 5 deletions(-)
create mode 100644 lnbits/extensions/admin/README.md
create mode 100644 lnbits/extensions/admin/__init__.py
create mode 100644 lnbits/extensions/admin/config.json
create mode 100644 lnbits/extensions/admin/crud.py
create mode 100644 lnbits/extensions/admin/migrations.py
create mode 100644 lnbits/extensions/admin/models.py
create mode 100644 lnbits/extensions/admin/templates/admin/index.html
create mode 100644 lnbits/extensions/admin/views.py
create mode 100644 lnbits/extensions/admin/views_api.py
diff --git a/.env.example b/.env.example
index 93b82325..68e25ad1 100644
--- a/.env.example
+++ b/.env.example
@@ -3,10 +3,12 @@ PORT=5000
DEBUG=false
-LNBITS_ALLOWED_USERS=""
-LNBITS_ADMIN_USERS=""
-# Extensions only admin can access
-LNBITS_ADMIN_EXTENSIONS="ngrok"
+LNBITS_ADMIN_USERS="" # User IDs seperated by comma
+LNBITS_ADMIN_EXTENSIONS="ngrok" # Extensions only admin can access
+LNBITS_ADMIN_UI=false # Extensions only admin can access
+
+LNBITS_ALLOWED_USERS="" # Restricts access, User IDs seperated by comma
+
LNBITS_DEFAULT_WALLET_NAME="LNbits wallet"
# csv ad image filepaths or urls, extensions can choose to honor
@@ -91,4 +93,4 @@ LNBITS_DENOMINATION=sats
# EclairWallet
ECLAIR_URL=http://127.0.0.1:8283
-ECLAIR_PASS=eclairpw
\ No newline at end of file
+ECLAIR_PASS=eclairpw
diff --git a/lnbits/extensions/admin/README.md b/lnbits/extensions/admin/README.md
new file mode 100644
index 00000000..27729459
--- /dev/null
+++ b/lnbits/extensions/admin/README.md
@@ -0,0 +1,11 @@
+Example Extension
+*tagline*
+This is an example extension to help you organise and build you own.
+
+Try to include an image
+
+
+
+If your extension has API endpoints, include useful ones here
+
+curl -H "Content-type: application/json" -X POST https://YOUR-LNBITS/YOUR-EXTENSION/api/v1/EXAMPLE -d '{"amount":"100","memo":"example"}' -H "X-Api-Key: YOUR_WALLET-ADMIN/INVOICE-KEY"
diff --git a/lnbits/extensions/admin/__init__.py b/lnbits/extensions/admin/__init__.py
new file mode 100644
index 00000000..d5f26c90
--- /dev/null
+++ b/lnbits/extensions/admin/__init__.py
@@ -0,0 +1,10 @@
+from quart import Blueprint
+from lnbits.db import Database
+
+db = Database("ext_admin")
+
+admin_ext: Blueprint = Blueprint("admin", __name__, static_folder="static", template_folder="templates")
+
+
+from .views_api import * # noqa
+from .views import * # noqa
diff --git a/lnbits/extensions/admin/config.json b/lnbits/extensions/admin/config.json
new file mode 100644
index 00000000..69661733
--- /dev/null
+++ b/lnbits/extensions/admin/config.json
@@ -0,0 +1,6 @@
+{
+ "name": "Admin",
+ "short_description": "Manage your LNbits install",
+ "icon": "build",
+ "contributors": ["benarc"]
+}
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
new file mode 100644
index 00000000..cb8f9b5b
--- /dev/null
+++ b/lnbits/extensions/admin/crud.py
@@ -0,0 +1,59 @@
+from typing import List, Optional
+
+from . import db
+from .models import Admin, Funding
+from lnbits.settings import *
+from lnbits.helpers import urlsafe_short_hash
+from lnbits.core.crud import create_payment
+from lnbits.db import Connection
+
+
+def update_wallet_balance(wallet_id: str, amount: int) -> str:
+ temp_id = f"temp_{urlsafe_short_hash()}"
+ internal_id = f"internal_{urlsafe_short_hash()}"
+ 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,
+ )
+ return "success"
+
+
+async def update_admin(
+) -> Optional[Admin]:
+ if not CLightningWallet:
+ print("poo")
+ await db.execute(
+ """
+ UPDATE admin
+ SET user = ?, site_title = ?, site_tagline = ?, site_description = ?, allowed_users = ?, default_wallet_name = ?, data_folder = ?, disabled_ext = ?, force_https = ?, service_fee = ?, funding_source = ?
+ WHERE 1
+ """,
+ (
+
+ ),
+ )
+ row = await db.fetchone("SELECT * FROM admin WHERE 1")
+ return Admin.from_row(row) if row else None
+
+async def update_admin(admin_id: str, **kwargs) -> Optional[Admin]:
+ q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
+ await db.execute(
+ f"UPDATE jukebox.jukebox SET {q} WHERE id = ?", (*kwargs.values(), juke_id)
+ )
+ row = await db.fetchone("SELECT * FROM jukebox.jukebox WHERE id = ?", (juke_id,))
+ return Jukebox(**row) if row else None
+
+async def get_admin() -> List[Admin]:
+ row = await db.fetchone("SELECT * FROM admin WHERE 1")
+ return Admin.from_row(row) if row else None
+
+
+async def get_funding() -> List[Funding]:
+ rows = await db.fetchall("SELECT * FROM funding")
+
+ return [Funding.from_row(row) for row in rows]
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
new file mode 100644
index 00000000..82d934cb
--- /dev/null
+++ b/lnbits/extensions/admin/migrations.py
@@ -0,0 +1,256 @@
+from sqlalchemy.exc import OperationalError # type: ignore
+from os import getenv
+from lnbits.helpers import urlsafe_short_hash
+
+
+async def m001_create_admin_table(db):
+ user = None
+ site_title = None
+ site_tagline = None
+ site_description = None
+ allowed_users = None
+ admin_user = None
+ default_wallet_name = None
+ data_folder = None
+ disabled_ext = None
+ force_https = True
+ service_fee = 0
+ funding_source = ""
+
+ if getenv("LNBITS_SITE_TITLE"):
+ site_title = getenv("LNBITS_SITE_TITLE")
+
+ if getenv("LNBITS_SITE_TAGLINE"):
+ site_tagline = getenv("LNBITS_SITE_TAGLINE")
+
+ if getenv("LNBITS_SITE_DESCRIPTION"):
+ site_description = getenv("LNBITS_SITE_DESCRIPTION")
+
+ if getenv("LNBITS_ALLOWED_USERS"):
+ allowed_users = getenv("LNBITS_ALLOWED_USERS")
+
+ if getenv("LNBITS_ADMIN_USER"):
+ admin_user = getenv("LNBITS_ADMIN_USER")
+
+ if getenv("LNBITS_DEFAULT_WALLET_NAME"):
+ default_wallet_name = getenv("LNBITS_DEFAULT_WALLET_NAME")
+
+ if getenv("LNBITS_DATA_FOLDER"):
+ data_folder = getenv("LNBITS_DATA_FOLDER")
+
+ if getenv("LNBITS_DISABLED_EXTENSIONS"):
+ disabled_ext = getenv("LNBITS_DISABLED_EXTENSIONS")
+
+ if getenv("LNBITS_FORCE_HTTPS"):
+ force_https = getenv("LNBITS_FORCE_HTTPS")
+
+ if getenv("LNBITS_SERVICE_FEE"):
+ service_fee = getenv("LNBITS_SERVICE_FEE")
+
+ if getenv("LNBITS_BACKEND_WALLET_CLASS"):
+ funding_source = getenv("LNBITS_BACKEND_WALLET_CLASS")
+
+ await db.execute(
+ """
+ CREATE TABLE IF NOT EXISTS admin (
+ user TEXT,
+ site_title TEXT,
+ site_tagline TEXT,
+ site_description TEXT,
+ admin_user TEXT,
+ allowed_users TEXT,
+ default_wallet_name TEXT,
+ data_folder TEXT,
+ disabled_ext TEXT,
+ force_https BOOLEAN,
+ service_fee INT,
+ funding_source TEXT
+ );
+ """
+ )
+ await db.execute(
+ """
+ INSERT INTO admin (user, site_title, site_tagline, site_description, admin_user, allowed_users, default_wallet_name, data_folder, disabled_ext, force_https, service_fee, funding_source)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ """,
+ (
+ user,
+ site_title,
+ site_tagline,
+ site_description,
+ admin_user,
+ allowed_users,
+ default_wallet_name,
+ data_folder,
+ disabled_ext,
+ force_https,
+ service_fee,
+ funding_source,
+ ),
+ )
+
+
+async def m001_create_funding_table(db):
+
+ funding_wallet = getenv("LNBITS_BACKEND_WALLET_CLASS")
+
+ # Make the funding table, if it does not already exist
+ await db.execute(
+ """
+ CREATE TABLE IF NOT EXISTS funding (
+ id TEXT PRIMARY KEY,
+ backend_wallet TEXT,
+ endpoint TEXT,
+ port INT,
+ read_key TEXT,
+ invoice_key TEXT,
+ admin_key TEXT,
+ cert TEXT,
+ balance INT,
+ selected INT
+ );
+ """
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, selected)
+ VALUES (?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "CLightningWallet",
+ getenv("CLIGHTNING_RPC"),
+ 1 if funding_wallet == "CLightningWallet" else 0,
+ ),
+ )
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ VALUES (?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "SparkWallet",
+ getenv("SPARK_URL"),
+ getenv("SPARK_TOKEN"),
+ 1 if funding_wallet == "SparkWallet" else 0,
+ ),
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ VALUES (?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "LnbitsWallet",
+ getenv("LNBITS_ENDPOINT"),
+ getenv("LNBITS_KEY"),
+ 1 if funding_wallet == "LnbitsWallet" else 0,
+ ),
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, port, admin_key, cert, selected)
+ VALUES (?, ?, ?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "LndWallet",
+ getenv("LND_GRPC_ENDPOINT"),
+ getenv("LND_GRPC_PORT"),
+ getenv("LND_GRPC_MACAROON"),
+ getenv("LND_GRPC_CERT"),
+ 1 if funding_wallet == "LndWallet" else 0,
+ ),
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, admin_key, cert, selected)
+ VALUES (?, ?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "LndRestWallet",
+ getenv("LND_REST_ENDPOINT"),
+ getenv("LND_REST_MACAROON"),
+ getenv("LND_REST_CERT"),
+ 1 if funding_wallet == "LndWallet" else 0,
+ ),
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, admin_key, cert, selected)
+ VALUES (?, ?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "LNPayWallet",
+ getenv("LNPAY_API_ENDPOINT"),
+ getenv("LNPAY_WALLET_KEY"),
+ getenv("LNPAY_API_KEY"), # this is going in as the cert
+ 1 if funding_wallet == "LNPayWallet" else 0,
+ ),
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ VALUES (?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "LntxbotWallet",
+ getenv("LNTXBOT_API_ENDPOINT"),
+ getenv("LNTXBOT_KEY"),
+ 1 if funding_wallet == "LntxbotWallet" else 0,
+ ),
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ VALUES (?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "OpenNodeWallet",
+ getenv("OPENNODE_API_ENDPOINT"),
+ getenv("OPENNODE_KEY"),
+ 1 if funding_wallet == "OpenNodeWallet" else 0,
+ ),
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ VALUES (?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "SparkWallet",
+ getenv("SPARK_URL"),
+ getenv("SPARK_TOKEN"),
+ 1 if funding_wallet == "SparkWallet" else 0,
+ ),
+ )
+
+ ## PLACEHOLDER FOR ECLAIR WALLET
+ # await db.execute(
+ # """
+ # INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ # VALUES (?, ?, ?, ?, ?)
+ # """,
+ # (
+ # urlsafe_short_hash(),
+ # "EclairWallet",
+ # getenv("ECLAIR_URL"),
+ # getenv("ECLAIR_PASS"),
+ # 1 if funding_wallet == "EclairWallet" else 0,
+ # ),
+ # )
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
new file mode 100644
index 00000000..c38f17f4
--- /dev/null
+++ b/lnbits/extensions/admin/models.py
@@ -0,0 +1,38 @@
+from typing import NamedTuple
+from sqlite3 import Row
+
+class Admin(NamedTuple):
+ user: str
+ site_title: str
+ site_tagline: str
+ site_description:str
+ allowed_users: str
+ admin_user: str
+ default_wallet_name: str
+ data_folder: str
+ disabled_ext: str
+ force_https: str
+ service_fee: str
+ funding_source: str
+
+ @classmethod
+ def from_row(cls, row: Row) -> "Admin":
+ data = dict(row)
+ return cls(**data)
+
+class Funding(NamedTuple):
+ id: str
+ backend_wallet: str
+ endpoint: str
+ port: str
+ read_key: str
+ invoice_key: str
+ admin_key: str
+ cert: str
+ balance: int
+ selected: int
+
+ @classmethod
+ def from_row(cls, row: Row) -> "Funding":
+ data = dict(row)
+ return cls(**data)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
new file mode 100644
index 00000000..87cf09ef
--- /dev/null
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -0,0 +1,565 @@
+{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
+%} {% block page %}
+
+Admin
+
+
+
+
+
+
+ Settings
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Wallet topup
+
+
+
+
+
+
+
+
+
+{% endblock %} {% block scripts %} {{ window_vars(user) }}
+
+{% endblock %}
diff --git a/lnbits/extensions/admin/views.py b/lnbits/extensions/admin/views.py
new file mode 100644
index 00000000..5e17919c
--- /dev/null
+++ b/lnbits/extensions/admin/views.py
@@ -0,0 +1,20 @@
+from quart import g, render_template, request, jsonify
+import json
+
+from lnbits.decorators import check_user_exists, validate_uuids
+from lnbits.extensions.admin import admin_ext
+from lnbits.core.crud import get_user, create_account
+from .crud import get_admin, get_funding
+from lnbits.settings import WALLET
+
+
+@admin_ext.route("/")
+@validate_uuids(["usr"], required=True)
+@check_user_exists()
+async def index():
+ user_id = g.user
+ admin = await get_admin()
+
+ funding = [{**funding._asdict()} for funding in await get_funding()]
+
+ return await render_template("admin/index.html", user=g.user, admin=admin, funding=funding)
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
new file mode 100644
index 00000000..2a61b6f5
--- /dev/null
+++ b/lnbits/extensions/admin/views_api.py
@@ -0,0 +1,41 @@
+from quart import jsonify, g, request
+from http import HTTPStatus
+from .crud import update_wallet_balance
+from lnbits.extensions.admin import admin_ext
+from lnbits.decorators import api_check_wallet_key, api_validate_post_request
+from lnbits.core.crud import get_wallet
+from .crud import get_admin,update_admin
+import json
+
+@admin_ext.route("/api/v1/admin//", methods=["GET"])
+@api_check_wallet_key("admin")
+async def api_update_balance(wallet_id, topup_amount):
+ print(g.data.wallet)
+ try:
+ wallet = await get_wallet(wallet_id)
+ except:
+ return (
+ jsonify({"error": "Not allowed: not an admin"}),
+ HTTPStatus.FORBIDDEN,
+ )
+ print(wallet)
+ print(topup_amount)
+ return jsonify({"status": "Success"}), HTTPStatus.OK
+
+
+@admin_ext.route("/api/v1/admin/", methods=["POST"])
+@api_check_wallet_key("admin")
+@api_validate_post_request(schema={})
+async def api_update_admin():
+ body = await request.get_json()
+ admin = await get_admin()
+ print(g.wallet[2])
+ print(body["admin_user"])
+ if not admin.admin_user == g.wallet[2] and admin.admin_user != None:
+ return (
+ jsonify({"error": "Not allowed: not an admin"}),
+ HTTPStatus.FORBIDDEN,
+ )
+ updated = await update_admin(body)
+ print(updated)
+ return jsonify({"status": "Success"}), HTTPStatus.OK
\ No newline at end of file
From 68eee00b45170db4e35fa6fdafba85373958e9fa Mon Sep 17 00:00:00 2001
From: benarc
Date: Mon, 7 Mar 2022 05:11:55 +0000
Subject: [PATCH 012/691] old admin setup UI
---
lnbits/core/templates/core/admin.html | 717 ++++++++++++++++++++++++++
1 file changed, 717 insertions(+)
create mode 100644 lnbits/core/templates/core/admin.html
diff --git a/lnbits/core/templates/core/admin.html b/lnbits/core/templates/core/admin.html
new file mode 100644
index 00000000..e8176555
--- /dev/null
+++ b/lnbits/core/templates/core/admin.html
@@ -0,0 +1,717 @@
+{% extends "public.html" %} {% from "macros.jinja" import window_vars with
+context %} {% block page %}
+
+
+
+
+
+ Welcome to LNbits
+
+
+ Fill in the information below to setup your LNbits instance. Details
+ can be changed later.
+
+
+
+
+
+
+ Branding
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Service settings
+
+
+
+ Funding source information (at least one required)
*if installed through RaspiBlitz, MyNode, etc, details
+ should be filled in for you
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ View project in GitHub
+ Donate
+
+
+
+
+
+{% endblock %} {% block scripts %} {{ window_vars(funding) }}
+
+{% endblock %}
From 65e1f19ed1124340d2a9ba97b4420c099896488c Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Sat, 12 Mar 2022 14:18:09 +0000
Subject: [PATCH 013/691] convert to FastAPI
---
lnbits/extensions/admin/__init__.py | 11 +++-
lnbits/extensions/admin/crud.py | 50 +++++++--------
lnbits/extensions/admin/migrations.py | 23 ++++---
lnbits/extensions/admin/models.py | 51 ++++++++++------
.../admin/templates/admin/index.html | 23 +++++--
lnbits/extensions/admin/views.py | 39 ++++++++----
lnbits/extensions/admin/views_api.py | 61 ++++++++++---------
7 files changed, 151 insertions(+), 107 deletions(-)
diff --git a/lnbits/extensions/admin/__init__.py b/lnbits/extensions/admin/__init__.py
index d5f26c90..6a56b2bb 100644
--- a/lnbits/extensions/admin/__init__.py
+++ b/lnbits/extensions/admin/__init__.py
@@ -1,10 +1,15 @@
-from quart import Blueprint
+from fastapi import APIRouter
+
from lnbits.db import Database
+from lnbits.helpers import template_renderer
db = Database("ext_admin")
-admin_ext: Blueprint = Blueprint("admin", __name__, static_folder="static", template_folder="templates")
+admin_ext: APIRouter = APIRouter(prefix="/admin", tags=["admin"])
+
+def admin_renderer():
+ return template_renderer(["lnbits/extensions/admin/templates"])
-from .views_api import * # noqa
from .views import * # noqa
+from .views_api import * # noqa
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index cb8f9b5b..872d6c97 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -1,11 +1,11 @@
from typing import List, Optional
+from lnbits.core.crud import create_payment
+from lnbits.helpers import urlsafe_short_hash
+from lnbits.settings import *
+
from . import db
from .models import Admin, Funding
-from lnbits.settings import *
-from lnbits.helpers import urlsafe_short_hash
-from lnbits.core.crud import create_payment
-from lnbits.db import Connection
def update_wallet_balance(wallet_id: str, amount: int) -> str:
@@ -22,38 +22,30 @@ def update_wallet_balance(wallet_id: str, amount: int) -> str:
)
return "success"
-
-async def update_admin(
-) -> Optional[Admin]:
- if not CLightningWallet:
- print("poo")
- await db.execute(
- """
- UPDATE admin
- SET user = ?, site_title = ?, site_tagline = ?, site_description = ?, allowed_users = ?, default_wallet_name = ?, data_folder = ?, disabled_ext = ?, force_https = ?, service_fee = ?, funding_source = ?
- WHERE 1
- """,
- (
-
- ),
- )
- row = await db.fetchone("SELECT * FROM admin WHERE 1")
- return Admin.from_row(row) if row else None
-
-async def update_admin(admin_id: str, **kwargs) -> Optional[Admin]:
+async def update_admin(user: str, **kwargs) -> Admin:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
+ print("UPDATE", q)
await db.execute(
- f"UPDATE jukebox.jukebox SET {q} WHERE id = ?", (*kwargs.values(), juke_id)
+ f'UPDATE admin SET {q} WHERE "user" = ?', (*kwargs.values(), user)
)
- row = await db.fetchone("SELECT * FROM jukebox.jukebox WHERE id = ?", (juke_id,))
- return Jukebox(**row) if row else None
+ row = await db.fetchone('SELECT * FROM admin WHERE "user" = ?', (user,))
+ assert row, "Newly updated settings couldn't be retrieved"
+ return Admin(**row) if row else None
+
+# async def update_admin(user: str, **kwargs) -> Optional[Admin]:
+# q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
+# await db.execute(
+# f"UPDATE admin SET {q} WHERE user = ?", (*kwargs.values(), user)
+# )
+# new_settings = await get_admin()
+# return new_settings
async def get_admin() -> List[Admin]:
- row = await db.fetchone("SELECT * FROM admin WHERE 1")
- return Admin.from_row(row) if row else None
+ row = await db.fetchone("SELECT * FROM admin")
+ return Admin(**row) if row else None
async def get_funding() -> List[Funding]:
rows = await db.fetchall("SELECT * FROM funding")
- return [Funding.from_row(row) for row in rows]
+ return [Funding(**row) for row in rows]
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 82d934cb..13b76923 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -1,5 +1,7 @@
-from sqlalchemy.exc import OperationalError # type: ignore
from os import getenv
+
+from sqlalchemy.exc import OperationalError # type: ignore
+
from lnbits.helpers import urlsafe_short_hash
@@ -9,7 +11,7 @@ async def m001_create_admin_table(db):
site_tagline = None
site_description = None
allowed_users = None
- admin_user = None
+ admin_users = None
default_wallet_name = None
data_folder = None
disabled_ext = None
@@ -29,8 +31,9 @@ async def m001_create_admin_table(db):
if getenv("LNBITS_ALLOWED_USERS"):
allowed_users = getenv("LNBITS_ALLOWED_USERS")
- if getenv("LNBITS_ADMIN_USER"):
- admin_user = getenv("LNBITS_ADMIN_USER")
+ if getenv("LNBITS_ADMIN_USERS"):
+ admin_users = "".join(getenv("LNBITS_ADMIN_USERS").split())
+ user = admin_users.split(',')[0]
if getenv("LNBITS_DEFAULT_WALLET_NAME"):
default_wallet_name = getenv("LNBITS_DEFAULT_WALLET_NAME")
@@ -53,32 +56,32 @@ async def m001_create_admin_table(db):
await db.execute(
"""
CREATE TABLE IF NOT EXISTS admin (
- user TEXT,
+ "user" TEXT,
site_title TEXT,
site_tagline TEXT,
site_description TEXT,
- admin_user TEXT,
+ admin_users TEXT,
allowed_users TEXT,
default_wallet_name TEXT,
data_folder TEXT,
disabled_ext TEXT,
force_https BOOLEAN,
- service_fee INT,
+ service_fee REAL,
funding_source TEXT
);
"""
)
await db.execute(
"""
- INSERT INTO admin (user, site_title, site_tagline, site_description, admin_user, allowed_users, default_wallet_name, data_folder, disabled_ext, force_https, service_fee, funding_source)
+ INSERT INTO admin ("user", site_title, site_tagline, site_description, admin_users, allowed_users, default_wallet_name, data_folder, disabled_ext, force_https, service_fee, funding_source)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
- user,
+ user.strip(),
site_title,
site_tagline,
site_description,
- admin_user,
+ admin_users[1:],
allowed_users,
default_wallet_name,
data_folder,
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index c38f17f4..4080ff01 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -1,18 +1,35 @@
-from typing import NamedTuple
from sqlite3 import Row
+from typing import List, Optional
-class Admin(NamedTuple):
+from fastapi import Query
+from pydantic import BaseModel
+
+
+class UpdateAdminSettings(BaseModel):
+ site_title: Optional[str]
+ site_tagline: Optional[str]
+ site_description: Optional[str]
+ allowed_users: Optional[str]
+ admin_users: Optional[str]
+ default_wallet_name: Optional[str]
+ data_folder: Optional[str]
+ disabled_ext: Optional[str]
+ force_https: Optional[bool]
+ service_fee: Optional[float]
+ funding_source: Optional[str]
+
+class Admin(BaseModel):
user: str
- site_title: str
- site_tagline: str
- site_description:str
- allowed_users: str
- admin_user: str
+ site_title: Optional[str]
+ site_tagline: Optional[str]
+ site_description: Optional[str]
+ allowed_users: Optional[str]
+ admin_users: str
default_wallet_name: str
data_folder: str
disabled_ext: str
- force_https: str
- service_fee: str
+ force_https: Optional[bool] = Query(True)
+ service_fee: float
funding_source: str
@classmethod
@@ -20,16 +37,16 @@ class Admin(NamedTuple):
data = dict(row)
return cls(**data)
-class Funding(NamedTuple):
+class Funding(BaseModel):
id: str
backend_wallet: str
- endpoint: str
- port: str
- read_key: str
- invoice_key: str
- admin_key: str
- cert: str
- balance: int
+ endpoint: str = Query(None)
+ port: str = Query(None)
+ read_key: str = Query(None)
+ invoice_key: str = Query(None)
+ admin_key: str = Query(None)
+ cert: str = Query(None)
+ balance: int = Query(None)
selected: int
@classmethod
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 87cf09ef..a6b45625 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -87,7 +87,7 @@
@@ -442,13 +442,14 @@
site_title: '{{admin.site_title}}',
tagline: '{{admin.site_tagline}}',
description: '{{admin.site_description}}',
- admin_user: '{{admin.admin_user}}',
- service_fee: parseInt('{{admin.service_fee}}'),
+ admin_users: '{{admin.admin_users}}',
+ service_fee: parseFloat('{{admin.service_fee}}'),
default_wallet_name: '{{admin.default_wallet_name}}',
data_folder: '{{admin.data_folder}}',
funding_source_primary: '{{admin.funding_source}}',
disabled_ext: '{{admin.disabled_ext}}'.split(','),
edited: [],
+ funding: {},
senddata: {}
}
},
@@ -528,15 +529,27 @@
},
UpdateLNbits: function () {
var self = this
- console.log(self.data.admin)
+ let {site_title, admin_users, default_wallet_name, data_folder, disabled_ext, service_fee, funding_source_primary} = this.data.admin
+ let data = {
+ site_title,
+ site_tagline: this.data.admin.tagline,
+ site_description: this.data.admin.description,
+ admin_users: admin_users.toString(),
+ default_wallet_name,
+ data_folder,
+ disabled_ext: disabled_ext.toString(),
+ service_fee,
+ funding_source: funding_source_primary}
+ console.log(data)
LNbits.api
.request(
'POST',
'/admin/api/v1/admin/',
self.g.user.wallets[0].adminkey,
- self.data.admin
+ data
)
.then(function (response) {
+ console.log(response.data)
self.$q.notify({
type: 'positive',
message:
diff --git a/lnbits/extensions/admin/views.py b/lnbits/extensions/admin/views.py
index 5e17919c..00a0c99f 100644
--- a/lnbits/extensions/admin/views.py
+++ b/lnbits/extensions/admin/views.py
@@ -1,20 +1,33 @@
-from quart import g, render_template, request, jsonify
-import json
+from email.policy import default
+from os import getenv
-from lnbits.decorators import check_user_exists, validate_uuids
+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_user_exists
from lnbits.extensions.admin import admin_ext
-from lnbits.core.crud import get_user, create_account
+from lnbits.requestvars import g
+
+from . import admin_ext, admin_renderer
from .crud import get_admin, get_funding
-from lnbits.settings import WALLET
+templates = Jinja2Templates(directory="templates")
-@admin_ext.route("/")
-@validate_uuids(["usr"], required=True)
-@check_user_exists()
-async def index():
- user_id = g.user
+@admin_ext.get("/", response_class=HTMLResponse)
+async def index(request: Request, user: User = Depends(check_user_exists)):
admin = await get_admin()
+ print(g())
+ funding = [f.dict() for f in await get_funding()]
- funding = [{**funding._asdict()} for funding in await get_funding()]
-
- return await render_template("admin/index.html", user=g.user, admin=admin, funding=funding)
+ print("ADMIN", admin.dict())
+ return admin_renderer().TemplateResponse(
+ "admin/index.html", {
+ "request": request,
+ "user": user.dict(),
+ "admin": admin.dict(),
+ "funding": funding
+ }
+ )
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index 2a61b6f5..b2c65be2 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -1,41 +1,42 @@
-from quart import jsonify, g, request
from http import HTTPStatus
-from .crud import update_wallet_balance
-from lnbits.extensions.admin import admin_ext
-from lnbits.decorators import api_check_wallet_key, api_validate_post_request
-from lnbits.core.crud import get_wallet
-from .crud import get_admin,update_admin
-import json
-@admin_ext.route("/api/v1/admin//", methods=["GET"])
-@api_check_wallet_key("admin")
-async def api_update_balance(wallet_id, topup_amount):
- print(g.data.wallet)
+from fastapi import Body, Depends, Request
+from starlette.exceptions import HTTPException
+
+from lnbits.core.crud import get_wallet
+from lnbits.decorators import WalletTypeInfo, require_admin_key
+from lnbits.extensions.admin import admin_ext
+from lnbits.extensions.admin.models import Admin, UpdateAdminSettings
+
+from .crud import get_admin, update_admin, update_wallet_balance
+
+
+@admin_ext.get("/api/v1/admin/{wallet_id}/{topup_amount}", status_code=HTTPStatus.OK)
+async def api_update_balance(wallet_id, topup_amount, g: WalletTypeInfo = Depends(require_admin_key)):
+ print(g.wallet)
try:
wallet = await get_wallet(wallet_id)
except:
- return (
- jsonify({"error": "Not allowed: not an admin"}),
- HTTPStatus.FORBIDDEN,
- )
+ raise HTTPException(
+ status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
+ )
print(wallet)
print(topup_amount)
- return jsonify({"status": "Success"}), HTTPStatus.OK
+ return {"status": "Success"}
-@admin_ext.route("/api/v1/admin/", methods=["POST"])
-@api_check_wallet_key("admin")
-@api_validate_post_request(schema={})
-async def api_update_admin():
- body = await request.get_json()
+@admin_ext.post("/api/v1/admin/", status_code=HTTPStatus.OK)
+async def api_update_admin(
+ request: Request,
+ data: UpdateAdminSettings = Body(...),
+ g: WalletTypeInfo = Depends(require_admin_key)
+ ):
admin = await get_admin()
- print(g.wallet[2])
- print(body["admin_user"])
- if not admin.admin_user == g.wallet[2] and admin.admin_user != None:
- return (
- jsonify({"error": "Not allowed: not an admin"}),
- HTTPStatus.FORBIDDEN,
- )
- updated = await update_admin(body)
+ print(data)
+ if not admin.user == g.wallet.user:
+ raise HTTPException(
+ status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
+ )
+ updated = await update_admin(user=g.wallet.user, **data.dict())
print(updated)
- return jsonify({"status": "Success"}), HTTPStatus.OK
\ No newline at end of file
+ return {"status": "Success"}
From 23d770a07489c3d74cc0c4c4d3b4a3b4b00fc393 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Sat, 12 Mar 2022 14:18:58 +0000
Subject: [PATCH 014/691] remove core admin html (renamed for now)
---
lnbits/core/templates/core/core_admin.html | 717 +++++++++++++++++++++
1 file changed, 717 insertions(+)
create mode 100644 lnbits/core/templates/core/core_admin.html
diff --git a/lnbits/core/templates/core/core_admin.html b/lnbits/core/templates/core/core_admin.html
new file mode 100644
index 00000000..835fc00a
--- /dev/null
+++ b/lnbits/core/templates/core/core_admin.html
@@ -0,0 +1,717 @@
+{% extends "public.html" %} {% from "macros.jinja" import window_vars with
+context %} {% block page %}
+
+
+
+
+
+ Welcome to LNbits
+
+
+ Fill in the information below to setup your LNbits instance. Details
+ can be changed later.
+
+
+
+
+
+
+ Branding
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Service settings
+
+
+
+ Funding source information (at least one required)
*if installed through RaspiBlitz, MyNode, etc, details
+ should be filled in for you
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ View project in GitHub
+ Donate
+
+
+
+
+
+{% endblock %} {% block scripts %} {{ window_vars(funding) }}
+
+{% endblock %}
From 165ab6d0b50b49cad69b46100bce0f87fd6f7257 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Sat, 12 Mar 2022 14:21:38 +0000
Subject: [PATCH 015/691] typo
---
.env.example | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.env.example b/.env.example
index 68e25ad1..bd189484 100644
--- a/.env.example
+++ b/.env.example
@@ -5,7 +5,7 @@ DEBUG=false
LNBITS_ADMIN_USERS="" # User IDs seperated by comma
LNBITS_ADMIN_EXTENSIONS="ngrok" # Extensions only admin can access
-LNBITS_ADMIN_UI=false # Extensions only admin can access
+LNBITS_ADMIN_UI=false # Enable Admin GUI, available for the first user in LNBITS_ADMIN_USERS
LNBITS_ALLOWED_USERS="" # Restricts access, User IDs seperated by comma
From 844e11edeb441fd2e7c7b40d11c25cc4019471bf Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Sat, 12 Mar 2022 14:22:23 +0000
Subject: [PATCH 016/691] add admin_ui env
---
lnbits/settings.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lnbits/settings.py b/lnbits/settings.py
index 3f4e31cc..43cb87cb 100644
--- a/lnbits/settings.py
+++ b/lnbits/settings.py
@@ -1,5 +1,6 @@
import importlib
import subprocess
+from email.policy import default
from os import path
from typing import List
@@ -27,6 +28,7 @@ LNBITS_DATABASE_URL = env.str("LNBITS_DATABASE_URL", default=None)
LNBITS_ALLOWED_USERS: List[str] = [
x.strip(" ") for x in env.list("LNBITS_ALLOWED_USERS", default=[], subcast=str)
]
+LNBITS_ADMIN_UI = env.bool("LNBITS_ADMIN_UI", default=False)
LNBITS_ADMIN_USERS: List[str] = [
x.strip(" ") for x in env.list("LNBITS_ADMIN_USERS", default=[], subcast=str)
]
From 4336613028e05dae5b6adf3b543903f6fc365a44 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Sat, 12 Mar 2022 14:23:16 +0000
Subject: [PATCH 017/691] add db config at startup
---
lnbits/commands.py | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/lnbits/commands.py b/lnbits/commands.py
index 0f7454f2..8c39c338 100644
--- a/lnbits/commands.py
+++ b/lnbits/commands.py
@@ -52,6 +52,25 @@ def bundle_vendored():
with open(outputpath, "w") as f:
f.write(output)
+async def get_admin_settings():
+ from lnbits.extensions.admin.models import Admin
+
+ async with core_db.connect() as conn:
+
+ if conn.type == SQLITE:
+ exists = await conn.fetchone(
+ "SELECT * FROM sqlite_master WHERE type='table' AND name='admin'"
+ )
+ elif conn.type in {POSTGRES, COCKROACH}:
+ exists = await conn.fetchone(
+ "SELECT * FROM information_schema.tables WHERE table_name = 'admin'"
+ )
+ if not exists:
+ return False
+
+ row = await conn.fetchone("SELECT * from admin")
+
+ return Admin(**row) if row else None
async def migrate_databases():
"""Creates the necessary databases if they don't exist already; or migrates them."""
From 32a6a6ae2fb9fa3ba01c24f31067a5115feca4e3 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Sat, 12 Mar 2022 14:23:53 +0000
Subject: [PATCH 018/691] get admin settings at startup
---
lnbits/app.py | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 51482538..6a66b99e 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -18,6 +18,7 @@ from loguru import logger
import lnbits.settings
from lnbits.core.tasks import register_task_listeners
+from .commands import get_admin_settings
from .core import core_app
from .core.views.generic import core_html_routes
from .helpers import (
@@ -42,6 +43,7 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
"""Create application factory.
:param config_object: The configuration object to use.
"""
+<<<<<<< HEAD
configure_logger()
app = FastAPI(
@@ -53,6 +55,14 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
},
)
app.mount("/static", StaticFiles(packages=[("lnbits", "static")]), name="static")
+=======
+ app = FastAPI()
+
+ if lnbits.settings.LNBITS_ADMIN_UI:
+ check_settings(app)
+
+ app.mount("/static", StaticFiles(directory="lnbits/static"), name="static")
+>>>>>>> e3a1b3ae (get admin settings at startup)
app.mount(
"/core/static",
StaticFiles(packages=[("lnbits.core", "static")]),
@@ -64,7 +74,6 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
app.add_middleware(
CORSMiddleware, allow_origins=origins, allow_methods=["*"], allow_headers=["*"]
)
-
g().config = lnbits.settings
g().base_url = f"http://{lnbits.settings.HOST}:{lnbits.settings.PORT}"
@@ -102,6 +111,18 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
return app
+def check_settings(app: FastAPI):
+ @app.on_event("startup")
+ async def check_settings_admin():
+ while True:
+ admin_set = await get_admin_settings()
+ if admin_set :
+ break
+ print("ERROR:", admin_set)
+ await asyncio.sleep(5)
+ # admin_set = await get_admin_settings()
+ g().admin_conf = admin_set
+
def check_funding_source(app: FastAPI) -> None:
@app.on_event("startup")
async def check_wallet_status():
From f245f3188b7f35b6f9388e9caa12d3d6a0b20c3e Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Sat, 12 Mar 2022 14:24:11 +0000
Subject: [PATCH 019/691] remove core admin.html
---
lnbits/core/templates/core/admin.html | 717 --------------------------
1 file changed, 717 deletions(-)
delete mode 100644 lnbits/core/templates/core/admin.html
diff --git a/lnbits/core/templates/core/admin.html b/lnbits/core/templates/core/admin.html
deleted file mode 100644
index e8176555..00000000
--- a/lnbits/core/templates/core/admin.html
+++ /dev/null
@@ -1,717 +0,0 @@
-{% extends "public.html" %} {% from "macros.jinja" import window_vars with
-context %} {% block page %}
-
-
-
-
-
- Welcome to LNbits
-
-
- Fill in the information below to setup your LNbits instance. Details
- can be changed later.
-
-
-
-
-
-
- Branding
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Service settings
-
-
-
- Funding source information (at least one required)
*if installed through RaspiBlitz, MyNode, etc, details
- should be filled in for you
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- View project in GitHub
- Donate
-
-
-
-
-
-{% endblock %} {% block scripts %} {{ window_vars(funding) }}
-
-{% endblock %}
From de21f0216161ac9f45cf17f42f5be708404156d0 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Fri, 18 Mar 2022 16:55:31 +0000
Subject: [PATCH 020/691] refactor ui
---
.../admin/templates/admin/index.html | 727 +++++++++++++++++-
1 file changed, 712 insertions(+), 15 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index a6b45625..65ac9f33 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -1,6 +1,670 @@
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
%} {% block page %}
+
+
+
+
+
+
+ tab = val.name"
+ >
+ tab = val.name"
+ >
+ tab = val.name"
+ >
+ tab = val.name"
+ >
+
+
+
+
+
+
+
+ Wallets Management
+
+
+
+
+
Funding Source Info
+
+ {%raw%}
+ - Funding Source: {{data.admin.funding_source}}
+ - Balance: {{data.admin.balance / 1000}} sats
+ {%endraw%}
+
+
+
+
+
+
+
+
+ TopUp a wallet
+
+
+
+
+
+
+
+
+
Funding Sources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Save
+
+
+
+
+
+ User Management
+
+
+ Super Admin: {% raw
+ %}{{this.data.admin.user}}{% endraw %}
+
+
+
+
Admin Users
+
+
+
+
+ {% raw %}
+
+ {{ user }}
+
+ {% endraw %}
+
+
+
+
+
Allowed Users
+
+
+
+
+ {% raw %}
+
+ {{ user }}
+
+ {% endraw %}
+
+
+
+
+
+
+
Disabled Extensions
+
+
+
+
+
+ Save
+
+
+
+
+
+ Server Management
+
+
+
+
+
Server Info
+
+ {%raw%}
+ - SQlite: {{data.admin.data_folder}}
+ - Postgres: {{data.admin.database_url}}
+ {%endraw%}
+
+
+
+
+
+
+
+
Miscelaneous
+
+
+ Force HTTPS
+ Prefer secure URLs
+
+
+
+
+
+
+
+ Hide API
+ Hides wallet api, extensions can choose to honor
+
+
+
+
+
+
+
+
+
+
+
+ Save
+
+
+
+
+
+ UI Management
+
+
+
+
+
+
+
+
Default Wallet Name
+
+
+
+
+
+
+
+
+
Advertisement Slots
+
+
+
+
+ {% raw %}
+
+ {{ space.slice(0, 8) + " ... " + space.slice(-8) }}
+
+ {% endraw %}
+
+
+
+
+
+
+
+ Save
+
+
+
+
+
+
+
+
+
Admin
-
+
@@ -426,6 +1090,7 @@
return {
wallet: {data: {}},
cancel: {},
+ tab: 'funding',
data: {
funding_source: [
'CLightningWallet',
@@ -436,24 +1101,14 @@
'LnbitsWallet',
'OpenNodeWallet'
],
-
+
admin: {
- user: '{{ user.id }}',
- site_title: '{{admin.site_title}}',
- tagline: '{{admin.site_tagline}}',
- description: '{{admin.site_description}}',
- admin_users: '{{admin.admin_users}}',
- service_fee: parseFloat('{{admin.service_fee}}'),
- default_wallet_name: '{{admin.default_wallet_name}}',
- data_folder: '{{admin.data_folder}}',
- funding_source_primary: '{{admin.funding_source}}',
- disabled_ext: '{{admin.disabled_ext}}'.split(','),
edited: [],
funding: {},
senddata: {}
}
},
-
+ themes: ['classic', 'bitcoin', 'flamingo', 'mint', 'autumn', 'monochrome', 'salvador'],
options: [
'bleskomat',
'captcha',
@@ -489,9 +1144,51 @@
for (i = 0; i < funding.length; i++) {
self.data.admin.funding[funding[i].backend_wallet] = funding[i]
}
- console.log(self.data.admin)
+ let settings = JSON.parse('{{ settings | tojson|safe }}')
+ settings.balance = '{{ balance }}'
+ this.data.admin = {...this.data.admin, ...settings}
+ console.log(this.g.user)
},
methods: {
+ addAdminUser(){
+ let addUser = this.data.admin_users_add
+ let admin_users = this.data.admin.admin_users
+ if(addUser.length && !admin_users.includes(addUser)){
+ admin_users.push(addUser)
+ this.data.admin.admin_users = admin_users
+ this.data.admin_users_add = ""
+ }
+ },
+ removeAdminUser(user){
+ let admin_users = this.data.admin.admin_users
+ this.data.admin.admin_users = admin_users.filter(u => u !== user)
+ },
+ addAllowedUser(){
+ let addUser = this.data.allowed_users_add
+ let allowed_users = this.data.admin.allowed_users
+ if(addUser.length && !allowed_users.includes(addUser)){
+ allowed_users.push(addUser)
+ this.data.admin.allowed_users = allowed_users
+ this.data.allowed_users_add = ""
+ }
+ },
+ removeAllowedUser(user){
+ let allowed_users = this.data.admin.allowed_users
+ this.data.admin.allowed_users = allowed_users.filter(u => u !== user)
+ },
+ addAdSpace(){
+ let adSpace = this.data.ad_space_add
+ let spaces = this.data.admin.ad_space
+ if(adSpace.length && !spaces.includes(adSpace)){
+ spaces.push(adSpace)
+ this.data.admin.ad_space = spaces
+ this.data.ad_space_add = ""
+ }
+ },
+ removeAdSpace(ad){
+ let spaces = this.data.admin.ad_space
+ this.data.admin.ad_space = spaces.filter(s => s !== ad)
+ },
topupWallet: function () {
var self = this
LNbits.api
From 582cc52ac61236ca7ae219b49e20d0954e983411 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Fri, 18 Mar 2022 16:59:06 +0000
Subject: [PATCH 021/691] make it work from g()
---
lnbits/app.py | 34 +++---
lnbits/config.py | 62 ++++++++++
lnbits/extensions/admin/crud.py | 2 +-
lnbits/extensions/admin/migrations.py | 162 +++++++++++++++++---------
lnbits/extensions/admin/models.py | 27 +++--
lnbits/extensions/admin/views.py | 8 +-
lnbits/settings.py | 2 +-
7 files changed, 218 insertions(+), 79 deletions(-)
create mode 100644 lnbits/config.py
diff --git a/lnbits/app.py b/lnbits/app.py
index 6a66b99e..ccac1e00 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -19,6 +19,7 @@ import lnbits.settings
from lnbits.core.tasks import register_task_listeners
from .commands import get_admin_settings
+from .config import WALLET, conf
from .core import core_app
from .core.views.generic import core_html_routes
from .helpers import (
@@ -29,7 +30,8 @@ from .helpers import (
url_for_vendored,
)
from .requestvars import g
-from .settings import WALLET
+
+# from .settings import WALLET
from .tasks import (
catch_everything_and_restart,
check_pending_payments,
@@ -43,7 +45,6 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
"""Create application factory.
:param config_object: The configuration object to use.
"""
-<<<<<<< HEAD
configure_logger()
app = FastAPI(
@@ -55,20 +56,18 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
},
)
app.mount("/static", StaticFiles(packages=[("lnbits", "static")]), name="static")
-=======
- app = FastAPI()
-
- if lnbits.settings.LNBITS_ADMIN_UI:
- check_settings(app)
-
- app.mount("/static", StaticFiles(directory="lnbits/static"), name="static")
->>>>>>> e3a1b3ae (get admin settings at startup)
app.mount(
"/core/static",
StaticFiles(packages=[("lnbits.core", "static")]),
name="core_static",
)
+ if lnbits.settings.LNBITS_ADMIN_UI:
+ g().admin_conf = conf
+ check_settings(app)
+
+ g().WALLET = WALLET
+
origins = ["*"]
app.add_middleware(
@@ -110,18 +109,27 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
return app
-
def check_settings(app: FastAPI):
@app.on_event("startup")
async def check_settings_admin():
+
+ def removeEmptyString(arr):
+ return list(filter(None, arr))
+
while True:
admin_set = await get_admin_settings()
if admin_set :
break
print("ERROR:", admin_set)
await asyncio.sleep(5)
- # admin_set = await get_admin_settings()
- g().admin_conf = admin_set
+
+ admin_set.admin_users = removeEmptyString(admin_set.admin_users.split(','))
+ admin_set.allowed_users = removeEmptyString(admin_set.allowed_users.split(','))
+ admin_set.admin_ext = removeEmptyString(admin_set.admin_ext.split(','))
+ admin_set.disabled_ext = removeEmptyString(admin_set.disabled_ext.split(','))
+ admin_set.theme = removeEmptyString(admin_set.theme.split(','))
+ admin_set.ad_space = removeEmptyString(admin_set.ad_space.split(','))
+ g().admin_conf = conf.copy(update=admin_set.dict())
def check_funding_source(app: FastAPI) -> None:
@app.on_event("startup")
diff --git a/lnbits/config.py b/lnbits/config.py
new file mode 100644
index 00000000..02e8cf53
--- /dev/null
+++ b/lnbits/config.py
@@ -0,0 +1,62 @@
+import importlib
+import json
+from os import getenv, path
+from typing import List, Optional
+
+from pydantic import BaseSettings, Field, validator
+
+wallets_module = importlib.import_module("lnbits.wallets")
+wallet_class = getattr(
+ wallets_module, getenv("LNBITS_BACKEND_WALLET_CLASS", "VoidWallet")
+)
+
+WALLET = wallet_class()
+
+def list_parse_fallback(v):
+ try:
+ return json.loads(v)
+ except Exception as e:
+ return v.replace(' ','').split(',')
+
+class Settings(BaseSettings):
+ # users
+ admin_users: List[str] = Field(default_factory=list, env="LNBITS_ADMIN_USERS")
+ allowed_users: List[str] = Field(default_factory=list, env="LNBITS_ALLOWED_USERS")
+ admin_ext: List[str] = Field(default_factory=list, env="LNBITS_ADMIN_EXTENSIONS")
+ disabled_ext: List[str] = Field(default_factory=list, env="LNBITS_DISABLED_EXTENSIONS")
+ funding_source: str = Field(default="VoidWallet", env="LNBITS_BACKEND_WALLET_CLASS")
+ # ops
+ data_folder: str = Field(default=None, env="LNBITS_DATA_FOLDER")
+ database_url: str = Field(default=None, env="LNBITS_DATABASE_URL")
+ force_https: bool = Field(default=True, env="LNBITS_FORCE_HTTPS")
+ service_fee: float = Field(default=0, env="LNBITS_SERVICE_FEE")
+ hide_api: bool = Field(default=False, env="LNBITS_HIDE_API")
+ denomination: str = Field(default="sats", env="LNBITS_DENOMINATION")
+ # Change theme
+ site_title: str = Field(default=None, env="LNBITS_SITE_TITLE")
+ site_tagline: str = Field(default=None, env="LNBITS_SITE_TAGLINE")
+ site_description: str = Field(default=None, env="LNBITS_SITE_DESCRIPTION")
+ default_wallet_name: str = Field(default=None, env="LNBITS_DEFAULT_WALLET_NAME")
+ theme: List[str] = Field(default="classic, flamingo, mint, salvador, monochrome, autumn", env="LNBITS_THEME_OPTIONS")
+ ad_space: List[str] = Field(default_factory=list, env="LNBITS_AD_SPACE")
+ # .env
+ env: Optional[str]
+ debug: Optional[str]
+ host: Optional[str]
+ port: Optional[str]
+ lnbits_path: Optional[str] = path.dirname(path.realpath(__file__))
+
+ # @validator('admin_users', 'allowed_users', 'admin_ext', 'disabled_ext', pre=True)
+ # def validate(cls, val):
+ # print(val)
+ # return val.split(',')
+
+ class Config:
+ env_file = ".env"
+ env_file_encoding = "utf-8"
+ case_sensitive = False
+ json_loads = list_parse_fallback
+
+
+conf = Settings()
+WALLET = wallet_class()
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index 872d6c97..6fccb8ee 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -40,7 +40,7 @@ async def update_admin(user: str, **kwargs) -> Admin:
# new_settings = await get_admin()
# return new_settings
-async def get_admin() -> List[Admin]:
+async def get_admin() -> Admin:
row = await db.fetchone("SELECT * FROM admin")
return Admin(**row) if row else None
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 13b76923..574f772d 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -2,93 +2,151 @@ from os import getenv
from sqlalchemy.exc import OperationalError # type: ignore
+from lnbits.config import conf
from lnbits.helpers import urlsafe_short_hash
async def m001_create_admin_table(db):
- user = None
- site_title = None
- site_tagline = None
- site_description = None
- allowed_users = None
- admin_users = None
- default_wallet_name = None
- data_folder = None
- disabled_ext = None
- force_https = True
- service_fee = 0
- funding_source = ""
+ # users/server
+ user = conf.admin_users[0]
+ admin_users = ",".join(conf.admin_users)
+ allowed_users = ",".join(conf.allowed_users)
+ admin_ext = ",".join(conf.admin_ext)
+ disabled_ext = ",".join(conf.disabled_ext)
+ funding_source = conf.funding_source
+ #operational
+ data_folder = conf.data_folder
+ database_url = conf.database_url
+ force_https = conf.force_https
+ service_fee = conf.service_fee
+ hide_api = conf.hide_api
+ denomination = conf.denomination
+ # Theme'ing
+ site_title = conf.site_title
+ site_tagline = conf.site_tagline
+ site_description = conf.site_description
+ default_wallet_name = conf.default_wallet_name
+ theme = ",".join(conf.theme)
+ ad_space = ",".join(conf.ad_space)
- if getenv("LNBITS_SITE_TITLE"):
- site_title = getenv("LNBITS_SITE_TITLE")
+ # if getenv("LNBITS_ADMIN_EXTENSIONS"):
+ # admin_ext = getenv("LNBITS_ADMIN_EXTENSIONS")
- if getenv("LNBITS_SITE_TAGLINE"):
- site_tagline = getenv("LNBITS_SITE_TAGLINE")
+ # if getenv("LNBITS_DATABASE_URL"):
+ # database_url = getenv("LNBITS_DATABASE_URL")
- if getenv("LNBITS_SITE_DESCRIPTION"):
- site_description = getenv("LNBITS_SITE_DESCRIPTION")
+ # if getenv("LNBITS_HIDE_API"):
+ # hide_api = getenv("LNBITS_HIDE_API")
- if getenv("LNBITS_ALLOWED_USERS"):
- allowed_users = getenv("LNBITS_ALLOWED_USERS")
+ # if getenv("LNBITS_THEME_OPTIONS"):
+ # theme = getenv("LNBITS_THEME_OPTIONS")
- if getenv("LNBITS_ADMIN_USERS"):
- admin_users = "".join(getenv("LNBITS_ADMIN_USERS").split())
- user = admin_users.split(',')[0]
+ # if getenv("LNBITS_AD_SPACE"):
+ # ad_space = getenv("LNBITS_AD_SPACE")
- if getenv("LNBITS_DEFAULT_WALLET_NAME"):
- default_wallet_name = getenv("LNBITS_DEFAULT_WALLET_NAME")
+ # if getenv("LNBITS_SITE_TITLE"):
+ # site_title = getenv("LNBITS_SITE_TITLE")
- if getenv("LNBITS_DATA_FOLDER"):
- data_folder = getenv("LNBITS_DATA_FOLDER")
+ # if getenv("LNBITS_SITE_TAGLINE"):
+ # site_tagline = getenv("LNBITS_SITE_TAGLINE")
- if getenv("LNBITS_DISABLED_EXTENSIONS"):
- disabled_ext = getenv("LNBITS_DISABLED_EXTENSIONS")
+ # if getenv("LNBITS_SITE_DESCRIPTION"):
+ # site_description = getenv("LNBITS_SITE_DESCRIPTION")
- if getenv("LNBITS_FORCE_HTTPS"):
- force_https = getenv("LNBITS_FORCE_HTTPS")
+ # if getenv("LNBITS_ALLOWED_USERS"):
+ # allowed_users = getenv("LNBITS_ALLOWED_USERS")
- if getenv("LNBITS_SERVICE_FEE"):
- service_fee = getenv("LNBITS_SERVICE_FEE")
+ # if getenv("LNBITS_ADMIN_USERS"):
+ # admin_users = "".join(getenv("LNBITS_ADMIN_USERS").split())
+ # user = admin_users.split(',')[0]
+
+ # if getenv("LNBITS_DEFAULT_WALLET_NAME"):
+ # default_wallet_name = getenv("LNBITS_DEFAULT_WALLET_NAME")
- if getenv("LNBITS_BACKEND_WALLET_CLASS"):
- funding_source = getenv("LNBITS_BACKEND_WALLET_CLASS")
+ # if getenv("LNBITS_DATA_FOLDER"):
+ # data_folder = getenv("LNBITS_DATA_FOLDER")
+
+ # if getenv("LNBITS_DISABLED_EXTENSIONS"):
+ # disabled_ext = getenv("LNBITS_DISABLED_EXTENSIONS")
+
+ # if getenv("LNBITS_FORCE_HTTPS"):
+ # force_https = getenv("LNBITS_FORCE_HTTPS")
+
+ # if getenv("LNBITS_SERVICE_FEE"):
+ # service_fee = getenv("LNBITS_SERVICE_FEE")
+
+ # if getenv("LNBITS_DENOMINATION"):
+ # denomination = getenv("LNBITS_DENOMINATION", "sats")
+
+ # if getenv("LNBITS_BACKEND_WALLET_CLASS"):
+ # funding_source = getenv("LNBITS_BACKEND_WALLET_CLASS")
await db.execute(
"""
CREATE TABLE IF NOT EXISTS admin (
- "user" TEXT,
+ "user" TEXT PRIMARY KEY,
+ admin_users TEXT,
+ allowed_users TEXT,
+ admin_ext TEXT,
+ disabled_ext TEXT,
+ funding_source TEXT,
+ data_folder TEXT,
+ database_url TEXT,
+ force_https BOOLEAN,
+ service_fee REAL,
+ hide_api BOOLEAN,
+ denomination TEXT,
site_title TEXT,
site_tagline TEXT,
site_description TEXT,
- admin_users TEXT,
- allowed_users TEXT,
default_wallet_name TEXT,
- data_folder TEXT,
- disabled_ext TEXT,
- force_https BOOLEAN,
- service_fee REAL,
- funding_source TEXT
+ theme TEXT,
+ ad_space TEXT
);
"""
)
await db.execute(
"""
- INSERT INTO admin ("user", site_title, site_tagline, site_description, admin_users, allowed_users, default_wallet_name, data_folder, disabled_ext, force_https, service_fee, funding_source)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- """,
- (
- user.strip(),
+ INSERT INTO admin (
+ "user",
+ admin_users,
+ allowed_users,
+ admin_ext,
+ disabled_ext,
+ funding_source,
+ data_folder,
+ database_url,
+ force_https,
+ service_fee,
+ hide_api,
+ denomination,
site_title,
site_tagline,
site_description,
- admin_users[1:],
- allowed_users,
default_wallet_name,
- data_folder,
+ theme,
+ ad_space)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ """,
+ (
+ user,
+ admin_users,
+ allowed_users,
+ admin_ext,
disabled_ext,
+ funding_source,
+ data_folder,
+ database_url,
force_https,
service_fee,
- funding_source,
+ hide_api,
+ denomination,
+ site_title,
+ site_tagline,
+ site_description,
+ default_wallet_name,
+ theme,
+ ad_space,
),
)
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 4080ff01..f7c64de5 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -2,7 +2,7 @@ from sqlite3 import Row
from typing import List, Optional
from fastapi import Query
-from pydantic import BaseModel
+from pydantic import BaseModel, Field
class UpdateAdminSettings(BaseModel):
@@ -19,18 +19,27 @@ class UpdateAdminSettings(BaseModel):
funding_source: Optional[str]
class Admin(BaseModel):
+ # users
user: str
+ admin_users: Optional[str]
+ allowed_users: Optional[str]
+ admin_ext: Optional[str]
+ disabled_ext: Optional[str]
+ funding_source: Optional[str]
+ # ops
+ data_folder: Optional[str]
+ database_url: Optional[str]
+ force_https: bool = Field(default=True)
+ service_fee: float = Field(default=0)
+ hide_api: bool = Field(default=False)
+ # Change theme
site_title: Optional[str]
site_tagline: Optional[str]
site_description: Optional[str]
- allowed_users: Optional[str]
- admin_users: str
- default_wallet_name: str
- data_folder: str
- disabled_ext: str
- force_https: Optional[bool] = Query(True)
- service_fee: float
- funding_source: str
+ default_wallet_name: Optional[str]
+ denomination: str = Field(default="sats")
+ theme: Optional[str]
+ ad_space: Optional[str]
@classmethod
def from_row(cls, row: Row) -> "Admin":
diff --git a/lnbits/extensions/admin/views.py b/lnbits/extensions/admin/views.py
index 00a0c99f..105f05a1 100644
--- a/lnbits/extensions/admin/views.py
+++ b/lnbits/extensions/admin/views.py
@@ -19,15 +19,17 @@ templates = Jinja2Templates(directory="templates")
@admin_ext.get("/", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_user_exists)):
admin = await get_admin()
- print(g())
funding = [f.dict() for f in await get_funding()]
-
+ error, balance = await g().WALLET.status()
print("ADMIN", admin.dict())
+ print(g().admin_conf)
return admin_renderer().TemplateResponse(
"admin/index.html", {
"request": request,
"user": user.dict(),
"admin": admin.dict(),
- "funding": funding
+ "funding": funding,
+ "settings": g().admin_conf.dict(),
+ "balance": balance
}
)
diff --git a/lnbits/settings.py b/lnbits/settings.py
index 43cb87cb..ed5c77f7 100644
--- a/lnbits/settings.py
+++ b/lnbits/settings.py
@@ -4,7 +4,7 @@ from email.policy import default
from os import path
from typing import List
-from environs import Env # type: ignore
+from environs import Env
env = Env()
env.read_env()
From 66a7f53b976ae98a1e18cff8305da1299e524b69 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 10:28:07 +0000
Subject: [PATCH 022/691] topup wallet endpoint
---
lnbits/extensions/admin/crud.py | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index 6fccb8ee..683558f9 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -1,26 +1,31 @@
+import json
from typing import List, Optional
from lnbits.core.crud import create_payment
from lnbits.helpers import urlsafe_short_hash
from lnbits.settings import *
+from lnbits.tasks import internal_invoice_queue
from . import db
from .models import Admin, Funding
-def update_wallet_balance(wallet_id: str, amount: int) -> str:
+async def update_wallet_balance(wallet_id: str, amount: int) -> str:
temp_id = f"temp_{urlsafe_short_hash()}"
internal_id = f"internal_{urlsafe_short_hash()}"
- create_payment(
+
+ payment = await create_payment(
wallet_id=wallet_id,
checking_id=internal_id,
payment_request="admin_internal",
payment_hash="admin_internal",
- amount=amount * 1000,
+ amount=amount*1000,
memo="Admin top up",
pending=False,
)
- return "success"
+ # manually send this for now
+ await internal_invoice_queue.put(internal_id)
+ return payment
async def update_admin(user: str, **kwargs) -> Admin:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
From 663c7ebd2f52c4cc0ea57839d921e3730d4decef Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 10:28:44 +0000
Subject: [PATCH 023/691] update admin settings in db
---
lnbits/extensions/admin/models.py | 29 +++++++++++++++++-----------
lnbits/extensions/admin/views_api.py | 8 ++++----
2 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index f7c64de5..36d9b815 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -6,17 +6,24 @@ from pydantic import BaseModel, Field
class UpdateAdminSettings(BaseModel):
- site_title: Optional[str]
- site_tagline: Optional[str]
- site_description: Optional[str]
- allowed_users: Optional[str]
- admin_users: Optional[str]
- default_wallet_name: Optional[str]
- data_folder: Optional[str]
- disabled_ext: Optional[str]
- force_https: Optional[bool]
- service_fee: Optional[float]
- funding_source: Optional[str]
+ # users
+ admin_users: str = Query(None)
+ allowed_users: str = Query(None)
+ admin_ext: str = Query(None)
+ disabled_ext: str = Query(None)
+ funding_source: str = Query(None)
+ # ops
+ force_https: bool = Query(None)
+ service_fee: float = Query(None, ge=0)
+ hide_api: bool = Query(None)
+ # Change theme
+ site_title: str = Query(None)
+ site_tagline: str = Query(None)
+ site_description: str = Query(None)
+ default_wallet_name: str = Query(None)
+ denomination: str = Query(None)
+ theme: str = Query(None)
+ ad_space: str = Query(None)
class Admin(BaseModel):
# users
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index b2c65be2..cb526aa5 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -12,16 +12,16 @@ from .crud import get_admin, update_admin, update_wallet_balance
@admin_ext.get("/api/v1/admin/{wallet_id}/{topup_amount}", status_code=HTTPStatus.OK)
-async def api_update_balance(wallet_id, topup_amount, g: WalletTypeInfo = Depends(require_admin_key)):
- print(g.wallet)
+async def api_update_balance(wallet_id, topup_amount: int, g: WalletTypeInfo = Depends(require_admin_key)):
try:
wallet = await get_wallet(wallet_id)
except:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
)
- print(wallet)
- print(topup_amount)
+
+ await update_wallet_balance(wallet_id=wallet_id, amount=int(topup_amount))
+
return {"status": "Success"}
From bc090190fca9a170566e1d605bdbdbd3536c70f5 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 10:29:18 +0000
Subject: [PATCH 024/691] update settings and topup logic
---
.../admin/templates/admin/index.html | 91 ++++++++++++-------
1 file changed, 57 insertions(+), 34 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 65ac9f33..e9ddc7c4 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -30,7 +30,7 @@
-
+
@@ -61,7 +61,7 @@
@@ -577,7 +577,6 @@
Site Description
s !== ad)
},
- topupWallet: function () {
- var self = this
+ topupWallet() {
LNbits.api
.request(
'GET',
'/admin/api/v1/admin/' +
- self.wallet.id +
+ this.wallet.data.id +
'/' +
- self.wallet.data.amount,
- self.g.user.wallets[0].adminkey
+ this.wallet.data.amount,
+ this.g.user.wallets[0].adminkey
)
- .then(function (response) {
- self.$q.notify({
+ .then((response) => {
+ this.$q.notify({
type: 'positive',
message:
- 'Success! Added ' +
- self.wallet.amount +
- ' to ' +
- self.wallet.id,
+ 'Success! Added ' +
+ this.wallet.data.amount +
+ ' to ' +
+ this.wallet.data.id,
icon: null
})
+ this.wallet.data = {}
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
@@ -1224,36 +1224,59 @@
self.data.admin.edited.push(source)
console.log(self.data.admin.edited)
},
- UpdateLNbits: function () {
- var self = this
- let {site_title, admin_users, default_wallet_name, data_folder, disabled_ext, service_fee, funding_source_primary} = this.data.admin
+ UpdateLNbits() {
+ let {
+ admin_users,
+ allowed_users,
+ admin_ext,
+ disabled_ext,
+ funding_source,
+ force_https,
+ service_fee,
+ hide_api,
+ site_title,
+ site_tagline,
+ site_description,
+ default_wallet_name,
+ denomination,
+ theme,
+ ad_space
+ } = this.data.admin
+ //console.log("this", this.data.admin)
let data = {
- site_title,
- site_tagline: this.data.admin.tagline,
- site_description: this.data.admin.description,
- admin_users: admin_users.toString(),
- default_wallet_name,
- data_folder,
+ admin_users: admin_users.toString(),
+ allowed_users: allowed_users.toString(),
+ admin_ext: admin_ext.toString(),
disabled_ext: disabled_ext.toString(),
- service_fee,
- funding_source: funding_source_primary}
+ funding_source,
+ force_https,
+ service_fee,
+ hide_api,
+ site_title,
+ site_tagline,
+ site_description,
+ default_wallet_name,
+ denomination,
+ theme: theme.toString(),
+ ad_space: ad_space.toString()
+ }
console.log(data)
LNbits.api
.request(
'POST',
'/admin/api/v1/admin/',
- self.g.user.wallets[0].adminkey,
+ this.g.user.wallets[0].adminkey,
data
)
- .then(function (response) {
+ .then(response => {
console.log(response.data)
- self.$q.notify({
+ this.$q.notify({
type: 'positive',
message:
'Success! Added ' +
- self.wallet.amount +
+ this.wallet.amount +
' to ' +
- self.wallet.id,
+ this.wallet.id,
icon: null
})
})
From 313574df1991c47b6a0dbc390f8d839278e200d4 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 11:34:47 +0000
Subject: [PATCH 025/691] make removeEmptyString fn as helper fn
---
lnbits/app.py | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index ccac1e00..5df439dc 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -26,6 +26,7 @@ from .helpers import (
get_css_vendored,
get_js_vendored,
get_valid_extensions,
+ removeEmptyString,
template_renderer,
url_for_vendored,
)
@@ -113,9 +114,6 @@ def check_settings(app: FastAPI):
@app.on_event("startup")
async def check_settings_admin():
- def removeEmptyString(arr):
- return list(filter(None, arr))
-
while True:
admin_set = await get_admin_settings()
if admin_set :
From edfa98f00e7111096321d259fca4cd2eb36ac3d5 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 11:35:15 +0000
Subject: [PATCH 026/691] add some defaults
---
lnbits/config.py | 6 +++---
lnbits/extensions/admin/models.py | 8 ++++----
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/lnbits/config.py b/lnbits/config.py
index 02e8cf53..b2fbfff1 100644
--- a/lnbits/config.py
+++ b/lnbits/config.py
@@ -33,10 +33,10 @@ class Settings(BaseSettings):
hide_api: bool = Field(default=False, env="LNBITS_HIDE_API")
denomination: str = Field(default="sats", env="LNBITS_DENOMINATION")
# Change theme
- site_title: str = Field(default=None, env="LNBITS_SITE_TITLE")
- site_tagline: str = Field(default=None, env="LNBITS_SITE_TAGLINE")
+ site_title: str = Field(default="LNbits", env="LNBITS_SITE_TITLE")
+ site_tagline: str = Field(default="free and open-source lightning wallet", env="LNBITS_SITE_TAGLINE")
site_description: str = Field(default=None, env="LNBITS_SITE_DESCRIPTION")
- default_wallet_name: str = Field(default=None, env="LNBITS_DEFAULT_WALLET_NAME")
+ default_wallet_name: str = Field(default="LNbits wallet", env="LNBITS_DEFAULT_WALLET_NAME")
theme: List[str] = Field(default="classic, flamingo, mint, salvador, monochrome, autumn", env="LNBITS_THEME_OPTIONS")
ad_space: List[str] = Field(default_factory=list, env="LNBITS_AD_SPACE")
# .env
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 36d9b815..0f25679d 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -17,11 +17,11 @@ class UpdateAdminSettings(BaseModel):
service_fee: float = Query(None, ge=0)
hide_api: bool = Query(None)
# Change theme
- site_title: str = Query(None)
- site_tagline: str = Query(None)
+ site_title: str = Query("LNbits")
+ site_tagline: str = Query("free and open-source lightning wallet")
site_description: str = Query(None)
- default_wallet_name: str = Query(None)
- denomination: str = Query(None)
+ default_wallet_name: str = Query("LNbits wallet")
+ denomination: str = Query("sats")
theme: str = Query(None)
ad_space: str = Query(None)
From ba6bda39ab4a6c50631658d9bee85329c4784950 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 11:36:04 +0000
Subject: [PATCH 027/691] removeEmtpy sting as helper fn
---
lnbits/helpers.py | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/lnbits/helpers.py b/lnbits/helpers.py
index e213240c..e456f715 100644
--- a/lnbits/helpers.py
+++ b/lnbits/helpers.py
@@ -154,8 +154,20 @@ def url_for(endpoint: str, external: Optional[bool] = False, **params: Any) -> s
url = f"{base}{endpoint}{url_params}"
return url
+def removeEmptyString(arr):
+ return list(filter(None, arr))
def template_renderer(additional_folders: List = []) -> Jinja2Templates:
+ if(settings.LNBITS_ADMIN_UI):
+ _ = g().admin_conf
+ settings.LNBITS_AD_SPACE = _.ad_space
+ settings.LNBITS_HIDE_API = _.hide_api
+ settings.LNBITS_SITE_TITLE = _.site_title
+ settings.LNBITS_DENOMINATION = _.denomination
+ settings.LNBITS_SITE_TAGLINE = _.site_tagline
+ settings.LNBITS_SITE_DESCRIPTION = _.site_description
+ settings.LNBITS_THEME_OPTIONS = _.theme
+
t = Jinja2Templates(
loader=jinja2.FileSystemLoader(
["lnbits/templates", "lnbits/core/templates", *additional_folders]
From 0a211a2fb2d1fdf7c135cf637b768c8fc2855a64 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 11:41:11 +0000
Subject: [PATCH 028/691] cleanup
---
lnbits/extensions/admin/crud.py | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index 683558f9..e14ad194 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -1,9 +1,7 @@
-import json
-from typing import List, Optional
+from typing import List
from lnbits.core.crud import create_payment
from lnbits.helpers import urlsafe_short_hash
-from lnbits.settings import *
from lnbits.tasks import internal_invoice_queue
from . import db
@@ -37,14 +35,6 @@ async def update_admin(user: str, **kwargs) -> Admin:
assert row, "Newly updated settings couldn't be retrieved"
return Admin(**row) if row else None
-# async def update_admin(user: str, **kwargs) -> Optional[Admin]:
-# q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
-# await db.execute(
-# f"UPDATE admin SET {q} WHERE user = ?", (*kwargs.values(), user)
-# )
-# new_settings = await get_admin()
-# return new_settings
-
async def get_admin() -> Admin:
row = await db.fetchone("SELECT * FROM admin")
return Admin(**row) if row else None
From 5ec7f21650897699f39723bbe93edd3d53da1fd2 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 11:42:28 +0000
Subject: [PATCH 029/691] make string to list
---
lnbits/extensions/admin/views_api.py | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index cb526aa5..1d4e6a9c 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -1,5 +1,6 @@
from http import HTTPStatus
+# from config import conf
from fastapi import Body, Depends, Request
from starlette.exceptions import HTTPException
@@ -7,6 +8,8 @@ from lnbits.core.crud import get_wallet
from lnbits.decorators import WalletTypeInfo, require_admin_key
from lnbits.extensions.admin import admin_ext
from lnbits.extensions.admin.models import Admin, UpdateAdminSettings
+from lnbits.helpers import removeEmptyString
+from lnbits.requestvars import g
from .crud import get_admin, update_admin, update_wallet_balance
@@ -19,7 +22,7 @@ async def api_update_balance(wallet_id, topup_amount: int, g: WalletTypeInfo = D
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
)
-
+
await update_wallet_balance(wallet_id=wallet_id, amount=int(topup_amount))
return {"status": "Success"}
@@ -29,14 +32,24 @@ async def api_update_balance(wallet_id, topup_amount: int, g: WalletTypeInfo = D
async def api_update_admin(
request: Request,
data: UpdateAdminSettings = Body(...),
- g: WalletTypeInfo = Depends(require_admin_key)
+ w: WalletTypeInfo = Depends(require_admin_key)
):
admin = await get_admin()
print(data)
- if not admin.user == g.wallet.user:
+ if not admin.user == w.wallet.user:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
)
- updated = await update_admin(user=g.wallet.user, **data.dict())
- print(updated)
+ updated = await update_admin(user=w.wallet.user, **data.dict())
+
+ updated.admin_users = removeEmptyString(updated.admin_users.split(','))
+ updated.allowed_users = removeEmptyString(updated.allowed_users.split(','))
+ updated.admin_ext = removeEmptyString(updated.admin_ext.split(','))
+ updated.disabled_ext = removeEmptyString(updated.disabled_ext.split(','))
+ updated.theme = removeEmptyString(updated.theme.split(','))
+ updated.ad_space = removeEmptyString(updated.ad_space.split(','))
+
+ g().admin_conf = g().admin_conf.copy(update=updated.dict())
+
+ print(g().admin_conf)
return {"status": "Success"}
From 4d16c296aa1d8b8375e3f131e459a2f2f80f0d3b Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 11:42:47 +0000
Subject: [PATCH 030/691] success message
---
lnbits/extensions/admin/templates/admin/index.html | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index e9ddc7c4..9aa4f12a 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -1273,10 +1273,7 @@
this.$q.notify({
type: 'positive',
message:
- 'Success! Added ' +
- this.wallet.amount +
- ' to ' +
- this.wallet.id,
+ 'Success! Settings changed!',
icon: null
})
})
From 2c48e3aa5f1e561e4106c60bfe0e4266a86711b3 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Thu, 14 Apr 2022 10:42:26 +0100
Subject: [PATCH 031/691] allow html to be passed to description
---
lnbits/core/templates/core/index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lnbits/core/templates/core/index.html b/lnbits/core/templates/core/index.html
index f769b44f..03cf706f 100644
--- a/lnbits/core/templates/core/index.html
+++ b/lnbits/core/templates/core/index.html
@@ -82,7 +82,7 @@
>
-
{{SITE_DESCRIPTION}}
+
{{SITE_DESCRIPTION | safe}}
From f16ead4f7303787d945ab9dc39550ae3bc0ec611 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Thu, 14 Apr 2022 16:37:13 +0100
Subject: [PATCH 032/691] update funding wallets
---
lnbits/extensions/admin/crud.py | 12 +
.../admin/templates/admin/index.html | 523 ++++++++++--------
lnbits/extensions/admin/views.py | 3 +-
lnbits/extensions/admin/views_api.py | 19 +-
4 files changed, 315 insertions(+), 242 deletions(-)
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index e14ad194..dd39e8e4 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -39,6 +39,18 @@ async def get_admin() -> Admin:
row = await db.fetchone("SELECT * FROM admin")
return Admin(**row) if row else None
+async def update_funding(data: Funding) -> Funding:
+ await db.execute(
+ """
+ UPDATE funding
+ SET backend_wallet = ?, endpoint = ?, port = ?, read_key = ?, invoice_key = ?, admin_key = ?, cert = ?, balance = ?, selected = ?
+ WHERE id = ?
+ """,
+ (data.backend_wallet, data.endpoint, data.port, data.read_key, data.invoice_key, data.admin_key, data.cert, data.balance, data.selected, data.id,),
+ )
+ row = await db.fetchone('SELECT * FROM funding WHERE "id" = ?', (data.id,))
+ assert row, "Newly updated settings couldn't be retrieved"
+ return Funding(**row) if row else None
async def get_funding() -> List[Funding]:
rows = await db.fetchall("SELECT * FROM funding")
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 9aa4f12a..d56b3d79 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -31,11 +31,11 @@
-
-
-
- Wallets Management
-
+
+
+
+ Wallets Management
+
@@ -62,43 +62,96 @@
-
TopUp a wallet
-
-
-
-
-
-
-
-
+
TopUp a wallet
+
Funding Sources
-
+ {% raw %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% endraw %}
+
+
+
+
+
+
+ User Management
+
+
+ Super Admin: {% raw %}{{this.data.admin.user}}{% endraw %}
+
+
Admin Users
+ hint="Users with admin privileges"
+ >
{% raw %}
-
-
-
- {% raw %}
-
Allowed Users
+
- {{ user }}
-
- {% endraw %}
+
+
+
+ {% raw %}
+
+ {{ user }}
+
+ {% endraw %}
+
+
+
+
+
+
Disabled Extensions
+
+
+
+
+
+ Save
+
+
+
+
+
+ Server Management
-
-
-
-
-
Disabled Extensions
-
-
-
-
-
- Save
-
-
-
-
-
- Server Management
-
Server Info
{%raw%}
- - SQlite: {{data.admin.data_folder}}
- - Postgres: {{data.admin.database_url}}
+ -
+ SQlite: {{data.admin.data_folder}}
+
+ -
+ Postgres: {{data.admin.database_url}}
+
{%endraw%}
@@ -520,7 +576,10 @@
Hide API
- Hides wallet api, extensions can choose to honor
+ Hides wallet api, extensions can choose to
+ honor
-
-
-
- Save
-
-
-
-
-
- UI Management
-
+
+
+
+ Save
+
+
+
+
+
+ UI Management
+
+
Default Wallet Name
@@ -628,12 +682,15 @@
@keydown.enter="addAdSpace"
type="text"
label="Ad image URL"
- hint="Ad image filepaths or urls, extensions can choose to honor">
+ hint="Ad image filepaths or urls, extensions can choose to honor"
+ >
{% raw %}
-
-
-
-
- Save
-
-
-
-
-
+
+
+
+ Save
+
+
+
+
+
-
-
-Admin
-
+
+
-
-
-
-
- Wallet topup
-
-
-
-
-
-
-
{% endblock %} {% block scripts %} {{ window_vars(user) }}
@@ -1100,14 +1114,22 @@
'LnbitsWallet',
'OpenNodeWallet'
],
-
+
admin: {
edited: [],
- funding: {},
+ funding: [],
senddata: {}
}
},
- themes: ['classic', 'bitcoin', 'flamingo', 'mint', 'autumn', 'monochrome', 'salvador'],
+ themes: [
+ 'classic',
+ 'bitcoin',
+ 'flamingo',
+ 'mint',
+ 'autumn',
+ 'monochrome',
+ 'salvador'
+ ],
options: [
'bleskomat',
'captcha',
@@ -1139,10 +1161,13 @@
self.cancel.on = true
}
funding = JSON.parse(String('{{ funding | tojson|safe }}'))
- var i
+ funding.map(f => {
+ this.data.admin.funding.push(f)
+ })
+ /*var i
for (i = 0; i < funding.length; i++) {
self.data.admin.funding[funding[i].backend_wallet] = funding[i]
- }
+ }*/
let settings = JSON.parse('{{ settings | tojson|safe }}')
settings.balance = '{{ balance }}'
this.data.admin = {...this.data.admin, ...settings}
@@ -1150,42 +1175,42 @@
console.log(settings)
},
methods: {
- addAdminUser(){
+ addAdminUser() {
let addUser = this.data.admin_users_add
let admin_users = this.data.admin.admin_users
- if(addUser.length && !admin_users.includes(addUser)){
+ if (addUser.length && !admin_users.includes(addUser)) {
admin_users.push(addUser)
this.data.admin.admin_users = admin_users
- this.data.admin_users_add = ""
+ this.data.admin_users_add = ''
}
},
- removeAdminUser(user){
+ removeAdminUser(user) {
let admin_users = this.data.admin.admin_users
this.data.admin.admin_users = admin_users.filter(u => u !== user)
},
- addAllowedUser(){
+ addAllowedUser() {
let addUser = this.data.allowed_users_add
let allowed_users = this.data.admin.allowed_users
- if(addUser.length && !allowed_users.includes(addUser)){
+ if (addUser.length && !allowed_users.includes(addUser)) {
allowed_users.push(addUser)
this.data.admin.allowed_users = allowed_users
- this.data.allowed_users_add = ""
+ this.data.allowed_users_add = ''
}
},
- removeAllowedUser(user){
+ removeAllowedUser(user) {
let allowed_users = this.data.admin.allowed_users
this.data.admin.allowed_users = allowed_users.filter(u => u !== user)
},
- addAdSpace(){
+ addAdSpace() {
let adSpace = this.data.ad_space_add
let spaces = this.data.admin.ad_space
- if(adSpace.length && !spaces.includes(adSpace)){
+ if (adSpace.length && !spaces.includes(adSpace)) {
spaces.push(adSpace)
this.data.admin.ad_space = spaces
- this.data.ad_space_add = ""
+ this.data.ad_space_add = ''
}
},
- removeAdSpace(ad){
+ removeAdSpace(ad) {
let spaces = this.data.admin.ad_space
this.data.admin.ad_space = spaces.filter(s => s !== ad)
},
@@ -1199,14 +1224,14 @@
this.wallet.data.amount,
this.g.user.wallets[0].adminkey
)
- .then((response) => {
+ .then(response => {
this.$q.notify({
type: 'positive',
message:
- 'Success! Added ' +
- this.wallet.data.amount +
- ' to ' +
- this.wallet.data.id,
+ 'Success! Added ' +
+ this.wallet.data.amount +
+ ' to ' +
+ this.wallet.data.id,
icon: null
})
this.wallet.data = {}
@@ -1224,6 +1249,29 @@
self.data.admin.edited.push(source)
console.log(self.data.admin.edited)
},
+ updateFunding(fund) {
+ let data = this.data.admin.funding.find(v => v.backend_wallet == fund)
+
+ LNbits.api
+ .request(
+ 'POST',
+ '/admin/api/v1/admin/funding',
+ this.g.user.wallets[0].adminkey,
+ data
+ )
+ .then(response => {
+ //let wallet = response.data.backend_wallet
+ //this.data.admin.funding[wallet] = response.data
+ //this.data.admin.funding[wallet].endpoint = response.data.endpoint
+ //console.log(this.data.admin.funding)
+ //console.log(this.data.admin)
+ this.$q.notify({
+ type: 'positive',
+ message: `Success! ${response.data.backend_wallet} changed!`,
+ icon: null
+ })
+ })
+ },
UpdateLNbits() {
let {
admin_users,
@@ -1272,8 +1320,7 @@
console.log(response.data)
this.$q.notify({
type: 'positive',
- message:
- 'Success! Settings changed!',
+ message: 'Success! Settings changed!',
icon: null
})
})
diff --git a/lnbits/extensions/admin/views.py b/lnbits/extensions/admin/views.py
index 105f05a1..24b8ca85 100644
--- a/lnbits/extensions/admin/views.py
+++ b/lnbits/extensions/admin/views.py
@@ -21,8 +21,7 @@ async def index(request: Request, user: User = Depends(check_user_exists)):
admin = await get_admin()
funding = [f.dict() for f in await get_funding()]
error, balance = await g().WALLET.status()
- print("ADMIN", admin.dict())
- print(g().admin_conf)
+
return admin_renderer().TemplateResponse(
"admin/index.html", {
"request": request,
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index 1d4e6a9c..b797dc2d 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -7,11 +7,11 @@ from starlette.exceptions import HTTPException
from lnbits.core.crud import get_wallet
from lnbits.decorators import WalletTypeInfo, require_admin_key
from lnbits.extensions.admin import admin_ext
-from lnbits.extensions.admin.models import Admin, UpdateAdminSettings
+from lnbits.extensions.admin.models import Admin, Funding, UpdateAdminSettings
from lnbits.helpers import removeEmptyString
from lnbits.requestvars import g
-from .crud import get_admin, update_admin, update_wallet_balance
+from .crud import get_admin, update_admin, update_funding, update_wallet_balance
@admin_ext.get("/api/v1/admin/{wallet_id}/{topup_amount}", status_code=HTTPStatus.OK)
@@ -53,3 +53,18 @@ async def api_update_admin(
print(g().admin_conf)
return {"status": "Success"}
+
+@admin_ext.post("/api/v1/admin/funding/", status_code=HTTPStatus.OK)
+async def api_update_funding(
+ request: Request,
+ data: Funding = Body(...),
+ w: WalletTypeInfo = Depends(require_admin_key)
+ ):
+ admin = await get_admin()
+
+ if not admin.user == w.wallet.user:
+ raise HTTPException(
+ status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
+ )
+ funding = await update_funding(data=data)
+ return funding
From 5a3ad81c315f42a7b482714e943a1b0a72028e93 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Mon, 18 Apr 2022 14:25:06 +0100
Subject: [PATCH 033/691] allow user settings without restart
---
lnbits/core/views/generic.py | 7 ++++++-
lnbits/decorators.py | 8 ++++++++
lnbits/helpers.py | 3 +++
3 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py
index 31a7b030..83648c44 100644
--- a/lnbits/core/views/generic.py
+++ b/lnbits/core/views/generic.py
@@ -15,7 +15,9 @@ from lnbits.core import db
from lnbits.core.models import User
from lnbits.decorators import check_user_exists
from lnbits.helpers import template_renderer, url_for
+from lnbits.requestvars import g
from lnbits.settings import (
+ LNBITS_ADMIN_UI,
LNBITS_ADMIN_USERS,
LNBITS_ALLOWED_USERS,
LNBITS_CUSTOM_LOGO,
@@ -37,7 +39,6 @@ from ..services import pay_invoice, redeem_lnurl_withdraw
core_html_routes: APIRouter = APIRouter(tags=["Core NON-API Website Routes"])
-
@core_html_routes.get("/favicon.ico", response_class=FileResponse)
async def favicon():
return FileResponse("lnbits/core/static/favicon.ico")
@@ -119,6 +120,10 @@ async def wallet(
wallet_name = nme
service_fee = int(SERVICE_FEE) if int(SERVICE_FEE) == SERVICE_FEE else SERVICE_FEE
+ if LNBITS_ADMIN_UI:
+ LNBITS_ADMIN_USERS = g().admin_conf.admin_users
+ LNBITS_ALLOWED_USERS = g().admin_conf.allowed_users
+
if not user_id:
user = await get_user((await create_account()).id)
logger.info(f"Create user {user.id}") # type: ignore
diff --git a/lnbits/decorators.py b/lnbits/decorators.py
index d4aa63ae..f951163f 100644
--- a/lnbits/decorators.py
+++ b/lnbits/decorators.py
@@ -16,6 +16,7 @@ from lnbits.core.models import User, Wallet
from lnbits.requestvars import g
from lnbits.settings import (
LNBITS_ADMIN_EXTENSIONS,
+ LNBITS_ADMIN_UI,
LNBITS_ADMIN_USERS,
LNBITS_ALLOWED_USERS,
)
@@ -138,6 +139,9 @@ async def get_key_type(
detail="Invoice (or Admin) key required.",
)
+ if LNBITS_ADMIN_UI:
+ LNBITS_ADMIN_USERS = g().admin_conf.admin_users
+
for typenr, WalletChecker in zip(
[0, 1], [WalletAdminKeyChecker, WalletInvoiceKeyChecker]
):
@@ -231,6 +235,10 @@ async def check_user_exists(usr: UUID4) -> User:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="User does not exist."
)
+
+ if LNBITS_ADMIN_UI:
+ LNBITS_ADMIN_USERS = g().admin_conf.admin_users
+ LNBITS_ALLOWED_USERS = g().admin_conf.allowed_users
if LNBITS_ALLOWED_USERS and g().user.id not in LNBITS_ALLOWED_USERS:
raise HTTPException(
diff --git a/lnbits/helpers.py b/lnbits/helpers.py
index e456f715..1167143f 100644
--- a/lnbits/helpers.py
+++ b/lnbits/helpers.py
@@ -24,6 +24,9 @@ class Extension(NamedTuple):
class ExtensionManager:
def __init__(self):
+ if settings.LNBITS_ADMIN_UI:
+ settings.LNBITS_DISABLED_EXTENSIONS = g().admin_conf.disabled_ext
+ settings.LNBITS_ADMIN_EXTENSIONS = g().admin_conf.admin_ext
self._disabled: List[str] = settings.LNBITS_DISABLED_EXTENSIONS
self._admin_only: List[str] = [
x.strip(" ") for x in settings.LNBITS_ADMIN_EXTENSIONS
From 1ff8a9fce5c15d421a8c37a3f8bc908a4b249510 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Mon, 18 Apr 2022 14:25:26 +0100
Subject: [PATCH 034/691] advert for server restart option
---
lnbits/extensions/admin/templates/admin/index.html | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index d56b3d79..089c5f1c 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -51,7 +51,9 @@
-
Active Funding
+
+ Active Funding (Requires server restart)
+
Date: Thu, 21 Apr 2022 11:08:26 +0100
Subject: [PATCH 035/691] cleanup prints and console logs
---
lnbits/extensions/admin/crud.py | 2 +-
lnbits/extensions/admin/templates/admin/index.html | 4 ++--
lnbits/extensions/admin/views_api.py | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index dd39e8e4..f866bc1a 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -27,7 +27,7 @@ async def update_wallet_balance(wallet_id: str, amount: int) -> str:
async def update_admin(user: str, **kwargs) -> Admin:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
- print("UPDATE", q)
+ # print("UPDATE", q)
await db.execute(
f'UPDATE admin SET {q} WHERE "user" = ?', (*kwargs.values(), user)
)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 089c5f1c..584d3a33 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -1310,7 +1310,7 @@
theme: theme.toString(),
ad_space: ad_space.toString()
}
- console.log(data)
+ //console.log(data)
LNbits.api
.request(
'POST',
@@ -1319,7 +1319,7 @@
data
)
.then(response => {
- console.log(response.data)
+ //console.log(response.data)
this.$q.notify({
type: 'positive',
message: 'Success! Settings changed!',
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index b797dc2d..c0650c8a 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -35,7 +35,7 @@ async def api_update_admin(
w: WalletTypeInfo = Depends(require_admin_key)
):
admin = await get_admin()
- print(data)
+ # print(data)
if not admin.user == w.wallet.user:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
@@ -51,7 +51,7 @@ async def api_update_admin(
g().admin_conf = g().admin_conf.copy(update=updated.dict())
- print(g().admin_conf)
+ # print(g().admin_conf)
return {"status": "Success"}
@admin_ext.post("/api/v1/admin/funding/", status_code=HTTPStatus.OK)
From b0f9c82e1b0b16e3e1d499f5173a0368e5d9c93e Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Mon, 16 May 2022 10:49:21 +0100
Subject: [PATCH 036/691] create first user on fresh install
---
.env.example | 4 ++--
lnbits/config.py | 3 ++-
lnbits/extensions/admin/README.md | 15 ++++++++-------
lnbits/extensions/admin/migrations.py | 15 ++++++++++++++-
4 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/.env.example b/.env.example
index bd189484..7a49d5c5 100644
--- a/.env.example
+++ b/.env.example
@@ -4,8 +4,8 @@ PORT=5000
DEBUG=false
LNBITS_ADMIN_USERS="" # User IDs seperated by comma
-LNBITS_ADMIN_EXTENSIONS="ngrok" # Extensions only admin can access
-LNBITS_ADMIN_UI=false # Enable Admin GUI, available for the first user in LNBITS_ADMIN_USERS
+LNBITS_ADMIN_EXTENSIONS="ngrok, admin" # Extensions only admin can access
+LNBITS_ADMIN_UI=false # Enable Admin GUI, available for the first user in LNBITS_ADMIN_USERS if available
LNBITS_ALLOWED_USERS="" # Restricts access, User IDs seperated by comma
diff --git a/lnbits/config.py b/lnbits/config.py
index b2fbfff1..3ce51c3c 100644
--- a/lnbits/config.py
+++ b/lnbits/config.py
@@ -19,6 +19,7 @@ def list_parse_fallback(v):
return v.replace(' ','').split(',')
class Settings(BaseSettings):
+ admin_ui: bool = Field(default=True, env="LNBITS_ADMIN_UI")
# users
admin_users: List[str] = Field(default_factory=list, env="LNBITS_ADMIN_USERS")
allowed_users: List[str] = Field(default_factory=list, env="LNBITS_ALLOWED_USERS")
@@ -37,7 +38,7 @@ class Settings(BaseSettings):
site_tagline: str = Field(default="free and open-source lightning wallet", env="LNBITS_SITE_TAGLINE")
site_description: str = Field(default=None, env="LNBITS_SITE_DESCRIPTION")
default_wallet_name: str = Field(default="LNbits wallet", env="LNBITS_DEFAULT_WALLET_NAME")
- theme: List[str] = Field(default="classic, flamingo, mint, salvador, monochrome, autumn", env="LNBITS_THEME_OPTIONS")
+ theme: List[str] = Field(default=["classic, flamingo, mint, salvador, monochrome, autumn"], env="LNBITS_THEME_OPTIONS")
ad_space: List[str] = Field(default_factory=list, env="LNBITS_AD_SPACE")
# .env
env: Optional[str]
diff --git a/lnbits/extensions/admin/README.md b/lnbits/extensions/admin/README.md
index 27729459..6cf073a1 100644
--- a/lnbits/extensions/admin/README.md
+++ b/lnbits/extensions/admin/README.md
@@ -1,11 +1,12 @@
-Example Extension
-*tagline*
-This is an example extension to help you organise and build you own.
+# Admin Extension
-Try to include an image
-
+## Dashboard to manage LNbits from the UI
+With AdminUI you can manage your LNbits from the UI
-If your extension has API endpoints, include useful ones here
+![AdminUI](https://i.imgur.com/BIyLkyG.png)
-curl -H "Content-type: application/json" -X POST https://YOUR-LNBITS/YOUR-EXTENSION/api/v1/EXAMPLE -d '{"amount":"100","memo":"example"}' -H "X-Api-Key: YOUR_WALLET-ADMIN/INVOICE-KEY"
+## 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.
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 574f772d..0e22e667 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -6,9 +6,22 @@ from lnbits.config import conf
from lnbits.helpers import urlsafe_short_hash
+async def get_admin_user():
+ if(conf.admin_users[0]):
+ return conf.admin_users[0]
+ from lnbits.core.crud import create_account, get_user
+ print("Seems like there's no admin users yet. Let's create an account for you!")
+ account = await create_account()
+ user = account.id
+ assert user, "Newly created user couldn't be retrieved"
+ print(f"Your newly created account/user id is: {user}. This will be the Super Admin user.")
+ return user
+
+
+
async def m001_create_admin_table(db):
# users/server
- user = conf.admin_users[0]
+ user = await get_admin_user()
admin_users = ",".join(conf.admin_users)
allowed_users = ",".join(conf.allowed_users)
admin_ext = ",".join(conf.admin_ext)
From 2f2d70f9a8cdd3edc59cb3c71b841b6823309dcf Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Mon, 16 May 2022 12:29:58 +0100
Subject: [PATCH 037/691] fix schemas for admin
---
lnbits/commands.py | 11 ++++++++---
lnbits/extensions/admin/crud.py | 12 ++++++------
lnbits/extensions/admin/migrations.py | 26 +++++++++++++-------------
3 files changed, 27 insertions(+), 22 deletions(-)
diff --git a/lnbits/commands.py b/lnbits/commands.py
index 8c39c338..7d9b49e2 100644
--- a/lnbits/commands.py
+++ b/lnbits/commands.py
@@ -55,8 +55,12 @@ def bundle_vendored():
async def get_admin_settings():
from lnbits.extensions.admin.models import Admin
- async with core_db.connect() as conn:
+ try:
+ ext_db = importlib.import_module(f"lnbits.extensions.admin").db
+ except:
+ return False
+ async with ext_db.connect() as conn:
if conn.type == SQLITE:
exists = await conn.fetchone(
"SELECT * FROM sqlite_master WHERE type='table' AND name='admin'"
@@ -65,11 +69,12 @@ async def get_admin_settings():
exists = await conn.fetchone(
"SELECT * FROM information_schema.tables WHERE table_name = 'admin'"
)
+ print("EXISTS", exists)
if not exists:
return False
- row = await conn.fetchone("SELECT * from admin")
-
+ row = await conn.fetchone("SELECT * from admin.admin")
+
return Admin(**row) if row else None
async def migrate_databases():
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index f866bc1a..67fbc614 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -29,30 +29,30 @@ async def update_admin(user: str, **kwargs) -> Admin:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
# print("UPDATE", q)
await db.execute(
- f'UPDATE admin SET {q} WHERE "user" = ?', (*kwargs.values(), user)
+ f'UPDATE admin.admin SET {q} WHERE "user" = ?', (*kwargs.values(), user)
)
- row = await db.fetchone('SELECT * FROM admin WHERE "user" = ?', (user,))
+ row = await db.fetchone('SELECT * FROM admin.admin WHERE "user" = ?', (user,))
assert row, "Newly updated settings couldn't be retrieved"
return Admin(**row) if row else None
async def get_admin() -> Admin:
- row = await db.fetchone("SELECT * FROM admin")
+ row = await db.fetchone("SELECT * FROM admin.admin")
return Admin(**row) if row else None
async def update_funding(data: Funding) -> Funding:
await db.execute(
"""
- UPDATE funding
+ UPDATE admin.funding
SET backend_wallet = ?, endpoint = ?, port = ?, read_key = ?, invoice_key = ?, admin_key = ?, cert = ?, balance = ?, selected = ?
WHERE id = ?
""",
(data.backend_wallet, data.endpoint, data.port, data.read_key, data.invoice_key, data.admin_key, data.cert, data.balance, data.selected, data.id,),
)
- row = await db.fetchone('SELECT * FROM funding WHERE "id" = ?', (data.id,))
+ row = await db.fetchone('SELECT * FROM admin.funding WHERE "id" = ?', (data.id,))
assert row, "Newly updated settings couldn't be retrieved"
return Funding(**row) if row else None
async def get_funding() -> List[Funding]:
- rows = await db.fetchall("SELECT * FROM funding")
+ rows = await db.fetchall("SELECT * FROM admin.funding")
return [Funding(**row) for row in rows]
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 0e22e667..c94d140b 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -96,7 +96,7 @@ async def m001_create_admin_table(db):
await db.execute(
"""
- CREATE TABLE IF NOT EXISTS admin (
+ CREATE TABLE IF NOT EXISTS admin.admin (
"user" TEXT PRIMARY KEY,
admin_users TEXT,
allowed_users TEXT,
@@ -120,7 +120,7 @@ async def m001_create_admin_table(db):
)
await db.execute(
"""
- INSERT INTO admin (
+ INSERT INTO admin.admin (
"user",
admin_users,
allowed_users,
@@ -171,7 +171,7 @@ async def m001_create_funding_table(db):
# Make the funding table, if it does not already exist
await db.execute(
"""
- CREATE TABLE IF NOT EXISTS funding (
+ CREATE TABLE IF NOT EXISTS admin.funding (
id TEXT PRIMARY KEY,
backend_wallet TEXT,
endpoint TEXT,
@@ -188,7 +188,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, selected)
VALUES (?, ?, ?, ?)
""",
(
@@ -200,7 +200,7 @@ async def m001_create_funding_table(db):
)
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
VALUES (?, ?, ?, ?, ?)
""",
(
@@ -214,7 +214,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
VALUES (?, ?, ?, ?, ?)
""",
(
@@ -228,7 +228,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, port, admin_key, cert, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, port, admin_key, cert, selected)
VALUES (?, ?, ?, ?, ?, ?, ?)
""",
(
@@ -244,7 +244,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, admin_key, cert, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, cert, selected)
VALUES (?, ?, ?, ?, ?, ?)
""",
(
@@ -259,7 +259,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, admin_key, cert, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, cert, selected)
VALUES (?, ?, ?, ?, ?, ?)
""",
(
@@ -274,7 +274,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
VALUES (?, ?, ?, ?, ?)
""",
(
@@ -288,7 +288,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
VALUES (?, ?, ?, ?, ?)
""",
(
@@ -302,7 +302,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
VALUES (?, ?, ?, ?, ?)
""",
(
@@ -317,7 +317,7 @@ async def m001_create_funding_table(db):
## PLACEHOLDER FOR ECLAIR WALLET
# await db.execute(
# """
- # INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ # INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
# VALUES (?, ?, ?, ?, ?)
# """,
# (
From 08e54de99b72eec2c8f7850ef0d346c15bf64705 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Mon, 16 May 2022 12:53:47 +0100
Subject: [PATCH 038/691] fix sqlite and show user account
---
lnbits/app.py | 1 +
lnbits/commands.py | 2 +-
lnbits/extensions/admin/migrations.py | 1 +
3 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 5df439dc..f066163f 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -117,6 +117,7 @@ def check_settings(app: FastAPI):
while True:
admin_set = await get_admin_settings()
if admin_set :
+ print(f"Access admin user account at: http://{lnbits.settings.HOST}:{lnbits.settings.PORT}/wallet?usr={admin_set.user}")
break
print("ERROR:", admin_set)
await asyncio.sleep(5)
diff --git a/lnbits/commands.py b/lnbits/commands.py
index 7d9b49e2..763a5b90 100644
--- a/lnbits/commands.py
+++ b/lnbits/commands.py
@@ -69,7 +69,7 @@ async def get_admin_settings():
exists = await conn.fetchone(
"SELECT * FROM information_schema.tables WHERE table_name = 'admin'"
)
- print("EXISTS", exists)
+
if not exists:
return False
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index c94d140b..6c5b507d 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -15,6 +15,7 @@ async def get_admin_user():
user = account.id
assert user, "Newly created user couldn't be retrieved"
print(f"Your newly created account/user id is: {user}. This will be the Super Admin user.")
+ conf.admin_users.insert(0, user)
return user
From 1adfb674ccb6bf44ad6e3680c795ed085bd20d8e Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Mon, 16 May 2022 15:35:04 +0100
Subject: [PATCH 039/691] cleanup and info to user on startup
---
lnbits/app.py | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index f066163f..950b6140 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -113,13 +113,11 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
def check_settings(app: FastAPI):
@app.on_event("startup")
async def check_settings_admin():
-
while True:
admin_set = await get_admin_settings()
if admin_set :
- print(f"Access admin user account at: http://{lnbits.settings.HOST}:{lnbits.settings.PORT}/wallet?usr={admin_set.user}")
break
- print("ERROR:", admin_set)
+ print("Waiting for admin settings... retrying in 5 seconds!")
await asyncio.sleep(5)
admin_set.admin_users = removeEmptyString(admin_set.admin_users.split(','))
@@ -129,6 +127,7 @@ def check_settings(app: FastAPI):
admin_set.theme = removeEmptyString(admin_set.theme.split(','))
admin_set.ad_space = removeEmptyString(admin_set.ad_space.split(','))
g().admin_conf = conf.copy(update=admin_set.dict())
+ print(f" ✔️ Access admin user account at: http://{lnbits.settings.HOST}:{lnbits.settings.PORT}/wallet?usr={admin_set.user}")
def check_funding_source(app: FastAPI) -> None:
@app.on_event("startup")
From 363bc85e3b73967c26b9809f1d71664ec8719d8d Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Wed, 8 Jun 2022 11:00:43 +0100
Subject: [PATCH 040/691] add custom logo
---
lnbits/config.py | 1 +
lnbits/extensions/admin/migrations.py | 58 ++-----------------
lnbits/extensions/admin/models.py | 2 +
.../admin/templates/admin/index.html | 20 +++++--
lnbits/helpers.py | 3 +-
5 files changed, 26 insertions(+), 58 deletions(-)
diff --git a/lnbits/config.py b/lnbits/config.py
index 3ce51c3c..d07ca044 100644
--- a/lnbits/config.py
+++ b/lnbits/config.py
@@ -39,6 +39,7 @@ class Settings(BaseSettings):
site_description: str = Field(default=None, env="LNBITS_SITE_DESCRIPTION")
default_wallet_name: str = Field(default="LNbits wallet", env="LNBITS_DEFAULT_WALLET_NAME")
theme: List[str] = Field(default=["classic, flamingo, mint, salvador, monochrome, autumn"], env="LNBITS_THEME_OPTIONS")
+ custom_logo: str = Field(default=None, env="LNBITS_CUSTOM_LOGO")
ad_space: List[str] = Field(default_factory=list, env="LNBITS_AD_SPACE")
# .env
env: Optional[str]
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 6c5b507d..aad66f02 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -41,60 +41,9 @@ async def m001_create_admin_table(db):
site_description = conf.site_description
default_wallet_name = conf.default_wallet_name
theme = ",".join(conf.theme)
+ custom_logo = conf.custom_logo
ad_space = ",".join(conf.ad_space)
- # if getenv("LNBITS_ADMIN_EXTENSIONS"):
- # admin_ext = getenv("LNBITS_ADMIN_EXTENSIONS")
-
- # if getenv("LNBITS_DATABASE_URL"):
- # database_url = getenv("LNBITS_DATABASE_URL")
-
- # if getenv("LNBITS_HIDE_API"):
- # hide_api = getenv("LNBITS_HIDE_API")
-
- # if getenv("LNBITS_THEME_OPTIONS"):
- # theme = getenv("LNBITS_THEME_OPTIONS")
-
- # if getenv("LNBITS_AD_SPACE"):
- # ad_space = getenv("LNBITS_AD_SPACE")
-
- # if getenv("LNBITS_SITE_TITLE"):
- # site_title = getenv("LNBITS_SITE_TITLE")
-
- # if getenv("LNBITS_SITE_TAGLINE"):
- # site_tagline = getenv("LNBITS_SITE_TAGLINE")
-
- # if getenv("LNBITS_SITE_DESCRIPTION"):
- # site_description = getenv("LNBITS_SITE_DESCRIPTION")
-
- # if getenv("LNBITS_ALLOWED_USERS"):
- # allowed_users = getenv("LNBITS_ALLOWED_USERS")
-
- # if getenv("LNBITS_ADMIN_USERS"):
- # admin_users = "".join(getenv("LNBITS_ADMIN_USERS").split())
- # user = admin_users.split(',')[0]
-
- # if getenv("LNBITS_DEFAULT_WALLET_NAME"):
- # default_wallet_name = getenv("LNBITS_DEFAULT_WALLET_NAME")
-
- # if getenv("LNBITS_DATA_FOLDER"):
- # data_folder = getenv("LNBITS_DATA_FOLDER")
-
- # if getenv("LNBITS_DISABLED_EXTENSIONS"):
- # disabled_ext = getenv("LNBITS_DISABLED_EXTENSIONS")
-
- # if getenv("LNBITS_FORCE_HTTPS"):
- # force_https = getenv("LNBITS_FORCE_HTTPS")
-
- # if getenv("LNBITS_SERVICE_FEE"):
- # service_fee = getenv("LNBITS_SERVICE_FEE")
-
- # if getenv("LNBITS_DENOMINATION"):
- # denomination = getenv("LNBITS_DENOMINATION", "sats")
-
- # if getenv("LNBITS_BACKEND_WALLET_CLASS"):
- # funding_source = getenv("LNBITS_BACKEND_WALLET_CLASS")
-
await db.execute(
"""
CREATE TABLE IF NOT EXISTS admin.admin (
@@ -115,6 +64,7 @@ async def m001_create_admin_table(db):
site_description TEXT,
default_wallet_name TEXT,
theme TEXT,
+ custom_logo TEXT,
ad_space TEXT
);
"""
@@ -139,8 +89,9 @@ async def m001_create_admin_table(db):
site_description,
default_wallet_name,
theme,
+ custom_logo,
ad_space)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
user,
@@ -160,6 +111,7 @@ async def m001_create_admin_table(db):
site_description,
default_wallet_name,
theme,
+ custom_logo,
ad_space,
),
)
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 0f25679d..3b17e720 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -23,6 +23,7 @@ class UpdateAdminSettings(BaseModel):
default_wallet_name: str = Query("LNbits wallet")
denomination: str = Query("sats")
theme: str = Query(None)
+ custom_logo: str = Query(None)
ad_space: str = Query(None)
class Admin(BaseModel):
@@ -46,6 +47,7 @@ class Admin(BaseModel):
default_wallet_name: Optional[str]
denomination: str = Field(default="sats")
theme: Optional[str]
+ custom_logo: Optional[str]
ad_space: Optional[str]
@classmethod
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 584d3a33..d9790051 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -705,6 +705,19 @@
+
@@ -718,10 +731,7 @@
-
+
@@ -1292,6 +1323,8 @@
disabled_ext,
funding_source,
force_https,
+ reserve_fee_min,
+ reserve_fee_pct,
service_fee,
hide_api,
site_title,
@@ -1311,6 +1344,8 @@
disabled_ext: disabled_ext.toString(),
funding_source,
force_https,
+ reserve_fee_min,
+ reserve_fee_pct,
service_fee,
hide_api,
site_title,
diff --git a/lnbits/settings.py b/lnbits/settings.py
index ed5c77f7..8e5c321a 100644
--- a/lnbits/settings.py
+++ b/lnbits/settings.py
@@ -1,6 +1,5 @@
import importlib
import subprocess
-from email.policy import default
from os import path
from typing import List
From fcf05a7dd19b831ee986578efad9b2d9094e69bd Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Wed, 8 Jun 2022 15:38:28 +0100
Subject: [PATCH 042/691] calle's semantics
---
lnbits/extensions/admin/templates/admin/index.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 832629bc..d34b9068 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -67,7 +67,7 @@
-
Minimum wallet reserve
+
Fee reserve
From faab389e3fa21671313b66236e66fccbf1f70a1d Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 5 Jul 2022 16:25:02 +0100
Subject: [PATCH 043/691] blacked
---
lnbits/extensions/admin/__init__.py | 1 +
lnbits/extensions/admin/crud.py | 23 ++++++++++++---
lnbits/extensions/admin/migrations.py | 10 ++++---
lnbits/extensions/admin/models.py | 2 ++
lnbits/extensions/admin/views.py | 10 ++++---
lnbits/extensions/admin/views_api.py | 41 ++++++++++++++-------------
6 files changed, 56 insertions(+), 31 deletions(-)
diff --git a/lnbits/extensions/admin/__init__.py b/lnbits/extensions/admin/__init__.py
index 6a56b2bb..24b91fe2 100644
--- a/lnbits/extensions/admin/__init__.py
+++ b/lnbits/extensions/admin/__init__.py
@@ -7,6 +7,7 @@ db = Database("ext_admin")
admin_ext: APIRouter = APIRouter(prefix="/admin", tags=["admin"])
+
def admin_renderer():
return template_renderer(["lnbits/extensions/admin/templates"])
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index 67fbc614..0d7019cc 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -11,13 +11,13 @@ from .models import Admin, Funding
async def update_wallet_balance(wallet_id: str, amount: int) -> str:
temp_id = f"temp_{urlsafe_short_hash()}"
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,
+ amount=amount * 1000,
memo="Admin top up",
pending=False,
)
@@ -25,6 +25,7 @@ async def update_wallet_balance(wallet_id: str, amount: int) -> str:
await internal_invoice_queue.put(internal_id)
return payment
+
async def update_admin(user: str, **kwargs) -> Admin:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
# print("UPDATE", q)
@@ -35,23 +36,37 @@ async def update_admin(user: str, **kwargs) -> Admin:
assert row, "Newly updated settings couldn't be retrieved"
return Admin(**row) if row else None
+
async def get_admin() -> Admin:
row = await db.fetchone("SELECT * FROM admin.admin")
return Admin(**row) if row else None
+
async def update_funding(data: Funding) -> Funding:
await db.execute(
"""
UPDATE admin.funding
SET backend_wallet = ?, endpoint = ?, port = ?, read_key = ?, invoice_key = ?, admin_key = ?, cert = ?, balance = ?, selected = ?
WHERE id = ?
- """,
- (data.backend_wallet, data.endpoint, data.port, data.read_key, data.invoice_key, data.admin_key, data.cert, data.balance, data.selected, data.id,),
+ """,
+ (
+ data.backend_wallet,
+ data.endpoint,
+ data.port,
+ data.read_key,
+ data.invoice_key,
+ data.admin_key,
+ data.cert,
+ data.balance,
+ data.selected,
+ data.id,
+ ),
)
row = await db.fetchone('SELECT * FROM admin.funding WHERE "id" = ?', (data.id,))
assert row, "Newly updated settings couldn't be retrieved"
return Funding(**row) if row else None
+
async def get_funding() -> List[Funding]:
rows = await db.fetchall("SELECT * FROM admin.funding")
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index f3663435..388f5ec6 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -7,19 +7,21 @@ from lnbits.helpers import urlsafe_short_hash
async def get_admin_user():
- if(conf.admin_users[0]):
+ if conf.admin_users[0]:
return conf.admin_users[0]
from lnbits.core.crud import create_account, get_user
+
print("Seems like there's no admin users yet. Let's create an account for you!")
account = await create_account()
user = account.id
assert user, "Newly created user couldn't be retrieved"
- print(f"Your newly created account/user id is: {user}. This will be the Super Admin user.")
+ print(
+ f"Your newly created account/user id is: {user}. This will be the Super Admin user."
+ )
conf.admin_users.insert(0, user)
return user
-
async def m001_create_admin_table(db):
# users/server
user = await get_admin_user()
@@ -28,7 +30,7 @@ async def m001_create_admin_table(db):
admin_ext = ",".join(conf.admin_ext)
disabled_ext = ",".join(conf.disabled_ext)
funding_source = conf.funding_source
- #operational
+ # operational
data_folder = conf.data_folder
database_url = conf.database_url
force_https = conf.force_https
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 3d8efdcd..6e95d68f 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -28,6 +28,7 @@ class UpdateAdminSettings(BaseModel):
custom_logo: str = Query(None)
ad_space: str = Query(None)
+
class Admin(BaseModel):
# users
user: str
@@ -59,6 +60,7 @@ class Admin(BaseModel):
data = dict(row)
return cls(**data)
+
class Funding(BaseModel):
id: str
backend_wallet: str
diff --git a/lnbits/extensions/admin/views.py b/lnbits/extensions/admin/views.py
index 24b8ca85..ceda5192 100644
--- a/lnbits/extensions/admin/views.py
+++ b/lnbits/extensions/admin/views.py
@@ -16,19 +16,21 @@ from .crud import get_admin, get_funding
templates = Jinja2Templates(directory="templates")
+
@admin_ext.get("/", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_user_exists)):
admin = await get_admin()
funding = [f.dict() for f in await get_funding()]
error, balance = await g().WALLET.status()
-
+
return admin_renderer().TemplateResponse(
- "admin/index.html", {
+ "admin/index.html",
+ {
"request": request,
"user": user.dict(),
"admin": admin.dict(),
"funding": funding,
"settings": g().admin_conf.dict(),
- "balance": balance
- }
+ "balance": balance,
+ },
)
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index c0650c8a..784ad97f 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -15,16 +15,18 @@ from .crud import get_admin, update_admin, update_funding, update_wallet_balance
@admin_ext.get("/api/v1/admin/{wallet_id}/{topup_amount}", status_code=HTTPStatus.OK)
-async def api_update_balance(wallet_id, topup_amount: int, g: WalletTypeInfo = Depends(require_admin_key)):
+async def api_update_balance(
+ wallet_id, topup_amount: int, g: WalletTypeInfo = Depends(require_admin_key)
+):
try:
wallet = await get_wallet(wallet_id)
except:
raise HTTPException(
- status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
- )
+ status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
+ )
await update_wallet_balance(wallet_id=wallet_id, amount=int(topup_amount))
-
+
return {"status": "Success"}
@@ -32,39 +34,40 @@ async def api_update_balance(wallet_id, topup_amount: int, g: WalletTypeInfo = D
async def api_update_admin(
request: Request,
data: UpdateAdminSettings = Body(...),
- w: WalletTypeInfo = Depends(require_admin_key)
- ):
+ w: WalletTypeInfo = Depends(require_admin_key),
+):
admin = await get_admin()
# print(data)
if not admin.user == w.wallet.user:
raise HTTPException(
- status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
- )
+ status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
+ )
updated = await update_admin(user=w.wallet.user, **data.dict())
- updated.admin_users = removeEmptyString(updated.admin_users.split(','))
- updated.allowed_users = removeEmptyString(updated.allowed_users.split(','))
- updated.admin_ext = removeEmptyString(updated.admin_ext.split(','))
- updated.disabled_ext = removeEmptyString(updated.disabled_ext.split(','))
- updated.theme = removeEmptyString(updated.theme.split(','))
- updated.ad_space = removeEmptyString(updated.ad_space.split(','))
+ updated.admin_users = removeEmptyString(updated.admin_users.split(","))
+ updated.allowed_users = removeEmptyString(updated.allowed_users.split(","))
+ updated.admin_ext = removeEmptyString(updated.admin_ext.split(","))
+ updated.disabled_ext = removeEmptyString(updated.disabled_ext.split(","))
+ updated.theme = removeEmptyString(updated.theme.split(","))
+ updated.ad_space = removeEmptyString(updated.ad_space.split(","))
g().admin_conf = g().admin_conf.copy(update=updated.dict())
-
+
# print(g().admin_conf)
return {"status": "Success"}
+
@admin_ext.post("/api/v1/admin/funding/", status_code=HTTPStatus.OK)
async def api_update_funding(
request: Request,
data: Funding = Body(...),
- w: WalletTypeInfo = Depends(require_admin_key)
- ):
+ w: WalletTypeInfo = Depends(require_admin_key),
+):
admin = await get_admin()
if not admin.user == w.wallet.user:
raise HTTPException(
- status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
- )
+ status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
+ )
funding = await update_funding(data=data)
return funding
From c319b84d7299eb5f7d942214fab2f21deffb38f6 Mon Sep 17 00:00:00 2001
From: ben
Date: Wed, 21 Sep 2022 15:28:13 +0100
Subject: [PATCH 044/691] Had to add a couple of tries
---
lnbits/core/views/generic.py | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py
index 83648c44..63f7af68 100644
--- a/lnbits/core/views/generic.py
+++ b/lnbits/core/views/generic.py
@@ -133,12 +133,19 @@ async def wallet(
return template_renderer().TemplateResponse(
"error.html", {"request": request, "err": "User does not exist."}
)
- if LNBITS_ALLOWED_USERS and user_id not in LNBITS_ALLOWED_USERS:
- return template_renderer().TemplateResponse(
- "error.html", {"request": request, "err": "User not authorized."}
- )
- if LNBITS_ADMIN_USERS and user_id in LNBITS_ADMIN_USERS:
- user.admin = True
+ try:
+ if LNBITS_ALLOWED_USERS and user_id not in LNBITS_ALLOWED_USERS:
+ return template_renderer().TemplateResponse(
+ "error.html", {"request": request, "err": "User not authorized."}
+ )
+ except:
+ pass
+
+ try:
+ if LNBITS_ADMIN_USERS and user_id in LNBITS_ADMIN_USERS:
+ user.admin = True
+ except:
+ pass
if not wallet_id:
if user.wallets and not wallet_name: # type: ignore
wallet = user.wallets[0] # type: ignore
From d8a13ed29d323f5233c6d9ba5cb59f9ef352d90c Mon Sep 17 00:00:00 2001
From: ben
Date: Wed, 21 Sep 2022 15:31:31 +0100
Subject: [PATCH 045/691] Added couple more tries
---
lnbits/decorators.py | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/lnbits/decorators.py b/lnbits/decorators.py
index f951163f..a810892d 100644
--- a/lnbits/decorators.py
+++ b/lnbits/decorators.py
@@ -239,13 +239,16 @@ async def check_user_exists(usr: UUID4) -> User:
if LNBITS_ADMIN_UI:
LNBITS_ADMIN_USERS = g().admin_conf.admin_users
LNBITS_ALLOWED_USERS = g().admin_conf.allowed_users
-
- if LNBITS_ALLOWED_USERS and g().user.id not in LNBITS_ALLOWED_USERS:
- raise HTTPException(
- status_code=HTTPStatus.UNAUTHORIZED, detail="User not authorized."
- )
-
- if LNBITS_ADMIN_USERS and g().user.id in LNBITS_ADMIN_USERS:
- g().user.admin = True
-
+ try:
+ if LNBITS_ALLOWED_USERS and g().user.id not in LNBITS_ALLOWED_USERS:
+ raise HTTPException(
+ status_code=HTTPStatus.UNAUTHORIZED, detail="User not authorized."
+ )
+ except:
+ pass
+ try:
+ if LNBITS_ADMIN_USERS and g().user.id in LNBITS_ADMIN_USERS:
+ g().user.admin = True
+ except:
+ pass
return g().user
From 55a44030283b34b6d61c0d441b779b135b449c3a Mon Sep 17 00:00:00 2001
From: ben
Date: Wed, 21 Sep 2022 15:35:06 +0100
Subject: [PATCH 046/691] Reverted try
---
lnbits/decorators.py | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/lnbits/decorators.py b/lnbits/decorators.py
index a810892d..904ca1c2 100644
--- a/lnbits/decorators.py
+++ b/lnbits/decorators.py
@@ -239,16 +239,12 @@ async def check_user_exists(usr: UUID4) -> User:
if LNBITS_ADMIN_UI:
LNBITS_ADMIN_USERS = g().admin_conf.admin_users
LNBITS_ALLOWED_USERS = g().admin_conf.allowed_users
- try:
- if LNBITS_ALLOWED_USERS and g().user.id not in LNBITS_ALLOWED_USERS:
- raise HTTPException(
- status_code=HTTPStatus.UNAUTHORIZED, detail="User not authorized."
- )
- except:
- pass
- try:
- if LNBITS_ADMIN_USERS and g().user.id in LNBITS_ADMIN_USERS:
- g().user.admin = True
+ if LNBITS_ALLOWED_USERS and g().user.id not in LNBITS_ALLOWED_USERS:
+ raise HTTPException(
+ status_code=HTTPStatus.UNAUTHORIZED, detail="User not authorized."
+ )
+ if LNBITS_ADMIN_USERS and g().user.id in LNBITS_ADMIN_USERS:
+ g().user.admin = True
except:
pass
return g().user
From a932f8a3d0c43692f6ec2b1ae9284c279ab7396c Mon Sep 17 00:00:00 2001
From: ben
Date: Wed, 21 Sep 2022 15:37:07 +0100
Subject: [PATCH 047/691] reverted other try
---
lnbits/core/views/generic.py | 19 ++++++-------------
lnbits/decorators.py | 2 --
2 files changed, 6 insertions(+), 15 deletions(-)
diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py
index 63f7af68..83648c44 100644
--- a/lnbits/core/views/generic.py
+++ b/lnbits/core/views/generic.py
@@ -133,19 +133,12 @@ async def wallet(
return template_renderer().TemplateResponse(
"error.html", {"request": request, "err": "User does not exist."}
)
- try:
- if LNBITS_ALLOWED_USERS and user_id not in LNBITS_ALLOWED_USERS:
- return template_renderer().TemplateResponse(
- "error.html", {"request": request, "err": "User not authorized."}
- )
- except:
- pass
-
- try:
- if LNBITS_ADMIN_USERS and user_id in LNBITS_ADMIN_USERS:
- user.admin = True
- except:
- pass
+ if LNBITS_ALLOWED_USERS and user_id not in LNBITS_ALLOWED_USERS:
+ return template_renderer().TemplateResponse(
+ "error.html", {"request": request, "err": "User not authorized."}
+ )
+ if LNBITS_ADMIN_USERS and user_id in LNBITS_ADMIN_USERS:
+ user.admin = True
if not wallet_id:
if user.wallets and not wallet_name: # type: ignore
wallet = user.wallets[0] # type: ignore
diff --git a/lnbits/decorators.py b/lnbits/decorators.py
index 904ca1c2..dd26d8fe 100644
--- a/lnbits/decorators.py
+++ b/lnbits/decorators.py
@@ -245,6 +245,4 @@ async def check_user_exists(usr: UUID4) -> User:
)
if LNBITS_ADMIN_USERS and g().user.id in LNBITS_ADMIN_USERS:
g().user.admin = True
- except:
- pass
return g().user
From c32e0cbecb147918b2c95ad29bcaf8876855ac0b Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Wed, 21 Sep 2022 18:40:46 +0100
Subject: [PATCH 048/691] fix main merge missing settings
---
lnbits/app.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lnbits/app.py b/lnbits/app.py
index 950b6140..49ef3d1b 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -56,6 +56,11 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
"url": "https://raw.githubusercontent.com/lnbits/lnbits-legend/main/LICENSE",
},
)
+ if lnbits.settings.LNBITS_ADMIN_UI:
+ g().admin_conf = conf
+ check_settings(app)
+
+ g().WALLET = WALLET
app.mount("/static", StaticFiles(packages=[("lnbits", "static")]), name="static")
app.mount(
"/core/static",
From e4c310d197fbb6ddb9a7d5528aab66fe60608313 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Thu, 22 Sep 2022 10:46:11 +0200
Subject: [PATCH 049/691] format
---
lnbits/app.py | 22 +++++++++++++---------
lnbits/commands.py | 6 +++++-
lnbits/config.py | 25 ++++++++++++++++++-------
lnbits/core/views/generic.py | 1 +
lnbits/decorators.py | 2 +-
lnbits/helpers.py | 8 +++++---
6 files changed, 43 insertions(+), 21 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 49ef3d1b..00ed6d8d 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -115,24 +115,28 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
return app
+
def check_settings(app: FastAPI):
@app.on_event("startup")
async def check_settings_admin():
while True:
admin_set = await get_admin_settings()
- if admin_set :
+ if admin_set:
break
print("Waiting for admin settings... retrying in 5 seconds!")
await asyncio.sleep(5)
-
- admin_set.admin_users = removeEmptyString(admin_set.admin_users.split(','))
- admin_set.allowed_users = removeEmptyString(admin_set.allowed_users.split(','))
- admin_set.admin_ext = removeEmptyString(admin_set.admin_ext.split(','))
- admin_set.disabled_ext = removeEmptyString(admin_set.disabled_ext.split(','))
- admin_set.theme = removeEmptyString(admin_set.theme.split(','))
- admin_set.ad_space = removeEmptyString(admin_set.ad_space.split(','))
+
+ admin_set.admin_users = removeEmptyString(admin_set.admin_users.split(","))
+ admin_set.allowed_users = removeEmptyString(admin_set.allowed_users.split(","))
+ admin_set.admin_ext = removeEmptyString(admin_set.admin_ext.split(","))
+ admin_set.disabled_ext = removeEmptyString(admin_set.disabled_ext.split(","))
+ admin_set.theme = removeEmptyString(admin_set.theme.split(","))
+ admin_set.ad_space = removeEmptyString(admin_set.ad_space.split(","))
g().admin_conf = conf.copy(update=admin_set.dict())
- print(f" ✔️ Access admin user account at: http://{lnbits.settings.HOST}:{lnbits.settings.PORT}/wallet?usr={admin_set.user}")
+ print(
+ f" ✔️ Access admin user account at: http://{lnbits.settings.HOST}:{lnbits.settings.PORT}/wallet?usr={admin_set.user}"
+ )
+
def check_funding_source(app: FastAPI) -> None:
@app.on_event("startup")
diff --git a/lnbits/commands.py b/lnbits/commands.py
index 763a5b90..86868f1f 100644
--- a/lnbits/commands.py
+++ b/lnbits/commands.py
@@ -5,6 +5,7 @@ import re
import warnings
import click
+from genericpath import exists
from loguru import logger
from .core import db as core_db
@@ -52,6 +53,7 @@ def bundle_vendored():
with open(outputpath, "w") as f:
f.write(output)
+
async def get_admin_settings():
from lnbits.extensions.admin.models import Admin
@@ -61,6 +63,7 @@ async def get_admin_settings():
return False
async with ext_db.connect() as conn:
+
if conn.type == SQLITE:
exists = await conn.fetchone(
"SELECT * FROM sqlite_master WHERE type='table' AND name='admin'"
@@ -69,7 +72,7 @@ async def get_admin_settings():
exists = await conn.fetchone(
"SELECT * FROM information_schema.tables WHERE table_name = 'admin'"
)
-
+
if not exists:
return False
@@ -77,6 +80,7 @@ async def get_admin_settings():
return Admin(**row) if row else None
+
async def migrate_databases():
"""Creates the necessary databases if they don't exist already; or migrates them."""
diff --git a/lnbits/config.py b/lnbits/config.py
index 37b700fd..cf26ad21 100644
--- a/lnbits/config.py
+++ b/lnbits/config.py
@@ -6,17 +6,19 @@ from typing import List, Optional
from pydantic import BaseSettings, Field
wallets_module = importlib.import_module("lnbits.wallets")
-wallet_class = getattr(
+wallet_class = getattr(
wallets_module, getenv("LNBITS_BACKEND_WALLET_CLASS", "VoidWallet")
)
WALLET = wallet_class()
+
def list_parse_fallback(v):
try:
return json.loads(v)
except Exception as e:
- return v.replace(' ','').split(',')
+ return v.replace(" ", "").split(",")
+
class Settings(BaseSettings):
admin_ui: bool = Field(default=True, env="LNBITS_ADMIN_UI")
@@ -24,7 +26,9 @@ class Settings(BaseSettings):
admin_users: List[str] = Field(default_factory=list, env="LNBITS_ADMIN_USERS")
allowed_users: List[str] = Field(default_factory=list, env="LNBITS_ALLOWED_USERS")
admin_ext: List[str] = Field(default_factory=list, env="LNBITS_ADMIN_EXTENSIONS")
- disabled_ext: List[str] = Field(default_factory=list, env="LNBITS_DISABLED_EXTENSIONS")
+ disabled_ext: List[str] = Field(
+ default_factory=list, env="LNBITS_DISABLED_EXTENSIONS"
+ )
funding_source: str = Field(default="VoidWallet", env="LNBITS_BACKEND_WALLET_CLASS")
# ops
data_folder: str = Field(default=None, env="LNBITS_DATA_FOLDER")
@@ -37,10 +41,17 @@ class Settings(BaseSettings):
denomination: str = Field(default="sats", env="LNBITS_DENOMINATION")
# Change theme
site_title: str = Field(default="LNbits", env="LNBITS_SITE_TITLE")
- site_tagline: str = Field(default="free and open-source lightning wallet", env="LNBITS_SITE_TAGLINE")
+ site_tagline: str = Field(
+ default="free and open-source lightning wallet", env="LNBITS_SITE_TAGLINE"
+ )
site_description: str = Field(default=None, env="LNBITS_SITE_DESCRIPTION")
- default_wallet_name: str = Field(default="LNbits wallet", env="LNBITS_DEFAULT_WALLET_NAME")
- theme: List[str] = Field(default=["classic, flamingo, mint, salvador, monochrome, autumn"], env="LNBITS_THEME_OPTIONS")
+ default_wallet_name: str = Field(
+ default="LNbits wallet", env="LNBITS_DEFAULT_WALLET_NAME"
+ )
+ theme: List[str] = Field(
+ default=["classic, flamingo, mint, salvador, monochrome, autumn"],
+ env="LNBITS_THEME_OPTIONS",
+ )
custom_logo: str = Field(default=None, env="LNBITS_CUSTOM_LOGO")
ad_space: List[str] = Field(default_factory=list, env="LNBITS_AD_SPACE")
# .env
@@ -48,7 +59,7 @@ class Settings(BaseSettings):
debug: Optional[str]
host: Optional[str]
port: Optional[str]
- lnbits_path: Optional[str] = path.dirname(path.realpath(__file__))
+ lnbits_path: Optional[str] = path.dirname(path.realpath(__file__))
# @validator('admin_users', 'allowed_users', 'admin_ext', 'disabled_ext', pre=True)
# def validate(cls, val):
diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py
index 83648c44..3a1fbdfc 100644
--- a/lnbits/core/views/generic.py
+++ b/lnbits/core/views/generic.py
@@ -39,6 +39,7 @@ from ..services import pay_invoice, redeem_lnurl_withdraw
core_html_routes: APIRouter = APIRouter(tags=["Core NON-API Website Routes"])
+
@core_html_routes.get("/favicon.ico", response_class=FileResponse)
async def favicon():
return FileResponse("lnbits/core/static/favicon.ico")
diff --git a/lnbits/decorators.py b/lnbits/decorators.py
index dd26d8fe..58b025aa 100644
--- a/lnbits/decorators.py
+++ b/lnbits/decorators.py
@@ -235,7 +235,7 @@ async def check_user_exists(usr: UUID4) -> User:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="User does not exist."
)
-
+
if LNBITS_ADMIN_UI:
LNBITS_ADMIN_USERS = g().admin_conf.admin_users
LNBITS_ALLOWED_USERS = g().admin_conf.allowed_users
diff --git a/lnbits/helpers.py b/lnbits/helpers.py
index 7bd1b54a..f4255c86 100644
--- a/lnbits/helpers.py
+++ b/lnbits/helpers.py
@@ -157,11 +157,13 @@ def url_for(endpoint: str, external: Optional[bool] = False, **params: Any) -> s
url = f"{base}{endpoint}{url_params}"
return url
+
def removeEmptyString(arr):
return list(filter(None, arr))
+
def template_renderer(additional_folders: List = []) -> Jinja2Templates:
- if(settings.LNBITS_ADMIN_UI):
+ if settings.LNBITS_ADMIN_UI:
_ = g().admin_conf
settings.LNBITS_AD_SPACE = _.ad_space
settings.LNBITS_HIDE_API = _.hide_api
@@ -170,8 +172,8 @@ def template_renderer(additional_folders: List = []) -> Jinja2Templates:
settings.LNBITS_SITE_TAGLINE = _.site_tagline
settings.LNBITS_SITE_DESCRIPTION = _.site_description
settings.LNBITS_THEME_OPTIONS = _.theme
- settings.LNBITS_CUSTOM_LOGO = _.custom_logo
-
+ settings.LNBITS_CUSTOM_LOGO = _.custom_logo
+
t = Jinja2Templates(
loader=jinja2.FileSystemLoader(
["lnbits/templates", "lnbits/core/templates", *additional_folders]
From 6c2a9b2258087302487716e3d35b1b2387bb58ff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Thu, 22 Sep 2022 11:47:24 +0200
Subject: [PATCH 050/691] format black
---
lnbits/app.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/lnbits/app.py b/lnbits/app.py
index 00ed6d8d..6ae75d7a 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -56,6 +56,7 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
"url": "https://raw.githubusercontent.com/lnbits/lnbits-legend/main/LICENSE",
},
)
+
if lnbits.settings.LNBITS_ADMIN_UI:
g().admin_conf = conf
check_settings(app)
From 7c05d4c354be10d502b7c453f96902f76f9c15d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Thu, 22 Sep 2022 15:29:12 +0200
Subject: [PATCH 051/691] fix AD_SPACE
---
lnbits/core/templates/core/wallet.html | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/lnbits/core/templates/core/wallet.html b/lnbits/core/templates/core/wallet.html
index bccdc2b4..189b060b 100644
--- a/lnbits/core/templates/core/wallet.html
+++ b/lnbits/core/templates/core/wallet.html
@@ -385,12 +385,9 @@
- {% endif %} {% if AD_SPACE %} {% for ADS in AD_SPACE %} {% set AD =
- ADS.split(';') %}
+ {% endif %} {% if AD_SPACE %} {% for AD in AD_SPACE %}
- {% endfor %} {% endif %}
From 415165c6fe7ec2affda20078c81e12b4fc2944de Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Thu, 22 Sep 2022 15:55:37 +0200
Subject: [PATCH 052/691] fix some javascript errors when adding users
---
lnbits/extensions/admin/templates/admin/index.html | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index d34b9068..1e881cb6 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -1221,7 +1221,7 @@
addAdminUser() {
let addUser = this.data.admin_users_add
let admin_users = this.data.admin.admin_users
- if (addUser.length && !admin_users.includes(addUser)) {
+ if (addUser && addUser.length && !admin_users.includes(addUser)) {
admin_users.push(addUser)
this.data.admin.admin_users = admin_users
this.data.admin_users_add = ''
@@ -1234,7 +1234,7 @@
addAllowedUser() {
let addUser = this.data.allowed_users_add
let allowed_users = this.data.admin.allowed_users
- if (addUser.length && !allowed_users.includes(addUser)) {
+ if (addUser && addUser.length && !allowed_users.includes(addUser)) {
allowed_users.push(addUser)
this.data.admin.allowed_users = allowed_users
this.data.allowed_users_add = ''
@@ -1336,7 +1336,6 @@
custom_logo,
ad_space
} = this.data.admin
- //console.log("this", this.data.admin)
let data = {
admin_users: admin_users.toString(),
allowed_users: allowed_users.toString(),
From 850ed85311fea5c5e10bca8cdeaaa0a3dffbe71f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Thu, 22 Sep 2022 16:04:55 +0200
Subject: [PATCH 053/691] fix ADMIN_UI=false errors
---
lnbits/core/views/generic.py | 3 +++
lnbits/decorators.py | 6 ++++++
2 files changed, 9 insertions(+)
diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py
index 3a1fbdfc..db4fac43 100644
--- a/lnbits/core/views/generic.py
+++ b/lnbits/core/views/generic.py
@@ -124,6 +124,9 @@ async def wallet(
if LNBITS_ADMIN_UI:
LNBITS_ADMIN_USERS = g().admin_conf.admin_users
LNBITS_ALLOWED_USERS = g().admin_conf.allowed_users
+ else:
+ LNBITS_ADMIN_USERS = []
+ LNBITS_ALLOWED_USERS = []
if not user_id:
user = await get_user((await create_account()).id)
diff --git a/lnbits/decorators.py b/lnbits/decorators.py
index 58b025aa..5a3c0a5c 100644
--- a/lnbits/decorators.py
+++ b/lnbits/decorators.py
@@ -141,6 +141,8 @@ async def get_key_type(
if LNBITS_ADMIN_UI:
LNBITS_ADMIN_USERS = g().admin_conf.admin_users
+ else:
+ LNBITS_ADMIN_USERS = []
for typenr, WalletChecker in zip(
[0, 1], [WalletAdminKeyChecker, WalletInvoiceKeyChecker]
@@ -239,6 +241,10 @@ async def check_user_exists(usr: UUID4) -> User:
if LNBITS_ADMIN_UI:
LNBITS_ADMIN_USERS = g().admin_conf.admin_users
LNBITS_ALLOWED_USERS = g().admin_conf.allowed_users
+ else:
+ LNBITS_ADMIN_USERS = []
+ LNBITS_ALLOWED_USERS = []
+
if LNBITS_ALLOWED_USERS and g().user.id not in LNBITS_ALLOWED_USERS:
raise HTTPException(
status_code=HTTPStatus.UNAUTHORIZED, detail="User not authorized."
From 393d1a8204f04498aca712604f5646dcb30d7746 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Thu, 22 Sep 2022 16:14:17 +0200
Subject: [PATCH 054/691] prettier
---
lnbits/core/templates/core/wallet.html | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lnbits/core/templates/core/wallet.html b/lnbits/core/templates/core/wallet.html
index 189b060b..22c65bf3 100644
--- a/lnbits/core/templates/core/wallet.html
+++ b/lnbits/core/templates/core/wallet.html
@@ -386,8 +386,7 @@
{% endif %} {% if AD_SPACE %} {% for AD in AD_SPACE %}
-
- {% endfor %} {% endif %}
From 622d0f50da4b319765175c97613ab31e5e1dd722 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Thu, 22 Sep 2022 18:35:47 +0200
Subject: [PATCH 055/691] fix migration tests
---
lnbits/extensions/admin/migrations.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 388f5ec6..196c9fc0 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -7,7 +7,7 @@ from lnbits.helpers import urlsafe_short_hash
async def get_admin_user():
- if conf.admin_users[0]:
+ if len(conf.admin_users) > 0:
return conf.admin_users[0]
from lnbits.core.crud import create_account, get_user
From 26769d94984c5d7c4f56b1bd06ca4ce3e376453c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Mon, 26 Sep 2022 16:54:19 +0200
Subject: [PATCH 056/691] change comments to use multiple lines
---
.env.example | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/.env.example b/.env.example
index 7a49d5c5..c1ac7497 100644
--- a/.env.example
+++ b/.env.example
@@ -3,11 +3,15 @@ PORT=5000
DEBUG=false
-LNBITS_ADMIN_USERS="" # User IDs seperated by comma
-LNBITS_ADMIN_EXTENSIONS="ngrok, admin" # Extensions only admin can access
-LNBITS_ADMIN_UI=false # Enable Admin GUI, available for the first user in LNBITS_ADMIN_USERS if available
+# User IDs seperated by comma
+LNBITS_ADMIN_USERS=""
+# Extensions only admin can access
+LNBITS_ADMIN_EXTENSIONS="ngrok, admin"
+# Enable Admin GUI, available for the first user in LNBITS_ADMIN_USERS if available
+LNBITS_ADMIN_UI=false
-LNBITS_ALLOWED_USERS="" # Restricts access, User IDs seperated by comma
+# Restricts access, User IDs seperated by comma
+LNBITS_ALLOWED_USERS=""
LNBITS_DEFAULT_WALLET_NAME="LNbits wallet"
From cadb6b21617c77fac36ea55937a03c223ec5aa56 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Mon, 26 Sep 2022 16:59:30 +0200
Subject: [PATCH 057/691] fix merge error
---
lnbits/app.py | 4 ----
1 file changed, 4 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 6ae75d7a..60c09038 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -57,10 +57,6 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
},
)
- if lnbits.settings.LNBITS_ADMIN_UI:
- g().admin_conf = conf
- check_settings(app)
-
g().WALLET = WALLET
app.mount("/static", StaticFiles(packages=[("lnbits", "static")]), name="static")
app.mount(
From a78ebbacd700c7975662424e07bb042a2da380f1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Tue, 27 Sep 2022 14:14:36 +0200
Subject: [PATCH 058/691] use logger in app.py
---
lnbits/app.py | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 60c09038..d7bd3ea6 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -31,8 +31,6 @@ from .helpers import (
url_for_vendored,
)
from .requestvars import g
-
-# from .settings import WALLET
from .tasks import (
catch_everything_and_restart,
check_pending_payments,
@@ -120,7 +118,7 @@ def check_settings(app: FastAPI):
admin_set = await get_admin_settings()
if admin_set:
break
- print("Waiting for admin settings... retrying in 5 seconds!")
+ logger.info("Waiting for admin settings... retrying in 5 seconds!")
await asyncio.sleep(5)
admin_set.admin_users = removeEmptyString(admin_set.admin_users.split(","))
@@ -130,7 +128,7 @@ def check_settings(app: FastAPI):
admin_set.theme = removeEmptyString(admin_set.theme.split(","))
admin_set.ad_space = removeEmptyString(admin_set.ad_space.split(","))
g().admin_conf = conf.copy(update=admin_set.dict())
- print(
+ logger.info(
f" ✔️ Access admin user account at: http://{lnbits.settings.HOST}:{lnbits.settings.PORT}/wallet?usr={admin_set.user}"
)
From 8be9b950fdff51e8c9d94d4123cae0dfb650dd3b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Tue, 27 Sep 2022 14:14:57 +0200
Subject: [PATCH 059/691] fix config
---
lnbits/config.py | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/lnbits/config.py b/lnbits/config.py
index cf26ad21..874effae 100644
--- a/lnbits/config.py
+++ b/lnbits/config.py
@@ -17,7 +17,11 @@ def list_parse_fallback(v):
try:
return json.loads(v)
except Exception as e:
- return v.replace(" ", "").split(",")
+ replaced = v.replace(" ", "")
+ if replaced:
+ return replaced.split(",")
+ else:
+ return []
class Settings(BaseSettings):
@@ -48,10 +52,7 @@ class Settings(BaseSettings):
default_wallet_name: str = Field(
default="LNbits wallet", env="LNBITS_DEFAULT_WALLET_NAME"
)
- theme: List[str] = Field(
- default=["classic, flamingo, mint, salvador, monochrome, autumn"],
- env="LNBITS_THEME_OPTIONS",
- )
+ theme: List[str] = Field(default_factory=list, env="LNBITS_THEME_OPTIONS")
custom_logo: str = Field(default=None, env="LNBITS_CUSTOM_LOGO")
ad_space: List[str] = Field(default_factory=list, env="LNBITS_AD_SPACE")
# .env
@@ -74,4 +75,5 @@ class Settings(BaseSettings):
conf = Settings()
+print(conf)
WALLET = wallet_class()
From f2e494384e96587b0b0fb2a9de8825aa9115ee21 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Tue, 27 Sep 2022 14:17:20 +0200
Subject: [PATCH 060/691] concatenate first migrations script
fixup
---
lnbits/config.py | 1 -
lnbits/extensions/admin/migrations.py | 7 +++----
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/lnbits/config.py b/lnbits/config.py
index 874effae..fe8dabf9 100644
--- a/lnbits/config.py
+++ b/lnbits/config.py
@@ -75,5 +75,4 @@ class Settings(BaseSettings):
conf = Settings()
-print(conf)
WALLET = wallet_class()
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 196c9fc0..2d48a8e4 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -23,6 +23,8 @@ async def get_admin_user():
async def m001_create_admin_table(db):
+
+
# users/server
user = await get_admin_user()
admin_users = ",".join(conf.admin_users)
@@ -78,7 +80,7 @@ async def m001_create_admin_table(db):
await db.execute(
"""
INSERT INTO admin.admin (
- "user",
+ "user",
admin_users,
allowed_users,
admin_ext,
@@ -126,9 +128,6 @@ async def m001_create_admin_table(db):
),
)
-
-async def m001_create_funding_table(db):
-
funding_wallet = getenv("LNBITS_BACKEND_WALLET_CLASS")
# Make the funding table, if it does not already exist
From 9757fad8684d166ce9ac04e6a69b0ff820c4de61 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Tue, 27 Sep 2022 16:37:08 +0200
Subject: [PATCH 061/691] add restart button to frontend
---
.../admin/templates/admin/index.html | 28 ++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 1e881cb6..319ca3f0 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -65,6 +65,14 @@
:options="data.funding_source"
>
+
+
+
Fee reserve
@@ -89,7 +97,7 @@
>
-
+
@@ -1257,6 +1265,24 @@
let spaces = this.data.admin.ad_space
this.data.admin.ad_space = spaces.filter(s => s !== ad)
},
+ restartServer() {
+ LNbits.api
+ .request(
+ 'GET',
+ '/admin/api/v1/admin/restart/',
+ this.g.user.wallets[0].adminkey
+ )
+ .then(response => {
+ this.$q.notify({
+ type: 'positive',
+ message: 'Success! Restarted Server',
+ icon: null
+ })
+ })
+ .catch(function (error) {
+ LNbits.utils.notifyApiError(error)
+ })
+ },
topupWallet() {
LNbits.api
.request(
From 66739f4246bdc6d3b347f54f675c00937601935e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Mon, 3 Oct 2022 16:34:52 +0200
Subject: [PATCH 062/691] make extension use new settings
---
lnbits/extensions/boltz/boltz.py | 14 ++++++--------
lnbits/extensions/boltz/mempool.py | 15 ++++++---------
lnbits/extensions/boltz/views_api.py | 4 ++--
lnbits/extensions/lndhub/views_api.py | 4 ++--
lnbits/extensions/tpos/views.py | 14 +++++++-------
5 files changed, 23 insertions(+), 28 deletions(-)
diff --git a/lnbits/extensions/boltz/boltz.py b/lnbits/extensions/boltz/boltz.py
index ac99d4f4..424d0bf7 100644
--- a/lnbits/extensions/boltz/boltz.py
+++ b/lnbits/extensions/boltz/boltz.py
@@ -12,7 +12,7 @@ from loguru import logger
from lnbits.core.services import create_invoice, pay_invoice
from lnbits.helpers import urlsafe_short_hash
-from lnbits.settings import BOLTZ_NETWORK, BOLTZ_URL
+from lnbits.settings import settings
from .crud import update_swap_status
from .mempool import (
@@ -33,9 +33,7 @@ from .models import (
)
from .utils import check_balance, get_timestamp, req_wrap
-net = NETWORKS[BOLTZ_NETWORK]
-logger.trace(f"BOLTZ_URL: {BOLTZ_URL}")
-logger.trace(f"Bitcoin Network: {net['name']}")
+net = NETWORKS[settings.boltz_network]
async def create_swap(data: CreateSubmarineSwap) -> SubmarineSwap:
@@ -62,7 +60,7 @@ async def create_swap(data: CreateSubmarineSwap) -> SubmarineSwap:
res = req_wrap(
"post",
- f"{BOLTZ_URL}/createswap",
+ f"{settings.boltz_url}/createswap",
json={
"type": "submarine",
"pairId": "BTC/BTC",
@@ -129,7 +127,7 @@ async def create_reverse_swap(
res = req_wrap(
"post",
- f"{BOLTZ_URL}/createswap",
+ f"{settings.boltz_url}/createswap",
json={
"type": "reversesubmarine",
"pairId": "BTC/BTC",
@@ -409,7 +407,7 @@ def check_boltz_limits(amount):
def get_boltz_pairs():
res = req_wrap(
"get",
- f"{BOLTZ_URL}/getpairs",
+ f"{settings.boltz_url}/getpairs",
headers={"Content-Type": "application/json"},
)
return res.json()
@@ -418,7 +416,7 @@ def get_boltz_pairs():
def get_boltz_status(boltzid):
res = req_wrap(
"post",
- f"{BOLTZ_URL}/swapstatus",
+ f"{settings.boltz_url}/swapstatus",
json={"id": boltzid},
)
return res.json()
diff --git a/lnbits/extensions/boltz/mempool.py b/lnbits/extensions/boltz/mempool.py
index a44c0f02..a64cadad 100644
--- a/lnbits/extensions/boltz/mempool.py
+++ b/lnbits/extensions/boltz/mempool.py
@@ -7,14 +7,11 @@ import websockets
from embit.transaction import Transaction
from loguru import logger
-from lnbits.settings import BOLTZ_MEMPOOL_SPACE_URL, BOLTZ_MEMPOOL_SPACE_URL_WS
+from lnbits.settings import settings
from .utils import req_wrap
-logger.trace(f"BOLTZ_MEMPOOL_SPACE_URL: {BOLTZ_MEMPOOL_SPACE_URL}")
-logger.trace(f"BOLTZ_MEMPOOL_SPACE_URL_WS: {BOLTZ_MEMPOOL_SPACE_URL_WS}")
-
-websocket_url = f"{BOLTZ_MEMPOOL_SPACE_URL_WS}/api/v1/ws"
+websocket_url = f"{settings.boltz_mempool_space_url_ws}/api/v1/ws"
async def wait_for_websocket_message(send, message_string):
@@ -33,7 +30,7 @@ async def wait_for_websocket_message(send, message_string):
def get_mempool_tx(address):
res = req_wrap(
"get",
- f"{BOLTZ_MEMPOOL_SPACE_URL}/api/address/{address}/txs",
+ f"{settings.boltz_mempool_space_url}/api/address/{address}/txs",
headers={"Content-Type": "text/plain"},
)
txs = res.json()
@@ -70,7 +67,7 @@ def get_fee_estimation() -> int:
def get_mempool_fees() -> int:
res = req_wrap(
"get",
- f"{BOLTZ_MEMPOOL_SPACE_URL}/api/v1/fees/recommended",
+ f"{settings.boltz_mempool_space_url}/api/v1/fees/recommended",
headers={"Content-Type": "text/plain"},
)
fees = res.json()
@@ -80,7 +77,7 @@ def get_mempool_fees() -> int:
def get_mempool_blockheight() -> int:
res = req_wrap(
"get",
- f"{BOLTZ_MEMPOOL_SPACE_URL}/api/blocks/tip/height",
+ f"{settings.boltz_mempool_space_url}/api/blocks/tip/height",
headers={"Content-Type": "text/plain"},
)
return int(res.text)
@@ -91,7 +88,7 @@ async def send_onchain_tx(tx: Transaction):
logger.debug(f"Boltz - mempool sending onchain tx...")
req_wrap(
"post",
- f"{BOLTZ_MEMPOOL_SPACE_URL}/api/tx",
+ f"{settings.boltz_mempool_space_url}/api/tx",
headers={"Content-Type": "text/plain"},
content=raw,
)
diff --git a/lnbits/extensions/boltz/views_api.py b/lnbits/extensions/boltz/views_api.py
index a4b7d318..18ca14cb 100644
--- a/lnbits/extensions/boltz/views_api.py
+++ b/lnbits/extensions/boltz/views_api.py
@@ -14,7 +14,7 @@ from starlette.requests import Request
from lnbits.core.crud import get_user
from lnbits.decorators import WalletTypeInfo, get_key_type, require_admin_key
-from lnbits.settings import BOLTZ_MEMPOOL_SPACE_URL
+from lnbits.settings import settings
from . import boltz_ext
from .boltz import (
@@ -55,7 +55,7 @@ from .utils import check_balance
response_model=str,
)
async def api_mempool_url():
- return BOLTZ_MEMPOOL_SPACE_URL
+ return settings.boltz_mempool_space_url
# NORMAL SWAP
diff --git a/lnbits/extensions/lndhub/views_api.py b/lnbits/extensions/lndhub/views_api.py
index 8cbe5a6b..b2328c39 100644
--- a/lnbits/extensions/lndhub/views_api.py
+++ b/lnbits/extensions/lndhub/views_api.py
@@ -12,7 +12,7 @@ from lnbits import bolt11
from lnbits.core.crud import delete_expired_invoices, get_payments
from lnbits.core.services import create_invoice, pay_invoice
from lnbits.decorators import WalletTypeInfo
-from lnbits.settings import LNBITS_SITE_TITLE, WALLET
+from lnbits.settings import WALLET, settings
from . import lndhub_ext
from .decorators import check_wallet, require_admin_key
@@ -56,7 +56,7 @@ async def lndhub_addinvoice(
_, pr = await create_invoice(
wallet_id=wallet.wallet.id,
amount=int(data.amt),
- memo=data.memo or LNBITS_SITE_TITLE,
+ memo=data.memo or settings.lnbits_site_title,
extra={"tag": "lndhub"},
)
except:
diff --git a/lnbits/extensions/tpos/views.py b/lnbits/extensions/tpos/views.py
index e1f1d21e..dac129a9 100644
--- a/lnbits/extensions/tpos/views.py
+++ b/lnbits/extensions/tpos/views.py
@@ -8,7 +8,7 @@ from starlette.responses import HTMLResponse
from lnbits.core.models import User
from lnbits.decorators import check_user_exists
-from lnbits.settings import LNBITS_CUSTOM_LOGO, LNBITS_SITE_TITLE
+from lnbits.settings import settings
from . import tpos_ext, tpos_renderer
from .crud import get_tpos
@@ -50,12 +50,12 @@ async def manifest(tpos_id: str):
)
return {
- "short_name": LNBITS_SITE_TITLE,
- "name": tpos.name + " - " + LNBITS_SITE_TITLE,
+ "short_name": settings.lnbits_site_title,
+ "name": tpos.name + " - " + settings.lnbits_site_title,
"icons": [
{
- "src": LNBITS_CUSTOM_LOGO
- if LNBITS_CUSTOM_LOGO
+ "src": settings.lnbits_custom_logo
+ if settings.lnbits_custom_logo
else "https://cdn.jsdelivr.net/gh/lnbits/lnbits@0.3.0/docs/logos/lnbits.png",
"type": "image/png",
"sizes": "900x900",
@@ -69,9 +69,9 @@ async def manifest(tpos_id: str):
"theme_color": "#1F2234",
"shortcuts": [
{
- "name": tpos.name + " - " + LNBITS_SITE_TITLE,
+ "name": tpos.name + " - " + settings.lnbits_site_title,
"short_name": tpos.name,
- "description": tpos.name + " - " + LNBITS_SITE_TITLE,
+ "description": tpos.name + " - " + settings.lnbits_site_title,
"url": "/tpos/" + tpos_id,
}
],
From 2b2884142fd9c2ac6fbfa3cbd8916aaf2225068a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Mon, 3 Oct 2022 16:35:26 +0200
Subject: [PATCH 063/691] remove enviroms
---
pyproject.toml | 1 -
1 file changed, 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 19dac860..7a69ec43 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -20,7 +20,6 @@ charset-normalizer = "2.0.6"
click = "8.0.1"
ecdsa = "0.17.0"
embit = "0.4.9"
-environs = "9.3.3"
fastapi = "0.78.0"
h11 = "0.12.0"
httpcore = "0.15.0"
From 840ede1bd66fd437e342bbefc0880de6fc2f216c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Mon, 3 Oct 2022 16:36:14 +0200
Subject: [PATCH 064/691] fix admin
---
lnbits/extensions/admin/crud.py | 24 +-
lnbits/extensions/admin/migrations.py | 337 +----
lnbits/extensions/admin/models.py | 58 +-
.../admin/templates/admin/_tab_funding.html | 158 +++
.../admin/templates/admin/_tab_server.html | 78 ++
.../admin/templates/admin/_tab_theme.html | 122 ++
.../admin/templates/admin/_tab_users.html | 96 ++
.../admin/templates/admin/index.html | 1133 +----------------
lnbits/extensions/admin/views.py | 16 +-
lnbits/extensions/admin/views_api.py | 28 +-
10 files changed, 576 insertions(+), 1474 deletions(-)
create mode 100644 lnbits/extensions/admin/templates/admin/_tab_funding.html
create mode 100644 lnbits/extensions/admin/templates/admin/_tab_server.html
create mode 100644 lnbits/extensions/admin/templates/admin/_tab_theme.html
create mode 100644 lnbits/extensions/admin/templates/admin/_tab_users.html
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index 0d7019cc..e4cb5d77 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -2,10 +2,11 @@ from typing import List
from lnbits.core.crud import create_payment
from lnbits.helpers import urlsafe_short_hash
+from lnbits.settings import Settings
from lnbits.tasks import internal_invoice_queue
from . import db
-from .models import Admin, Funding
+from .models import Funding
async def update_wallet_balance(wallet_id: str, amount: int) -> str:
@@ -23,26 +24,26 @@ async def update_wallet_balance(wallet_id: str, amount: int) -> str:
)
# manually send this for now
await internal_invoice_queue.put(internal_id)
- return payment
-async def update_admin(user: str, **kwargs) -> Admin:
+async def update_settings(user: str, **kwargs) -> Settings:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
# print("UPDATE", q)
await db.execute(
- f'UPDATE admin.admin SET {q} WHERE "user" = ?', (*kwargs.values(), user)
+ f'UPDATE admin.settings SET {q} WHERE "user" = ?', (*kwargs.values(), user)
)
- row = await db.fetchone('SELECT * FROM admin.admin WHERE "user" = ?', (user,))
+ row = await db.fetchone('SELECT * FROM admin.settings WHERE "user" = ?', (user,))
assert row, "Newly updated settings couldn't be retrieved"
- return Admin(**row) if row else None
-
-
-async def get_admin() -> Admin:
- row = await db.fetchone("SELECT * FROM admin.admin")
- return Admin(**row) if row else None
+ return Settings(**row) if row else None
async def update_funding(data: Funding) -> Funding:
+ await db.execute(
+ """
+ UPDATE admin.settings SET funding_source = ? WHERE user = ?
+ """,
+ (data.backend_wallet, data.user),
+ )
await db.execute(
"""
UPDATE admin.funding
@@ -69,5 +70,4 @@ async def update_funding(data: Funding) -> Funding:
async def get_funding() -> List[Funding]:
rows = await db.fetchall("SELECT * FROM admin.funding")
-
return [Funding(**row) for row in rows]
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 2d48a8e4..8f6c76a0 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -1,292 +1,57 @@
-from os import getenv
-
-from sqlalchemy.exc import OperationalError # type: ignore
-
-from lnbits.config import conf
-from lnbits.helpers import urlsafe_short_hash
-
-
-async def get_admin_user():
- if len(conf.admin_users) > 0:
- return conf.admin_users[0]
- from lnbits.core.crud import create_account, get_user
-
- print("Seems like there's no admin users yet. Let's create an account for you!")
- account = await create_account()
- user = account.id
- assert user, "Newly created user couldn't be retrieved"
- print(
- f"Your newly created account/user id is: {user}. This will be the Super Admin user."
- )
- conf.admin_users.insert(0, user)
- return user
-
-
-async def m001_create_admin_table(db):
-
-
- # users/server
- user = await get_admin_user()
- admin_users = ",".join(conf.admin_users)
- allowed_users = ",".join(conf.allowed_users)
- admin_ext = ",".join(conf.admin_ext)
- disabled_ext = ",".join(conf.disabled_ext)
- funding_source = conf.funding_source
- # operational
- data_folder = conf.data_folder
- database_url = conf.database_url
- force_https = conf.force_https
- reserve_fee_min = conf.reserve_fee_min
- reserve_fee_pct = conf.reserve_fee_pct
- service_fee = conf.service_fee
- hide_api = conf.hide_api
- denomination = conf.denomination
- # Theme'ing
- site_title = conf.site_title
- site_tagline = conf.site_tagline
- site_description = conf.site_description
- default_wallet_name = conf.default_wallet_name
- theme = ",".join(conf.theme)
- custom_logo = conf.custom_logo
- ad_space = ",".join(conf.ad_space)
-
+async def m001_create_admin_settings_table(db):
await db.execute(
"""
- CREATE TABLE IF NOT EXISTS admin.admin (
- "user" TEXT PRIMARY KEY,
- admin_users TEXT,
- allowed_users TEXT,
- admin_ext TEXT,
- disabled_ext TEXT,
- funding_source TEXT,
- data_folder TEXT,
- database_url TEXT,
- force_https BOOLEAN,
- reserve_fee_min INT,
- reserve_fee_pct REAL,
- service_fee REAL,
- hide_api BOOLEAN,
- denomination TEXT,
- site_title TEXT,
- site_tagline TEXT,
- site_description TEXT,
- default_wallet_name TEXT,
- theme TEXT,
- custom_logo TEXT,
- ad_space TEXT
- );
- """
- )
- await db.execute(
- """
- INSERT INTO admin.admin (
- "user",
- admin_users,
- allowed_users,
- admin_ext,
- disabled_ext,
- funding_source,
- data_folder,
- database_url,
- force_https,
- reserve_fee_min,
- reserve_fee_pct,
- service_fee,
- hide_api,
- denomination,
- site_title,
- site_tagline,
- site_description,
- default_wallet_name,
- theme,
- custom_logo,
- ad_space)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- """,
- (
- user,
- admin_users,
- allowed_users,
- admin_ext,
- disabled_ext,
- funding_source,
- data_folder,
- database_url,
- force_https,
- reserve_fee_min,
- reserve_fee_pct,
- service_fee,
- hide_api,
- denomination,
- site_title,
- site_tagline,
- site_description,
- default_wallet_name,
- theme,
- custom_logo,
- ad_space,
- ),
- )
-
- funding_wallet = getenv("LNBITS_BACKEND_WALLET_CLASS")
-
- # Make the funding table, if it does not already exist
- await db.execute(
- """
- CREATE TABLE IF NOT EXISTS admin.funding (
- id TEXT PRIMARY KEY,
- backend_wallet TEXT,
- endpoint TEXT,
+ CREATE TABLE IF NOT EXISTS admin.settings (
+ lnbits_admin_ui TEXT,
+ debug TEXT,
+ host TEXT,
port INT,
- read_key TEXT,
- invoice_key TEXT,
- admin_key TEXT,
- cert TEXT,
- balance INT,
- selected INT
+ lnbits_path TEXT,
+ lnbits_commit TEXT,
+ lnbits_admin_users TEXT,
+ lnbits_allowed_users TEXT,
+ lnbits_allowed_funding_sources TEXT,
+ lnbits_admin_extensions 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_data_folder TEXT,
+ lnbits_database_url TEXT,
+ 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,
+ fake_wallet_secret TEXT,
+ lnbits_endpoint TEXT,
+ lnbits_key TEXT,
+ cliche_endpoint TEXT,
+ corelightning_rpc TEXT,
+ eclair_url TEXT,
+ eclair_pass TEXT,
+ lnd_rest_endpoint TEXT,
+ lnd_rest_cert TEXT,
+ lnd_rest_macaroon 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
);
"""
)
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, selected)
- VALUES (?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "CLightningWallet",
- getenv("CLIGHTNING_RPC"),
- 1 if funding_wallet == "CLightningWallet" else 0,
- ),
- )
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
- VALUES (?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "SparkWallet",
- getenv("SPARK_URL"),
- getenv("SPARK_TOKEN"),
- 1 if funding_wallet == "SparkWallet" else 0,
- ),
- )
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
- VALUES (?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "LnbitsWallet",
- getenv("LNBITS_ENDPOINT"),
- getenv("LNBITS_KEY"),
- 1 if funding_wallet == "LnbitsWallet" else 0,
- ),
- )
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, port, admin_key, cert, selected)
- VALUES (?, ?, ?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "LndWallet",
- getenv("LND_GRPC_ENDPOINT"),
- getenv("LND_GRPC_PORT"),
- getenv("LND_GRPC_MACAROON"),
- getenv("LND_GRPC_CERT"),
- 1 if funding_wallet == "LndWallet" else 0,
- ),
- )
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, cert, selected)
- VALUES (?, ?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "LndRestWallet",
- getenv("LND_REST_ENDPOINT"),
- getenv("LND_REST_MACAROON"),
- getenv("LND_REST_CERT"),
- 1 if funding_wallet == "LndWallet" else 0,
- ),
- )
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, cert, selected)
- VALUES (?, ?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "LNPayWallet",
- getenv("LNPAY_API_ENDPOINT"),
- getenv("LNPAY_WALLET_KEY"),
- getenv("LNPAY_API_KEY"), # this is going in as the cert
- 1 if funding_wallet == "LNPayWallet" else 0,
- ),
- )
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
- VALUES (?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "LntxbotWallet",
- getenv("LNTXBOT_API_ENDPOINT"),
- getenv("LNTXBOT_KEY"),
- 1 if funding_wallet == "LntxbotWallet" else 0,
- ),
- )
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
- VALUES (?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "OpenNodeWallet",
- getenv("OPENNODE_API_ENDPOINT"),
- getenv("OPENNODE_KEY"),
- 1 if funding_wallet == "OpenNodeWallet" else 0,
- ),
- )
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
- VALUES (?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "SparkWallet",
- getenv("SPARK_URL"),
- getenv("SPARK_TOKEN"),
- 1 if funding_wallet == "SparkWallet" else 0,
- ),
- )
-
- ## PLACEHOLDER FOR ECLAIR WALLET
- # await db.execute(
- # """
- # INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
- # VALUES (?, ?, ?, ?, ?)
- # """,
- # (
- # urlsafe_short_hash(),
- # "EclairWallet",
- # getenv("ECLAIR_URL"),
- # getenv("ECLAIR_PASS"),
- # 1 if funding_wallet == "EclairWallet" else 0,
- # ),
- # )
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 6e95d68f..ef57cadd 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -29,36 +29,36 @@ class UpdateAdminSettings(BaseModel):
ad_space: str = Query(None)
-class Admin(BaseModel):
- # users
- user: str
- admin_users: Optional[str]
- allowed_users: Optional[str]
- admin_ext: Optional[str]
- disabled_ext: Optional[str]
- funding_source: Optional[str]
- # ops
- data_folder: Optional[str]
- database_url: Optional[str]
- force_https: bool = Field(default=True)
- reserve_fee_min: Optional[int]
- reserve_fee_pct: Optional[float]
- service_fee: float = Optional[float]
- hide_api: bool = Field(default=False)
- # Change theme
- site_title: Optional[str]
- site_tagline: Optional[str]
- site_description: Optional[str]
- default_wallet_name: Optional[str]
- denomination: str = Field(default="sats")
- theme: Optional[str]
- custom_logo: Optional[str]
- ad_space: Optional[str]
+# class Admin(BaseModel):
+# # users
+# user: str
+# admin_users: Optional[str]
+# allowed_users: Optional[str]
+# admin_ext: Optional[str]
+# disabled_ext: Optional[str]
+# funding_source: Optional[str]
+# # ops
+# data_folder: Optional[str]
+# database_url: Optional[str]
+# force_https: bool = Field(default=True)
+# reserve_fee_min: Optional[int]
+# reserve_fee_pct: Optional[float]
+# service_fee: float = Optional[float]
+# hide_api: bool = Field(default=False)
+# # Change theme
+# site_title: Optional[str]
+# site_tagline: Optional[str]
+# site_description: Optional[str]
+# default_wallet_name: Optional[str]
+# denomination: str = Field(default="sats")
+# theme: Optional[str]
+# custom_logo: Optional[str]
+# ad_space: Optional[str]
- @classmethod
- def from_row(cls, row: Row) -> "Admin":
- data = dict(row)
- return cls(**data)
+# @classmethod
+# def from_row(cls, row: Row) -> "Admin":
+# data = dict(row)
+# return cls(**data)
class Funding(BaseModel):
diff --git a/lnbits/extensions/admin/templates/admin/_tab_funding.html b/lnbits/extensions/admin/templates/admin/_tab_funding.html
new file mode 100644
index 00000000..2ed0aae2
--- /dev/null
+++ b/lnbits/extensions/admin/templates/admin/_tab_funding.html
@@ -0,0 +1,158 @@
+
+
+ Wallets Management
+
+
+
+
+
Funding Source Info
+
+ {%raw%}
+ -
+ Funding Source: {{data.settings.lnbits_backend_wallet_class}}
+
+ - Balance: {{data.balance / 1000}} sats
+ {%endraw%}
+
+
+
+
+
+
+
+
+
Active Funding (Requires server restart)
+
+
+
+
+
+
+
+
+
+
+
TopUp a wallet
+
+
+
+
+
+
+
+
Funding Sources
+ {% raw %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% endraw %}
+
+
+
diff --git a/lnbits/extensions/admin/templates/admin/_tab_server.html b/lnbits/extensions/admin/templates/admin/_tab_server.html
new file mode 100644
index 00000000..2924e6a4
--- /dev/null
+++ b/lnbits/extensions/admin/templates/admin/_tab_server.html
@@ -0,0 +1,78 @@
+
+
+ Server Management
+
+
+
+
+
Server Info
+
+ {%raw%}
+ -
+ SQlite: {{data.settings.lnbits_data_folder}}
+
+ -
+ Postgres: {{data.settings.lnbits_database_url}}
+
+ {%endraw%}
+
+
+
+
+
+
+
+
Miscelaneous
+
+
+ Force HTTPS
+ Prefer secure URLs
+
+
+
+
+
+
+
+ Hide API
+ Hides wallet api, extensions can choose to honor
+
+
+
+
+
+
+
+
+
+
+
+ Save
+
+
+
diff --git a/lnbits/extensions/admin/templates/admin/_tab_theme.html b/lnbits/extensions/admin/templates/admin/_tab_theme.html
new file mode 100644
index 00000000..41dc0447
--- /dev/null
+++ b/lnbits/extensions/admin/templates/admin/_tab_theme.html
@@ -0,0 +1,122 @@
+
+
+ UI Management
+
+
+
+
+
+
+
+
Default Wallet Name
+
+
+
+
+
+
+
+
+
Advertisement Slots
+
+
+
+
+ {% raw %}
+
+ {{ space.slice(0, 8) + " ... " + space.slice(-8) }}
+
+ {% endraw %}
+
+
+
+
+
+
+
+
+ Save
+
+
+
diff --git a/lnbits/extensions/admin/templates/admin/_tab_users.html b/lnbits/extensions/admin/templates/admin/_tab_users.html
new file mode 100644
index 00000000..3eb53ac4
--- /dev/null
+++ b/lnbits/extensions/admin/templates/admin/_tab_users.html
@@ -0,0 +1,96 @@
+
+
+ User Management
+
+
+ Super Admin: {% raw %}{{this.data.settings.lnbits_admin_users[0]}}{%
+ endraw %}
+
+
+
+
Admin Users
+
+
+
+
+ {% raw %}
+
+ {{ user }}
+
+ {% endraw %}
+
+
+
+
+
Allowed Users
+
+
+
+
+ {% raw %}
+
+ {{ user }}
+
+ {% endraw %}
+
+
+
+
+
+
+
Disabled Extensions
+
+
+
+
+
+ Save
+
+
+
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 319ca3f0..87e89321 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -29,1118 +29,16 @@
-
-
-
- Wallets Management
-
-
-
-
-
Funding Source Info
-
- {%raw%}
- - Funding Source: {{data.admin.funding_source}}
- - Balance: {{data.admin.balance / 1000}} sats
- {%endraw%}
-
-
-
-
-
-
-
-
-
- Active Funding
- (Requires server restart)
-
-
-
-
-
-
-
-
-
-
-
-
-
TopUp a wallet
-
-
-
-
-
-
-
-
-
Funding Sources
- {% raw %}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% endraw %}
-
-
-
-
-
-
- User Management
-
-
- Super Admin: {% raw %}{{this.data.admin.user}}{% endraw %}
-
-
-
-
Admin Users
-
-
-
-
- {% raw %}
-
- {{ user }}
-
- {% endraw %}
-
-
-
-
-
Allowed Users
-
-
-
-
- {% raw %}
-
- {{ user }}
-
- {% endraw %}
-
-
-
-
-
-
-
Disabled Extensions
-
-
-
-
-
- Save
-
-
-
-
-
- Server Management
-
-
-
-
-
Server Info
-
- {%raw%}
- -
- SQlite: {{data.admin.data_folder}}
-
- -
- Postgres: {{data.admin.database_url}}
-
- {%endraw%}
-
-
-
-
-
-
-
-
Miscelaneous
-
-
- Force HTTPS
- Prefer secure URLs
-
-
-
-
-
-
-
- Hide API
- Hides wallet api, extensions can choose to
- honor
-
-
-
-
-
-
-
-
-
-
-
- Save
-
-
-
-
-
- UI Management
-
-
-
-
-
-
-
-
Default Wallet Name
-
-
-
-
-
-
-
-
-
Advertisement Slots
-
-
-
-
- {% raw %}
-
- {{ space.slice(0, 8) + " ... " + space.slice(-8) }}
-
- {% endraw %}
-
-
-
-
-
-
-
-
- Save
-
-
-
+ {% include "admin/_tab_funding.html" %} {% include
+ "admin/_tab_users.html" %} {% include "admin/_tab_server.html" %} {%
+ include "admin/_tab_theme.html" %}
-
-
-
-
-
{% endblock %} {% block scripts %} {{ window_vars(user) }}
{% endblock %}
From 3778990000848fc74c23e4fdab3696f73edda4b1 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Fri, 7 Oct 2022 19:24:07 +0100
Subject: [PATCH 106/691] make saving possible (possible will change in future)
---
.../admin/templates/admin/index.html | 36 ++++++++++++-------
1 file changed, 24 insertions(+), 12 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 72352651..18df16a9 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -121,8 +121,11 @@
created: function () {
this.settings = JSON.parse('{{ settings|tojson|safe }}') //DB data
this.balance = +'{{ balance|safe }}'
- this.formData = this.settings //model
+ this.formData = _.clone(this.settings) //model
+ //this.formData.lnbits_ad_space = "hdh"
console.log(this.formData)
+ console.log(_.isEqual(this.settings, this.formData))
+
},
methods: {
addAdminUser() {
@@ -206,18 +209,27 @@
},
updateSettings() {
let data = {
- ...this.settings,
- ...this.formData
+ lnbits_backend_wallet_class: this.formData.lnbits_backend_wallet_class,
+ lnbits_admin_users: this.formData.lnbits_admin_users.toString(),
+ lnbits_allowed_users: this.formData.lnbits_allowed_users.toString(),
+ lnbits_admin_ext: this.formData.lnbits_admin_ext,
+ lnbits_disabled_ext: this.formData.lnbits_disabled_ext,
+ lnbits_funding_source: this.formData.lnbits_funding_source,
+ lnbits_force_https: this.formData.lnbits_force_https,
+ lnbits_reserve_fee_min: this.formData.lnbits_reserve_fee_min,
+ lnbits_reserve_fee_percent: this.formData.lnbits_reserve_fee_percent,
+ lnbits_service_fee: this.formData.lnbits_service_fee,
+ lnbits_hide_api: this.formData.lnbits_hide_api,
+ lnbits_site_title: this.formData.lnbits_site_title,
+ lnbits_site_tagline: this.formData.lnbits_site_tagline,
+ lnbits_site_description: this.formData.lnbits_site_description,
+ lnbits_default_wallet_name: this.formData.lnbits_default_wallet_name,
+ lnbits_denomination: this.formData.lnbits_denomination,
+ lnbits_theme: this.formData.lnbits_theme,
+ lnbits_custom_logo: this.formData.lnbits_custom_logo,
+ lnbits_ad_space: this.formData.lnbits_ad_space.toString()
}
- /*
- 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`)
- }*/
+ console.log(data)
LNbits.api
.request(
'PUT',
From 3fdafca0a15bb9931fbfe3a61b7a228c91b2d855 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Fri, 7 Oct 2022 19:44:03 +0100
Subject: [PATCH 107/691] some more refining
---
lnbits/extensions/admin/models.py | 10 +++++-----
.../extensions/admin/templates/admin/_tab_users.html | 2 ++
lnbits/extensions/admin/templates/admin/index.html | 12 +++++++++---
3 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 13a6cd23..45cd990d 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -4,10 +4,10 @@ from pydantic import BaseModel
class UpdateSettings(BaseModel):
lnbits_backend_wallet_class: str = Query(None)
- lnbits_admin_users: str = Query(None)
- lnbits_allowed_users: str = Query(None)
- lnbits_admin_ext: str = Query(None)
- lnbits_disabled_ext: str = Query(None)
+ lnbits_admin_users: str = Query(None) #this should be List[str] ??
+ lnbits_allowed_users: str = Query(None) #this should be List[str] ??
+ lnbits_admin_ext: str = Query(None) #this should be List[str] ??
+ lnbits_disabled_ext: str = Query(None) #this should be List[str] ??
lnbits_funding_source: str = Query(None)
lnbits_force_https: bool = Query(None)
lnbits_reserve_fee_min: int = Query(None, ge=0)
@@ -21,4 +21,4 @@ class UpdateSettings(BaseModel):
lnbits_denomination: str = Query(None)
lnbits_theme: str = Query(None)
lnbits_custom_logo: str = Query(None)
- lnbits_ad_space: str = Query(None)
+ lnbits_ad_space: str = Query(None) #this should be List[str] ??
diff --git a/lnbits/extensions/admin/templates/admin/_tab_users.html b/lnbits/extensions/admin/templates/admin/_tab_users.html
index c396ba7d..08b08a62 100644
--- a/lnbits/extensions/admin/templates/admin/_tab_users.html
+++ b/lnbits/extensions/admin/templates/admin/_tab_users.html
@@ -71,6 +71,7 @@
multiple
hint="Extensions only user with admin privileges can use"
label="Admin extensions"
+ :options="g.extensions.map(e => e.name)"
>
@@ -79,6 +80,7 @@
-
+
Date: Mon, 10 Oct 2022 12:17:35 +0100
Subject: [PATCH 108/691] get saved data and alert when data changed
---
.../admin/templates/admin/index.html | 18 +++++++-----------
lnbits/extensions/admin/views_api.py | 5 +++--
2 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 4754656d..4e401cb4 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -3,7 +3,7 @@
-
+
{
+ this.settings = response.data.settings
+ this.formData = _.clone(this.settings)
this.$q.notify({
type: 'positive',
message: 'Success! Settings changed!',
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index c8120564..c2079e37 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -43,8 +43,9 @@ async def api_update_settings(
user: User = Depends(check_admin),
data: UpdateSettings = Body(...),
):
- await update_settings(data)
- return {"status": "Success"}
+ settings = await update_settings(data)
+ logger.debug(settings)
+ return {"status": "Success", "settings": settings.dict()}
@admin_ext.delete("/api/v1/settings/", status_code=HTTPStatus.OK)
From a3b05e26b718db4969884e642416b2eac119f506 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Mon, 10 Oct 2022 12:23:19 +0100
Subject: [PATCH 109/691] cleanup and typing fix for data
---
lnbits/extensions/admin/models.py | 12 +++++-----
.../admin/templates/admin/index.html | 22 ++-----------------
lnbits/extensions/admin/views_api.py | 1 -
3 files changed, 9 insertions(+), 26 deletions(-)
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 45cd990d..94fa56bb 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -1,13 +1,15 @@
+from typing import List
+
from fastapi import Query
from pydantic import BaseModel
class UpdateSettings(BaseModel):
lnbits_backend_wallet_class: str = Query(None)
- lnbits_admin_users: str = Query(None) #this should be List[str] ??
- lnbits_allowed_users: str = Query(None) #this should be List[str] ??
- lnbits_admin_ext: str = Query(None) #this should be List[str] ??
- lnbits_disabled_ext: str = Query(None) #this should be List[str] ??
+ lnbits_admin_users: List[str] = Query(None)
+ lnbits_allowed_users: List[str] = Query(None)
+ lnbits_admin_ext: List[str] = Query(None)
+ lnbits_disabled_ext: List[str] = Query(None)
lnbits_funding_source: str = Query(None)
lnbits_force_https: bool = Query(None)
lnbits_reserve_fee_min: int = Query(None, ge=0)
@@ -21,4 +23,4 @@ class UpdateSettings(BaseModel):
lnbits_denomination: str = Query(None)
lnbits_theme: str = Query(None)
lnbits_custom_logo: str = Query(None)
- lnbits_ad_space: str = Query(None) #this should be List[str] ??
+ lnbits_ad_space: List[str] = Query(None)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 4e401cb4..d8111595 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -209,26 +209,8 @@
})
},
updateSettings() {
- let data = {
- lnbits_backend_wallet_class: this.formData.lnbits_backend_wallet_class,
- lnbits_admin_users: this.formData.lnbits_admin_users.toString(),
- lnbits_allowed_users: this.formData.lnbits_allowed_users.toString(),
- lnbits_admin_ext: this.formData.lnbits_admin_ext,
- lnbits_disabled_ext: this.formData.lnbits_disabled_ext,
- lnbits_funding_source: this.formData.lnbits_funding_source,
- lnbits_force_https: this.formData.lnbits_force_https,
- lnbits_reserve_fee_min: this.formData.lnbits_reserve_fee_min,
- lnbits_reserve_fee_percent: this.formData.lnbits_reserve_fee_percent,
- lnbits_service_fee: this.formData.lnbits_service_fee,
- lnbits_hide_api: this.formData.lnbits_hide_api,
- lnbits_site_title: this.formData.lnbits_site_title,
- lnbits_site_tagline: this.formData.lnbits_site_tagline,
- lnbits_site_description: this.formData.lnbits_site_description,
- lnbits_default_wallet_name: this.formData.lnbits_default_wallet_name,
- lnbits_denomination: this.formData.lnbits_denomination,
- lnbits_theme: this.formData.lnbits_theme,
- lnbits_custom_logo: this.formData.lnbits_custom_logo,
- lnbits_ad_space: this.formData.lnbits_ad_space.toString()
+ let data = {
+ ...this.formData
}
LNbits.api
.request(
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index c2079e37..19b52e35 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -44,7 +44,6 @@ async def api_update_settings(
data: UpdateSettings = Body(...),
):
settings = await update_settings(data)
- logger.debug(settings)
return {"status": "Success", "settings": settings.dict()}
From 91a5f7d2143ac4e2eb4f58607a062c1386bea6e9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Mon, 10 Oct 2022 23:27:46 +0200
Subject: [PATCH 110/691] add callback for saas app
---
lnbits/app.py | 2 +-
lnbits/extensions/admin/migrations.py | 3 +++
lnbits/extensions/admin/models.py | 10 ++++-----
lnbits/extensions/admin/views_api.py | 5 -----
lnbits/settings.py | 32 +++++++++++++++++++++++----
5 files changed, 37 insertions(+), 15 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index a8371950..6fa5cf5d 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -64,7 +64,7 @@ def create_app() -> FastAPI:
# TODO: why those 2?
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)
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index c4bc98d8..ea698c27 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -6,6 +6,9 @@ async def m001_create_admin_settings_table(db):
debug TEXT,
host TEXT,
port INTEGER,
+ lnbits_saas_instance_id TEXT,
+ lnbits_saas_callback TEXT,
+ lnbits_saas_secret TEXT,
lnbits_path TEXT,
lnbits_commit TEXT,
lnbits_admin_users TEXT,
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 94fa56bb..ada84e9d 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -6,10 +6,10 @@ from pydantic import BaseModel
class UpdateSettings(BaseModel):
lnbits_backend_wallet_class: str = Query(None)
- lnbits_admin_users: List[str] = Query(None)
- lnbits_allowed_users: List[str] = Query(None)
- lnbits_admin_ext: List[str] = Query(None)
- lnbits_disabled_ext: List[str] = Query(None)
+ lnbits_admin_users: List[str] = Query(None)
+ lnbits_allowed_users: List[str] = Query(None)
+ lnbits_admin_ext: List[str] = Query(None)
+ lnbits_disabled_ext: List[str] = Query(None)
lnbits_funding_source: str = Query(None)
lnbits_force_https: bool = Query(None)
lnbits_reserve_fee_min: int = Query(None, ge=0)
@@ -23,4 +23,4 @@ class UpdateSettings(BaseModel):
lnbits_denomination: str = Query(None)
lnbits_theme: str = Query(None)
lnbits_custom_logo: str = Query(None)
- lnbits_ad_space: List[str] = Query(None)
+ lnbits_ad_space: List[str] = Query(None)
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index 19b52e35..ae2959bc 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -53,8 +53,3 @@ async def api_delete_settings(
):
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"}
diff --git a/lnbits/settings.py b/lnbits/settings.py
index ffcdcc0a..f183211c 100644
--- a/lnbits/settings.py
+++ b/lnbits/settings.py
@@ -1,6 +1,7 @@
import importlib
import json
import subprocess
+import httpx
from os import path
from sqlite3 import Row
from typing import List, Optional
@@ -9,6 +10,7 @@ from loguru import logger
from pydantic import BaseSettings, Field, validator
+
def list_parse_fallback(v):
try:
return json.loads(v)
@@ -34,6 +36,11 @@ class Settings(BaseSettings):
lnbits_path: str = Field(default=".")
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
lnbits_admin_users: List[str] = Field(default=[])
lnbits_allowed_users: List[str] = Field(default=[])
@@ -230,11 +237,28 @@ async def check_admin_settings():
http = "https" if settings.lnbits_force_https else "http"
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:
+ r = client.post(settings.lnbits_saas_callback, headers=headers, json=payload)
+ logger.warning("sent admin user to saas application")
+ except:
+ logger.error(f"error sending admin user to saas: {settings.lnbits_saas_callback}")
+
except:
- logger.warning("admin.settings tables does not exist.")
+ logger.error("admin.settings tables does not exist.")
raise
From c9ead25d50cc1c8cd019e51d7147c4febb71b635 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Wed, 12 Oct 2022 13:08:59 +0200
Subject: [PATCH 111/691] bugfixes and fix topup wallet
---
lnbits/app.py | 1 +
.../admin/templates/admin/_tab_funding.html | 4 +--
.../admin/templates/admin/index.html | 28 +++++++++------
lnbits/extensions/admin/views_api.py | 36 ++++++++++---------
lnbits/server.py | 1 +
lnbits/settings.py | 29 ++++++++++-----
lnbits/wallets/fake.py | 2 +-
7 files changed, 60 insertions(+), 41 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 6fa5cf5d..49ad8d77 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -84,6 +84,7 @@ async def check_funding_source() -> None:
def signal_handler(signal, frame):
logger.debug(f"SIGINT received, terminating LNbits.")
sys.exit(1)
+
signal.signal(signal.SIGINT, signal_handler)
WALLET = get_wallet_class()
diff --git a/lnbits/extensions/admin/templates/admin/_tab_funding.html b/lnbits/extensions/admin/templates/admin/_tab_funding.html
index 8b5456f1..34162a9f 100644
--- a/lnbits/extensions/admin/templates/admin/_tab_funding.html
+++ b/lnbits/extensions/admin/templates/admin/_tab_funding.html
@@ -8,9 +8,7 @@
Funding Source Info
{%raw%}
- -
- Funding Source: {{settings.lnbits_backend_wallet_class}}
-
+ - Funding Source: {{settings.lnbits_backend_wallet_class}}
- Balance: {{balance / 1000}} sats
{%endraw%}
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index d8111595..d3e93a71 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -3,7 +3,13 @@
-
+
u !== user
- )
+ this.settings.lnbits_admin_users = admin_users.filter(u => u !== user)
},
addAllowedUser() {
let addUser = this.formData.allowed_users_add
@@ -155,7 +159,9 @@
},
removeAllowedUser(user) {
let allowed_users = this.settings.lnbits_allowed_users
- this.settings.lnbits_allowed_users = allowed_users.filter(u => u !== user)
+ this.settings.lnbits_allowed_users = allowed_users.filter(
+ u => u !== user
+ )
},
addAdSpace() {
let adSpace = this.formData.ad_space_add
@@ -187,10 +193,10 @@
topupWallet() {
LNbits.api
.request(
- 'POST',
+ 'PUT',
'/admin/api/v1/topup/?usr=' + this.g.user.id,
- this.wallet.id,
- this.wallet.amount
+ this.g.user.wallets[0].adminkey,
+ this.wallet
)
.then(response => {
this.$q.notify({
@@ -209,7 +215,7 @@
})
},
updateSettings() {
- let data = {
+ let data = {
...this.formData
}
LNbits.api
@@ -262,7 +268,7 @@
LNbits.utils.notifyApiError(error)
})
}
- },
+ }
})
{% endblock %}
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index ae2959bc..63ed5b3c 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -1,7 +1,6 @@
from http import HTTPStatus
-from fastapi import Body, Depends, Request
-from loguru import logger
+from fastapi import Body, Depends, Query
from starlette.exceptions import HTTPException
from lnbits.core.crud import get_wallet
@@ -9,47 +8,50 @@ from lnbits.core.models import User
from lnbits.decorators import check_admin
from lnbits.extensions.admin import admin_ext
from lnbits.extensions.admin.models import UpdateSettings
-from lnbits.requestvars import g
from lnbits.server import server_restart
-from lnbits.settings import settings
from .crud import delete_settings, update_settings, update_wallet_balance
-@admin_ext.get("/api/v1/restart/", status_code=HTTPStatus.OK)
-async def api_restart_server(user: User = Depends(check_admin)):
+@admin_ext.get(
+ "/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.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(
- wallet_id, topup_amount: int, user: User = Depends(check_admin)
-):
+ id: str = Body(...), amount: int = Body(...)
+) -> dict[str, str]:
try:
- wallet = await get_wallet(wallet_id)
+ await get_wallet(id)
except:
raise HTTPException(
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"}
-@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(
- user: User = Depends(check_admin),
data: UpdateSettings = Body(...),
):
settings = await update_settings(data)
return {"status": "Success", "settings": settings.dict()}
-@admin_ext.delete("/api/v1/settings/", status_code=HTTPStatus.OK)
-async def api_delete_settings(
- user: User = Depends(check_admin),
-):
+@admin_ext.delete(
+ "/api/v1/settings/", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
+)
+async def api_delete_settings() -> dict[str, str]:
await delete_settings()
return {"status": "Success"}
diff --git a/lnbits/server.py b/lnbits/server.py
index 79af8112..6d4cd2e7 100644
--- a/lnbits/server.py
+++ b/lnbits/server.py
@@ -52,6 +52,7 @@ def main(ctx, port: int, host: str, ssl_keyfile: str, ssl_certfile: str, reload:
port=port,
host=host,
reload=reload,
+ forwarded_allow_ips="*",
ssl_keyfile=ssl_keyfile,
ssl_certfile=ssl_certfile,
**d
diff --git a/lnbits/settings.py b/lnbits/settings.py
index f183211c..61dbd6f2 100644
--- a/lnbits/settings.py
+++ b/lnbits/settings.py
@@ -1,20 +1,19 @@
import importlib
import json
import subprocess
-import httpx
from os import path
from sqlite3 import Row
from typing import List, Optional
+import httpx
from loguru import logger
from pydantic import BaseSettings, Field, validator
-
def list_parse_fallback(v):
try:
return json.loads(v)
- except Exception as e:
+ except Exception:
replaced = v.replace(" ", "")
if replaced:
return replaced.split(",")
@@ -238,24 +237,36 @@ async def check_admin_settings():
http = "https" if settings.lnbits_force_https else "http"
user = settings.lnbits_admin_users[0]
- admin_url = f"{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:
+ 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
+ "X-API-KEY": settings.lnbits_saas_secret,
}
payload = {
"instance_id": settings.lnbits_saas_instance_id,
- "adminuser": user
+ "adminuser": user,
}
try:
- r = client.post(settings.lnbits_saas_callback, headers=headers, json=payload)
+ client.post(
+ settings.lnbits_saas_callback,
+ headers=headers,
+ json=payload,
+ )
logger.warning("sent admin user to saas application")
except:
- logger.error(f"error sending admin user to saas: {settings.lnbits_saas_callback}")
+ logger.error(
+ f"error sending admin user to saas: {settings.lnbits_saas_callback}"
+ )
except:
logger.error("admin.settings tables does not exist.")
diff --git a/lnbits/wallets/fake.py b/lnbits/wallets/fake.py
index 73458e8c..94ff5f48 100644
--- a/lnbits/wallets/fake.py
+++ b/lnbits/wallets/fake.py
@@ -19,7 +19,6 @@ from .base import (
class FakeWallet(Wallet):
- queue: asyncio.Queue = asyncio.Queue(0)
secret: str = settings.fake_wallet_secret
privkey: str = hashlib.pbkdf2_hmac(
"sha256",
@@ -98,6 +97,7 @@ class FakeWallet(Wallet):
return PaymentStatus(None)
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
+ self.queue: asyncio.Queue = asyncio.Queue(0)
while True:
value: Invoice = await self.queue.get()
yield value.payment_hash
From 9a48b174c62bd1908be3a8698c36b34aa78a3188 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Wed, 12 Oct 2022 19:04:46 +0100
Subject: [PATCH 112/691] add funding sources options
---
lnbits/app.py | 1 +
lnbits/extensions/admin/models.py | 41 +++-
.../admin/templates/admin/_tab_funding.html | 25 +-
.../admin/templates/admin/index.html | 217 +++++++++++++++++-
4 files changed, 259 insertions(+), 25 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index a8371950..50f218b7 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -84,6 +84,7 @@ async def check_funding_source() -> None:
def signal_handler(signal, frame):
logger.debug(f"SIGINT received, terminating LNbits.")
sys.exit(1)
+
signal.signal(signal.SIGINT, signal_handler)
WALLET = get_wallet_class()
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 94fa56bb..d9d2b22f 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -6,10 +6,10 @@ from pydantic import BaseModel
class UpdateSettings(BaseModel):
lnbits_backend_wallet_class: str = Query(None)
- lnbits_admin_users: List[str] = Query(None)
- lnbits_allowed_users: List[str] = Query(None)
- lnbits_admin_ext: List[str] = Query(None)
- lnbits_disabled_ext: List[str] = Query(None)
+ lnbits_admin_users: List[str] = Query(None)
+ lnbits_allowed_users: List[str] = Query(None)
+ lnbits_admin_ext: List[str] = Query(None)
+ lnbits_disabled_ext: List[str] = Query(None)
lnbits_funding_source: str = Query(None)
lnbits_force_https: bool = Query(None)
lnbits_reserve_fee_min: int = Query(None, ge=0)
@@ -23,4 +23,35 @@ class UpdateSettings(BaseModel):
lnbits_denomination: str = Query(None)
lnbits_theme: str = Query(None)
lnbits_custom_logo: str = Query(None)
- lnbits_ad_space: List[str] = Query(None)
+ lnbits_ad_space: List[str] = 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_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)
diff --git a/lnbits/extensions/admin/templates/admin/_tab_funding.html b/lnbits/extensions/admin/templates/admin/_tab_funding.html
index 8b5456f1..a523d4e5 100644
--- a/lnbits/extensions/admin/templates/admin/_tab_funding.html
+++ b/lnbits/extensions/admin/templates/admin/_tab_funding.html
@@ -8,9 +8,7 @@
Funding Source Info
{%raw%}
- -
- Funding Source: {{settings.lnbits_backend_wallet_class}}
-
+ - Funding Source: {{settings.lnbits_backend_wallet_class}}
- Balance: {{balance / 1000}} sats
{%endraw%}
@@ -60,21 +58,30 @@
- Funding Sources
+ Funding Sources (Requires server restart)
-
+
-
-
+
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index d8111595..ccaddda4 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -3,7 +3,13 @@
-
+
u !== user
- )
+ this.settings.lnbits_admin_users = admin_users.filter(u => u !== user)
},
addAllowedUser() {
let addUser = this.formData.allowed_users_add
@@ -155,7 +335,9 @@
},
removeAllowedUser(user) {
let allowed_users = this.settings.lnbits_allowed_users
- this.settings.lnbits_allowed_users = allowed_users.filter(u => u !== user)
+ this.settings.lnbits_allowed_users = allowed_users.filter(
+ u => u !== user
+ )
},
addAdSpace() {
let adSpace = this.formData.ad_space_add
@@ -208,8 +390,19 @@
LNbits.utils.notifyApiError(error)
})
},
+ updateFundingData(){
+ this.settings.lnbits_allowed_funding_sources.map(f => {
+ let opts = this.funding_sources.get(f)
+ if (!opts) return
+
+ Object.keys(opts).forEach(e => {
+ opts[e].value = this.settings[e]
+ })
+ })
+ console.log("funding", this.funding_sources)
+ },
updateSettings() {
- let data = {
+ let data = {
...this.formData
}
LNbits.api
@@ -222,11 +415,13 @@
.then(response => {
this.settings = response.data.settings
this.formData = _.clone(this.settings)
+ this.updateFundingData()
this.$q.notify({
type: 'positive',
message: 'Success! Settings changed!',
icon: null
})
+ console.log(this.settings)
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
@@ -262,7 +457,7 @@
LNbits.utils.notifyApiError(error)
})
}
- },
+ }
})
{% endblock %}
From dde28e66a24e09517b668e291ed58a6eb7df37e2 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Thu, 13 Oct 2022 15:52:02 +0100
Subject: [PATCH 113/691] added tooltips, moved reset, and warnings
---
.../admin/templates/admin/index.html | 97 ++++++++++++-------
1 file changed, 61 insertions(+), 36 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 575b377f..7d268301 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -1,8 +1,14 @@
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
%} {% block page %}
-
-
+
+
+ Save your changes
-
-
-
+
+
+ Restart the server for changes to take effect
+
+
+
+
+ Add funds to a wallet.
+
+ > -->
+
+ Delete all settings and reset to defaults.
+
@@ -121,6 +136,7 @@
show: false
},
tab: 'funding',
+ needsRestart: false,
funding_sources: new Map([
['VoidWallet', null],
[
@@ -302,13 +318,12 @@
this.balance = +'{{ balance|safe }}'
this.formData = _.clone(this.settings) //model
this.updateFundingData()
-
console.log(this.settings)
},
computed: {
checkChanges() {
return !_.isEqual(this.settings, this.formData)
- },
+ }
},
methods: {
addAdminUser() {
@@ -361,6 +376,7 @@
message: 'Success! Restarted Server',
icon: null
})
+ this.needsRestart = false
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
@@ -390,16 +406,15 @@
LNbits.utils.notifyApiError(error)
})
},
- updateFundingData(){
+ updateFundingData() {
this.settings.lnbits_allowed_funding_sources.map(f => {
let opts = this.funding_sources.get(f)
if (!opts) return
-
+
Object.keys(opts).forEach(e => {
opts[e].value = this.settings[e]
})
})
- console.log("funding", this.funding_sources)
},
updateSettings() {
let data = {
@@ -415,31 +430,41 @@
.then(response => {
this.settings = response.data.settings
this.formData = _.clone(this.settings)
+ this.needsRestart = true
this.updateFundingData()
this.$q.notify({
type: 'positive',
message: 'Success! Settings changed!',
icon: null
})
- console.log(this.settings)
})
.catch(function (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)
+ LNbits.utils
+ .confirmDialog(
+ 'Are you sure you want to restore settings to default?'
+ )
+ .onOk(() => {
+ 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
+ })
+ this.needsRestart = true
+ })
+ .catch(function (error) {
+ LNbits.utils.notifyApiError(error)
+ })
})
},
downloadBackup() {
From fb2dee73955aef2700bdf52decb6a570440beb23 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Thu, 13 Oct 2022 15:52:26 +0100
Subject: [PATCH 114/691] moved to columns
---
.../admin/templates/admin/_tab_funding.html | 54 +++++++++----------
1 file changed, 27 insertions(+), 27 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/_tab_funding.html b/lnbits/extensions/admin/templates/admin/_tab_funding.html
index a523d4e5..a69ecb47 100644
--- a/lnbits/extensions/admin/templates/admin/_tab_funding.html
+++ b/lnbits/extensions/admin/templates/admin/_tab_funding.html
@@ -27,38 +27,38 @@
:options="settings.lnbits_allowed_funding_sources"
>
-
+
-
-
-
- Funding Sources (Requires server restart)
+
+ Funding Sources (Requires server restart)
+
Date: Thu, 13 Oct 2022 15:52:39 +0100
Subject: [PATCH 115/691] themes not displaying fixed
---
lnbits/extensions/admin/templates/admin/_tab_theme.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lnbits/extensions/admin/templates/admin/_tab_theme.html b/lnbits/extensions/admin/templates/admin/_tab_theme.html
index 46bf83e9..c327733f 100644
--- a/lnbits/extensions/admin/templates/admin/_tab_theme.html
+++ b/lnbits/extensions/admin/templates/admin/_tab_theme.html
@@ -63,7 +63,7 @@
Themes
Date: Fri, 21 Oct 2022 10:00:47 +0200
Subject: [PATCH 116/691] add loop to uvicorn
---
lnbits/server.py | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/lnbits/server.py b/lnbits/server.py
index 6d4cd2e7..eb7c12b1 100644
--- a/lnbits/server.py
+++ b/lnbits/server.py
@@ -1,12 +1,7 @@
-import asyncio
-
import uvloop
-
uvloop.install()
-import contextlib
import multiprocessing as mp
-import sys
import time
import click
@@ -49,6 +44,7 @@ def main(ctx, port: int, host: str, ssl_keyfile: str, ssl_certfile: str, reload:
while True:
config = uvicorn.Config(
"lnbits.__main__:app",
+ loop="uvloop",
port=port,
host=host,
reload=reload,
@@ -65,9 +61,10 @@ def main(ctx, port: int, host: str, ssl_keyfile: str, ssl_certfile: str, reload:
server_restart.clear()
server.should_exit = True
server.force_exit = True
+ time.sleep(3)
process.terminate()
process.join()
- time.sleep(3)
+ time.sleep(1)
server_restart = mp.Event()
From 1b675f295bd2ec1a69ae972cce9b70f0371eefdc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Fri, 21 Oct 2022 11:13:40 +0200
Subject: [PATCH 117/691] add get settings endpoint with only values you can
also save
---
lnbits/app.py | 6 +----
lnbits/extensions/admin/crud.py | 12 +++++++++-
lnbits/extensions/admin/models.py | 6 ++++-
.../admin/templates/admin/index.html | 22 +++++++++++++++----
lnbits/extensions/admin/views_api.py | 7 +++++-
lnbits/server.py | 1 +
6 files changed, 42 insertions(+), 12 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 49ad8d77..959a8168 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -62,10 +62,6 @@ def create_app() -> FastAPI:
CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]
)
- # TODO: why those 2?
- g().config = settings
- g().base_url = f"http://{settings.host}:{settings.port}"
-
app.add_middleware(GZipMiddleware, minimum_size=1000)
register_startup(app)
@@ -174,7 +170,7 @@ def register_assets(app: FastAPI):
@app.on_event("startup")
async def vendored_assets_variable():
- if g().config.debug:
+ if settings.debug:
g().VENDORED_JS = map(url_for_vendored, get_js_vendored())
g().VENDORED_CSS = map(url_for_vendored, get_css_vendored())
else:
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index cc937b5e..2ce91612 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -6,7 +6,7 @@ from lnbits.settings import Settings, read_only_variables
from lnbits.tasks import internal_invoice_queue
from . import db
-from .models import UpdateSettings
+from .models import AdminSettings, UpdateSettings
async def update_wallet_balance(wallet_id: str, amount: int) -> str:
@@ -26,6 +26,16 @@ async def update_wallet_balance(wallet_id: str, amount: int) -> str:
await internal_invoice_queue.put(internal_id)
+async def get_settings() -> AdminSettings:
+ row = await db.fetchone("SELECT * FROM admin.settings")
+ all_settings = Settings(**row)
+ settings = AdminSettings()
+ for key, value in row.items():
+ if hasattr(settings, key):
+ setattr(settings, key, getattr(all_settings, key))
+ return settings
+
+
async def update_settings(data: UpdateSettings) -> Settings:
fields = []
for key, value in data.dict(exclude_none=True).items():
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index d9d2b22f..31811659 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -1,4 +1,4 @@
-from typing import List
+from typing import List, Optional
from fastapi import Query
from pydantic import BaseModel
@@ -55,3 +55,7 @@ class UpdateSettings(BaseModel):
opennode_key: str = Query(None)
spark_url: str = Query(None)
spark_token: str = Query(None)
+
+
+class AdminSettings(UpdateSettings):
+ lnbits_allowed_funding_sources: Optional[List[str]]
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 7d268301..10391261 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -314,11 +314,8 @@
}
},
created: function () {
- this.settings = JSON.parse('{{ settings|tojson|safe }}') //DB data
+ this.getSettings()
this.balance = +'{{ balance|safe }}'
- this.formData = _.clone(this.settings) //model
- this.updateFundingData()
- console.log(this.settings)
},
computed: {
checkChanges() {
@@ -416,6 +413,23 @@
})
})
},
+ getSettings() {
+ LNbits.api
+ .request(
+ 'GET',
+ '/admin/api/v1/settings/?usr=' + this.g.user.id,
+ this.g.user.wallets[0].adminkey
+ )
+ .then(response => {
+ this.settings = response.data
+ this.formData = _.clone(this.settings)
+ this.updateFundingData()
+ console.log(this.settings)
+ })
+ .catch(function (error) {
+ LNbits.utils.notifyApiError(error)
+ })
+ },
updateSettings() {
let data = {
...this.formData
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index 63ed5b3c..57d62ed4 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -10,7 +10,7 @@ from lnbits.extensions.admin import admin_ext
from lnbits.extensions.admin.models import UpdateSettings
from lnbits.server import server_restart
-from .crud import delete_settings, update_settings, update_wallet_balance
+from .crud import delete_settings, get_settings, update_settings, update_wallet_balance
@admin_ext.get(
@@ -21,6 +21,11 @@ async def api_restart_server() -> dict[str, str]:
return {"status": "Success"}
+@admin_ext.get("/api/v1/settings/", dependencies=[Depends(check_admin)])
+async def api_get_settings() -> UpdateSettings:
+ return await get_settings()
+
+
@admin_ext.put(
"/api/v1/topup/", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
)
diff --git a/lnbits/server.py b/lnbits/server.py
index eb7c12b1..ecf7ff62 100644
--- a/lnbits/server.py
+++ b/lnbits/server.py
@@ -1,4 +1,5 @@
import uvloop
+
uvloop.install()
import multiprocessing as mp
From 49c58cc8d0cb48fd874ba40d28c4331a065424df Mon Sep 17 00:00:00 2001
From: Gene Takavic <80261724+iWarpBTC@users.noreply.github.com>
Date: Mon, 24 Oct 2022 11:48:34 +0200
Subject: [PATCH 118/691] return a reason of failed payment to the pos; disable
a change of wallet in the form
---
lnbits/extensions/boltcards/lnurl.py | 4 ++--
lnbits/extensions/boltcards/templates/boltcards/index.html | 1 +
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/lnbits/extensions/boltcards/lnurl.py b/lnbits/extensions/boltcards/lnurl.py
index 064bde2c..cd4c6ba4 100644
--- a/lnbits/extensions/boltcards/lnurl.py
+++ b/lnbits/extensions/boltcards/lnurl.py
@@ -136,8 +136,8 @@ async def lnurl_callback(
)
return {"status": "OK"}
- except:
- return {"status": "ERROR", "reason": f"Payment failed"}
+ except Exception as exc:
+ return {"status": "ERROR", "reason": f"Payment failed - {exc}"}
# /boltcards/api/v1/auth?a=00000000000000000000000000000000
diff --git a/lnbits/extensions/boltcards/templates/boltcards/index.html b/lnbits/extensions/boltcards/templates/boltcards/index.html
index f795e454..7b9713e2 100644
--- a/lnbits/extensions/boltcards/templates/boltcards/index.html
+++ b/lnbits/extensions/boltcards/templates/boltcards/index.html
@@ -215,6 +215,7 @@
emit-value
v-model="cardDialog.data.wallet"
:options="g.user.walletOptions"
+ :disable="cardDialog.data.id != null"
label="Wallet *"
>
From 708f855c1d485639dfa559c2f2a26a5a9f41c1d7 Mon Sep 17 00:00:00 2001
From: benarc
Date: Mon, 7 Mar 2022 05:03:32 +0000
Subject: [PATCH 119/691] Added old admin extension
---
.env.example | 14 +-
lnbits/extensions/admin/README.md | 11 +
lnbits/extensions/admin/__init__.py | 10 +
lnbits/extensions/admin/config.json | 6 +
lnbits/extensions/admin/crud.py | 59 ++
lnbits/extensions/admin/migrations.py | 256 ++++++++
lnbits/extensions/admin/models.py | 38 ++
.../admin/templates/admin/index.html | 565 ++++++++++++++++++
lnbits/extensions/admin/views.py | 20 +
lnbits/extensions/admin/views_api.py | 41 ++
10 files changed, 1014 insertions(+), 6 deletions(-)
create mode 100644 lnbits/extensions/admin/README.md
create mode 100644 lnbits/extensions/admin/__init__.py
create mode 100644 lnbits/extensions/admin/config.json
create mode 100644 lnbits/extensions/admin/crud.py
create mode 100644 lnbits/extensions/admin/migrations.py
create mode 100644 lnbits/extensions/admin/models.py
create mode 100644 lnbits/extensions/admin/templates/admin/index.html
create mode 100644 lnbits/extensions/admin/views.py
create mode 100644 lnbits/extensions/admin/views_api.py
diff --git a/.env.example b/.env.example
index 987c6ca6..bfaeb515 100644
--- a/.env.example
+++ b/.env.example
@@ -3,17 +3,19 @@ PORT=5000
DEBUG=false
-LNBITS_ALLOWED_USERS=""
-LNBITS_ADMIN_USERS=""
-# Extensions only admin can access
-LNBITS_ADMIN_EXTENSIONS="ngrok"
+LNBITS_ADMIN_USERS="" # User IDs seperated by comma
+LNBITS_ADMIN_EXTENSIONS="ngrok" # Extensions only admin can access
+LNBITS_ADMIN_UI=false # Extensions only admin can access
+
+LNBITS_ALLOWED_USERS="" # Restricts access, User IDs seperated by comma
+
LNBITS_DEFAULT_WALLET_NAME="LNbits wallet"
# csv ad image filepaths or urls, extensions can choose to honor
LNBITS_AD_SPACE=""
# Hides wallet api, extensions can choose to honor
-LNBITS_HIDE_API=false
+LNBITS_HIDE_API=false
# Disable extensions for all users, use "all" to disable all extensions
LNBITS_DISABLED_EXTENSIONS="amilk"
@@ -67,7 +69,7 @@ LNBITS_KEY=LNBITS_ADMIN_KEY
LND_REST_ENDPOINT=https://127.0.0.1:8080/
LND_REST_CERT="/home/bob/.config/Zap/lnd/bitcoin/mainnet/wallet-1/data/chain/bitcoin/mainnet/tls.cert"
LND_REST_MACAROON="/home/bob/.config/Zap/lnd/bitcoin/mainnet/wallet-1/data/chain/bitcoin/mainnet/admin.macaroon or HEXSTRING"
-# To use an AES-encrypted macaroon, set
+# To use an AES-encrypted macaroon, set
# LND_REST_MACAROON_ENCRYPTED="eNcRyPtEdMaCaRoOn"
# LNPayWallet
diff --git a/lnbits/extensions/admin/README.md b/lnbits/extensions/admin/README.md
new file mode 100644
index 00000000..27729459
--- /dev/null
+++ b/lnbits/extensions/admin/README.md
@@ -0,0 +1,11 @@
+Example Extension
+*tagline*
+This is an example extension to help you organise and build you own.
+
+Try to include an image
+
+
+
+If your extension has API endpoints, include useful ones here
+
+curl -H "Content-type: application/json" -X POST https://YOUR-LNBITS/YOUR-EXTENSION/api/v1/EXAMPLE -d '{"amount":"100","memo":"example"}' -H "X-Api-Key: YOUR_WALLET-ADMIN/INVOICE-KEY"
diff --git a/lnbits/extensions/admin/__init__.py b/lnbits/extensions/admin/__init__.py
new file mode 100644
index 00000000..d5f26c90
--- /dev/null
+++ b/lnbits/extensions/admin/__init__.py
@@ -0,0 +1,10 @@
+from quart import Blueprint
+from lnbits.db import Database
+
+db = Database("ext_admin")
+
+admin_ext: Blueprint = Blueprint("admin", __name__, static_folder="static", template_folder="templates")
+
+
+from .views_api import * # noqa
+from .views import * # noqa
diff --git a/lnbits/extensions/admin/config.json b/lnbits/extensions/admin/config.json
new file mode 100644
index 00000000..69661733
--- /dev/null
+++ b/lnbits/extensions/admin/config.json
@@ -0,0 +1,6 @@
+{
+ "name": "Admin",
+ "short_description": "Manage your LNbits install",
+ "icon": "build",
+ "contributors": ["benarc"]
+}
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
new file mode 100644
index 00000000..cb8f9b5b
--- /dev/null
+++ b/lnbits/extensions/admin/crud.py
@@ -0,0 +1,59 @@
+from typing import List, Optional
+
+from . import db
+from .models import Admin, Funding
+from lnbits.settings import *
+from lnbits.helpers import urlsafe_short_hash
+from lnbits.core.crud import create_payment
+from lnbits.db import Connection
+
+
+def update_wallet_balance(wallet_id: str, amount: int) -> str:
+ temp_id = f"temp_{urlsafe_short_hash()}"
+ internal_id = f"internal_{urlsafe_short_hash()}"
+ 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,
+ )
+ return "success"
+
+
+async def update_admin(
+) -> Optional[Admin]:
+ if not CLightningWallet:
+ print("poo")
+ await db.execute(
+ """
+ UPDATE admin
+ SET user = ?, site_title = ?, site_tagline = ?, site_description = ?, allowed_users = ?, default_wallet_name = ?, data_folder = ?, disabled_ext = ?, force_https = ?, service_fee = ?, funding_source = ?
+ WHERE 1
+ """,
+ (
+
+ ),
+ )
+ row = await db.fetchone("SELECT * FROM admin WHERE 1")
+ return Admin.from_row(row) if row else None
+
+async def update_admin(admin_id: str, **kwargs) -> Optional[Admin]:
+ q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
+ await db.execute(
+ f"UPDATE jukebox.jukebox SET {q} WHERE id = ?", (*kwargs.values(), juke_id)
+ )
+ row = await db.fetchone("SELECT * FROM jukebox.jukebox WHERE id = ?", (juke_id,))
+ return Jukebox(**row) if row else None
+
+async def get_admin() -> List[Admin]:
+ row = await db.fetchone("SELECT * FROM admin WHERE 1")
+ return Admin.from_row(row) if row else None
+
+
+async def get_funding() -> List[Funding]:
+ rows = await db.fetchall("SELECT * FROM funding")
+
+ return [Funding.from_row(row) for row in rows]
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
new file mode 100644
index 00000000..82d934cb
--- /dev/null
+++ b/lnbits/extensions/admin/migrations.py
@@ -0,0 +1,256 @@
+from sqlalchemy.exc import OperationalError # type: ignore
+from os import getenv
+from lnbits.helpers import urlsafe_short_hash
+
+
+async def m001_create_admin_table(db):
+ user = None
+ site_title = None
+ site_tagline = None
+ site_description = None
+ allowed_users = None
+ admin_user = None
+ default_wallet_name = None
+ data_folder = None
+ disabled_ext = None
+ force_https = True
+ service_fee = 0
+ funding_source = ""
+
+ if getenv("LNBITS_SITE_TITLE"):
+ site_title = getenv("LNBITS_SITE_TITLE")
+
+ if getenv("LNBITS_SITE_TAGLINE"):
+ site_tagline = getenv("LNBITS_SITE_TAGLINE")
+
+ if getenv("LNBITS_SITE_DESCRIPTION"):
+ site_description = getenv("LNBITS_SITE_DESCRIPTION")
+
+ if getenv("LNBITS_ALLOWED_USERS"):
+ allowed_users = getenv("LNBITS_ALLOWED_USERS")
+
+ if getenv("LNBITS_ADMIN_USER"):
+ admin_user = getenv("LNBITS_ADMIN_USER")
+
+ if getenv("LNBITS_DEFAULT_WALLET_NAME"):
+ default_wallet_name = getenv("LNBITS_DEFAULT_WALLET_NAME")
+
+ if getenv("LNBITS_DATA_FOLDER"):
+ data_folder = getenv("LNBITS_DATA_FOLDER")
+
+ if getenv("LNBITS_DISABLED_EXTENSIONS"):
+ disabled_ext = getenv("LNBITS_DISABLED_EXTENSIONS")
+
+ if getenv("LNBITS_FORCE_HTTPS"):
+ force_https = getenv("LNBITS_FORCE_HTTPS")
+
+ if getenv("LNBITS_SERVICE_FEE"):
+ service_fee = getenv("LNBITS_SERVICE_FEE")
+
+ if getenv("LNBITS_BACKEND_WALLET_CLASS"):
+ funding_source = getenv("LNBITS_BACKEND_WALLET_CLASS")
+
+ await db.execute(
+ """
+ CREATE TABLE IF NOT EXISTS admin (
+ user TEXT,
+ site_title TEXT,
+ site_tagline TEXT,
+ site_description TEXT,
+ admin_user TEXT,
+ allowed_users TEXT,
+ default_wallet_name TEXT,
+ data_folder TEXT,
+ disabled_ext TEXT,
+ force_https BOOLEAN,
+ service_fee INT,
+ funding_source TEXT
+ );
+ """
+ )
+ await db.execute(
+ """
+ INSERT INTO admin (user, site_title, site_tagline, site_description, admin_user, allowed_users, default_wallet_name, data_folder, disabled_ext, force_https, service_fee, funding_source)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ """,
+ (
+ user,
+ site_title,
+ site_tagline,
+ site_description,
+ admin_user,
+ allowed_users,
+ default_wallet_name,
+ data_folder,
+ disabled_ext,
+ force_https,
+ service_fee,
+ funding_source,
+ ),
+ )
+
+
+async def m001_create_funding_table(db):
+
+ funding_wallet = getenv("LNBITS_BACKEND_WALLET_CLASS")
+
+ # Make the funding table, if it does not already exist
+ await db.execute(
+ """
+ CREATE TABLE IF NOT EXISTS funding (
+ id TEXT PRIMARY KEY,
+ backend_wallet TEXT,
+ endpoint TEXT,
+ port INT,
+ read_key TEXT,
+ invoice_key TEXT,
+ admin_key TEXT,
+ cert TEXT,
+ balance INT,
+ selected INT
+ );
+ """
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, selected)
+ VALUES (?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "CLightningWallet",
+ getenv("CLIGHTNING_RPC"),
+ 1 if funding_wallet == "CLightningWallet" else 0,
+ ),
+ )
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ VALUES (?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "SparkWallet",
+ getenv("SPARK_URL"),
+ getenv("SPARK_TOKEN"),
+ 1 if funding_wallet == "SparkWallet" else 0,
+ ),
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ VALUES (?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "LnbitsWallet",
+ getenv("LNBITS_ENDPOINT"),
+ getenv("LNBITS_KEY"),
+ 1 if funding_wallet == "LnbitsWallet" else 0,
+ ),
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, port, admin_key, cert, selected)
+ VALUES (?, ?, ?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "LndWallet",
+ getenv("LND_GRPC_ENDPOINT"),
+ getenv("LND_GRPC_PORT"),
+ getenv("LND_GRPC_MACAROON"),
+ getenv("LND_GRPC_CERT"),
+ 1 if funding_wallet == "LndWallet" else 0,
+ ),
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, admin_key, cert, selected)
+ VALUES (?, ?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "LndRestWallet",
+ getenv("LND_REST_ENDPOINT"),
+ getenv("LND_REST_MACAROON"),
+ getenv("LND_REST_CERT"),
+ 1 if funding_wallet == "LndWallet" else 0,
+ ),
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, admin_key, cert, selected)
+ VALUES (?, ?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "LNPayWallet",
+ getenv("LNPAY_API_ENDPOINT"),
+ getenv("LNPAY_WALLET_KEY"),
+ getenv("LNPAY_API_KEY"), # this is going in as the cert
+ 1 if funding_wallet == "LNPayWallet" else 0,
+ ),
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ VALUES (?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "LntxbotWallet",
+ getenv("LNTXBOT_API_ENDPOINT"),
+ getenv("LNTXBOT_KEY"),
+ 1 if funding_wallet == "LntxbotWallet" else 0,
+ ),
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ VALUES (?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "OpenNodeWallet",
+ getenv("OPENNODE_API_ENDPOINT"),
+ getenv("OPENNODE_KEY"),
+ 1 if funding_wallet == "OpenNodeWallet" else 0,
+ ),
+ )
+
+ await db.execute(
+ """
+ INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ VALUES (?, ?, ?, ?, ?)
+ """,
+ (
+ urlsafe_short_hash(),
+ "SparkWallet",
+ getenv("SPARK_URL"),
+ getenv("SPARK_TOKEN"),
+ 1 if funding_wallet == "SparkWallet" else 0,
+ ),
+ )
+
+ ## PLACEHOLDER FOR ECLAIR WALLET
+ # await db.execute(
+ # """
+ # INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ # VALUES (?, ?, ?, ?, ?)
+ # """,
+ # (
+ # urlsafe_short_hash(),
+ # "EclairWallet",
+ # getenv("ECLAIR_URL"),
+ # getenv("ECLAIR_PASS"),
+ # 1 if funding_wallet == "EclairWallet" else 0,
+ # ),
+ # )
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
new file mode 100644
index 00000000..c38f17f4
--- /dev/null
+++ b/lnbits/extensions/admin/models.py
@@ -0,0 +1,38 @@
+from typing import NamedTuple
+from sqlite3 import Row
+
+class Admin(NamedTuple):
+ user: str
+ site_title: str
+ site_tagline: str
+ site_description:str
+ allowed_users: str
+ admin_user: str
+ default_wallet_name: str
+ data_folder: str
+ disabled_ext: str
+ force_https: str
+ service_fee: str
+ funding_source: str
+
+ @classmethod
+ def from_row(cls, row: Row) -> "Admin":
+ data = dict(row)
+ return cls(**data)
+
+class Funding(NamedTuple):
+ id: str
+ backend_wallet: str
+ endpoint: str
+ port: str
+ read_key: str
+ invoice_key: str
+ admin_key: str
+ cert: str
+ balance: int
+ selected: int
+
+ @classmethod
+ def from_row(cls, row: Row) -> "Funding":
+ data = dict(row)
+ return cls(**data)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
new file mode 100644
index 00000000..87cf09ef
--- /dev/null
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -0,0 +1,565 @@
+{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
+%} {% block page %}
+
+Admin
+
+
+
+
+
+
+ Settings
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Wallet topup
+
+
+
+
+
+
+
+
+
+{% endblock %} {% block scripts %} {{ window_vars(user) }}
+
+{% endblock %}
diff --git a/lnbits/extensions/admin/views.py b/lnbits/extensions/admin/views.py
new file mode 100644
index 00000000..5e17919c
--- /dev/null
+++ b/lnbits/extensions/admin/views.py
@@ -0,0 +1,20 @@
+from quart import g, render_template, request, jsonify
+import json
+
+from lnbits.decorators import check_user_exists, validate_uuids
+from lnbits.extensions.admin import admin_ext
+from lnbits.core.crud import get_user, create_account
+from .crud import get_admin, get_funding
+from lnbits.settings import WALLET
+
+
+@admin_ext.route("/")
+@validate_uuids(["usr"], required=True)
+@check_user_exists()
+async def index():
+ user_id = g.user
+ admin = await get_admin()
+
+ funding = [{**funding._asdict()} for funding in await get_funding()]
+
+ return await render_template("admin/index.html", user=g.user, admin=admin, funding=funding)
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
new file mode 100644
index 00000000..2a61b6f5
--- /dev/null
+++ b/lnbits/extensions/admin/views_api.py
@@ -0,0 +1,41 @@
+from quart import jsonify, g, request
+from http import HTTPStatus
+from .crud import update_wallet_balance
+from lnbits.extensions.admin import admin_ext
+from lnbits.decorators import api_check_wallet_key, api_validate_post_request
+from lnbits.core.crud import get_wallet
+from .crud import get_admin,update_admin
+import json
+
+@admin_ext.route("/api/v1/admin//", methods=["GET"])
+@api_check_wallet_key("admin")
+async def api_update_balance(wallet_id, topup_amount):
+ print(g.data.wallet)
+ try:
+ wallet = await get_wallet(wallet_id)
+ except:
+ return (
+ jsonify({"error": "Not allowed: not an admin"}),
+ HTTPStatus.FORBIDDEN,
+ )
+ print(wallet)
+ print(topup_amount)
+ return jsonify({"status": "Success"}), HTTPStatus.OK
+
+
+@admin_ext.route("/api/v1/admin/", methods=["POST"])
+@api_check_wallet_key("admin")
+@api_validate_post_request(schema={})
+async def api_update_admin():
+ body = await request.get_json()
+ admin = await get_admin()
+ print(g.wallet[2])
+ print(body["admin_user"])
+ if not admin.admin_user == g.wallet[2] and admin.admin_user != None:
+ return (
+ jsonify({"error": "Not allowed: not an admin"}),
+ HTTPStatus.FORBIDDEN,
+ )
+ updated = await update_admin(body)
+ print(updated)
+ return jsonify({"status": "Success"}), HTTPStatus.OK
\ No newline at end of file
From a3b1d9528c92008b42116904f5ebbdf8d9360173 Mon Sep 17 00:00:00 2001
From: benarc
Date: Mon, 7 Mar 2022 05:11:55 +0000
Subject: [PATCH 120/691] old admin setup UI
---
lnbits/core/templates/core/admin.html | 717 ++++++++++++++++++++++++++
1 file changed, 717 insertions(+)
create mode 100644 lnbits/core/templates/core/admin.html
diff --git a/lnbits/core/templates/core/admin.html b/lnbits/core/templates/core/admin.html
new file mode 100644
index 00000000..e8176555
--- /dev/null
+++ b/lnbits/core/templates/core/admin.html
@@ -0,0 +1,717 @@
+{% extends "public.html" %} {% from "macros.jinja" import window_vars with
+context %} {% block page %}
+
+
+
+
+
+ Welcome to LNbits
+
+
+ Fill in the information below to setup your LNbits instance. Details
+ can be changed later.
+
+
+
+
+
+
+ Branding
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Service settings
+
+
+
+ Funding source information (at least one required)
*if installed through RaspiBlitz, MyNode, etc, details
+ should be filled in for you
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ View project in GitHub
+ Donate
+
+
+
+
+
+{% endblock %} {% block scripts %} {{ window_vars(funding) }}
+
+{% endblock %}
From b325566302f079575e478d9ca9eeff47a8f10a1a Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Sat, 12 Mar 2022 14:18:09 +0000
Subject: [PATCH 121/691] convert to FastAPI
---
lnbits/extensions/admin/__init__.py | 11 +++-
lnbits/extensions/admin/crud.py | 50 +++++++--------
lnbits/extensions/admin/migrations.py | 23 ++++---
lnbits/extensions/admin/models.py | 51 ++++++++++------
.../admin/templates/admin/index.html | 23 +++++--
lnbits/extensions/admin/views.py | 39 ++++++++----
lnbits/extensions/admin/views_api.py | 61 ++++++++++---------
7 files changed, 151 insertions(+), 107 deletions(-)
diff --git a/lnbits/extensions/admin/__init__.py b/lnbits/extensions/admin/__init__.py
index d5f26c90..6a56b2bb 100644
--- a/lnbits/extensions/admin/__init__.py
+++ b/lnbits/extensions/admin/__init__.py
@@ -1,10 +1,15 @@
-from quart import Blueprint
+from fastapi import APIRouter
+
from lnbits.db import Database
+from lnbits.helpers import template_renderer
db = Database("ext_admin")
-admin_ext: Blueprint = Blueprint("admin", __name__, static_folder="static", template_folder="templates")
+admin_ext: APIRouter = APIRouter(prefix="/admin", tags=["admin"])
+
+def admin_renderer():
+ return template_renderer(["lnbits/extensions/admin/templates"])
-from .views_api import * # noqa
from .views import * # noqa
+from .views_api import * # noqa
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index cb8f9b5b..872d6c97 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -1,11 +1,11 @@
from typing import List, Optional
+from lnbits.core.crud import create_payment
+from lnbits.helpers import urlsafe_short_hash
+from lnbits.settings import *
+
from . import db
from .models import Admin, Funding
-from lnbits.settings import *
-from lnbits.helpers import urlsafe_short_hash
-from lnbits.core.crud import create_payment
-from lnbits.db import Connection
def update_wallet_balance(wallet_id: str, amount: int) -> str:
@@ -22,38 +22,30 @@ def update_wallet_balance(wallet_id: str, amount: int) -> str:
)
return "success"
-
-async def update_admin(
-) -> Optional[Admin]:
- if not CLightningWallet:
- print("poo")
- await db.execute(
- """
- UPDATE admin
- SET user = ?, site_title = ?, site_tagline = ?, site_description = ?, allowed_users = ?, default_wallet_name = ?, data_folder = ?, disabled_ext = ?, force_https = ?, service_fee = ?, funding_source = ?
- WHERE 1
- """,
- (
-
- ),
- )
- row = await db.fetchone("SELECT * FROM admin WHERE 1")
- return Admin.from_row(row) if row else None
-
-async def update_admin(admin_id: str, **kwargs) -> Optional[Admin]:
+async def update_admin(user: str, **kwargs) -> Admin:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
+ print("UPDATE", q)
await db.execute(
- f"UPDATE jukebox.jukebox SET {q} WHERE id = ?", (*kwargs.values(), juke_id)
+ f'UPDATE admin SET {q} WHERE "user" = ?', (*kwargs.values(), user)
)
- row = await db.fetchone("SELECT * FROM jukebox.jukebox WHERE id = ?", (juke_id,))
- return Jukebox(**row) if row else None
+ row = await db.fetchone('SELECT * FROM admin WHERE "user" = ?', (user,))
+ assert row, "Newly updated settings couldn't be retrieved"
+ return Admin(**row) if row else None
+
+# async def update_admin(user: str, **kwargs) -> Optional[Admin]:
+# q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
+# await db.execute(
+# f"UPDATE admin SET {q} WHERE user = ?", (*kwargs.values(), user)
+# )
+# new_settings = await get_admin()
+# return new_settings
async def get_admin() -> List[Admin]:
- row = await db.fetchone("SELECT * FROM admin WHERE 1")
- return Admin.from_row(row) if row else None
+ row = await db.fetchone("SELECT * FROM admin")
+ return Admin(**row) if row else None
async def get_funding() -> List[Funding]:
rows = await db.fetchall("SELECT * FROM funding")
- return [Funding.from_row(row) for row in rows]
+ return [Funding(**row) for row in rows]
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 82d934cb..13b76923 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -1,5 +1,7 @@
-from sqlalchemy.exc import OperationalError # type: ignore
from os import getenv
+
+from sqlalchemy.exc import OperationalError # type: ignore
+
from lnbits.helpers import urlsafe_short_hash
@@ -9,7 +11,7 @@ async def m001_create_admin_table(db):
site_tagline = None
site_description = None
allowed_users = None
- admin_user = None
+ admin_users = None
default_wallet_name = None
data_folder = None
disabled_ext = None
@@ -29,8 +31,9 @@ async def m001_create_admin_table(db):
if getenv("LNBITS_ALLOWED_USERS"):
allowed_users = getenv("LNBITS_ALLOWED_USERS")
- if getenv("LNBITS_ADMIN_USER"):
- admin_user = getenv("LNBITS_ADMIN_USER")
+ if getenv("LNBITS_ADMIN_USERS"):
+ admin_users = "".join(getenv("LNBITS_ADMIN_USERS").split())
+ user = admin_users.split(',')[0]
if getenv("LNBITS_DEFAULT_WALLET_NAME"):
default_wallet_name = getenv("LNBITS_DEFAULT_WALLET_NAME")
@@ -53,32 +56,32 @@ async def m001_create_admin_table(db):
await db.execute(
"""
CREATE TABLE IF NOT EXISTS admin (
- user TEXT,
+ "user" TEXT,
site_title TEXT,
site_tagline TEXT,
site_description TEXT,
- admin_user TEXT,
+ admin_users TEXT,
allowed_users TEXT,
default_wallet_name TEXT,
data_folder TEXT,
disabled_ext TEXT,
force_https BOOLEAN,
- service_fee INT,
+ service_fee REAL,
funding_source TEXT
);
"""
)
await db.execute(
"""
- INSERT INTO admin (user, site_title, site_tagline, site_description, admin_user, allowed_users, default_wallet_name, data_folder, disabled_ext, force_https, service_fee, funding_source)
+ INSERT INTO admin ("user", site_title, site_tagline, site_description, admin_users, allowed_users, default_wallet_name, data_folder, disabled_ext, force_https, service_fee, funding_source)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
- user,
+ user.strip(),
site_title,
site_tagline,
site_description,
- admin_user,
+ admin_users[1:],
allowed_users,
default_wallet_name,
data_folder,
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index c38f17f4..4080ff01 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -1,18 +1,35 @@
-from typing import NamedTuple
from sqlite3 import Row
+from typing import List, Optional
-class Admin(NamedTuple):
+from fastapi import Query
+from pydantic import BaseModel
+
+
+class UpdateAdminSettings(BaseModel):
+ site_title: Optional[str]
+ site_tagline: Optional[str]
+ site_description: Optional[str]
+ allowed_users: Optional[str]
+ admin_users: Optional[str]
+ default_wallet_name: Optional[str]
+ data_folder: Optional[str]
+ disabled_ext: Optional[str]
+ force_https: Optional[bool]
+ service_fee: Optional[float]
+ funding_source: Optional[str]
+
+class Admin(BaseModel):
user: str
- site_title: str
- site_tagline: str
- site_description:str
- allowed_users: str
- admin_user: str
+ site_title: Optional[str]
+ site_tagline: Optional[str]
+ site_description: Optional[str]
+ allowed_users: Optional[str]
+ admin_users: str
default_wallet_name: str
data_folder: str
disabled_ext: str
- force_https: str
- service_fee: str
+ force_https: Optional[bool] = Query(True)
+ service_fee: float
funding_source: str
@classmethod
@@ -20,16 +37,16 @@ class Admin(NamedTuple):
data = dict(row)
return cls(**data)
-class Funding(NamedTuple):
+class Funding(BaseModel):
id: str
backend_wallet: str
- endpoint: str
- port: str
- read_key: str
- invoice_key: str
- admin_key: str
- cert: str
- balance: int
+ endpoint: str = Query(None)
+ port: str = Query(None)
+ read_key: str = Query(None)
+ invoice_key: str = Query(None)
+ admin_key: str = Query(None)
+ cert: str = Query(None)
+ balance: int = Query(None)
selected: int
@classmethod
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 87cf09ef..a6b45625 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -87,7 +87,7 @@
@@ -442,13 +442,14 @@
site_title: '{{admin.site_title}}',
tagline: '{{admin.site_tagline}}',
description: '{{admin.site_description}}',
- admin_user: '{{admin.admin_user}}',
- service_fee: parseInt('{{admin.service_fee}}'),
+ admin_users: '{{admin.admin_users}}',
+ service_fee: parseFloat('{{admin.service_fee}}'),
default_wallet_name: '{{admin.default_wallet_name}}',
data_folder: '{{admin.data_folder}}',
funding_source_primary: '{{admin.funding_source}}',
disabled_ext: '{{admin.disabled_ext}}'.split(','),
edited: [],
+ funding: {},
senddata: {}
}
},
@@ -528,15 +529,27 @@
},
UpdateLNbits: function () {
var self = this
- console.log(self.data.admin)
+ let {site_title, admin_users, default_wallet_name, data_folder, disabled_ext, service_fee, funding_source_primary} = this.data.admin
+ let data = {
+ site_title,
+ site_tagline: this.data.admin.tagline,
+ site_description: this.data.admin.description,
+ admin_users: admin_users.toString(),
+ default_wallet_name,
+ data_folder,
+ disabled_ext: disabled_ext.toString(),
+ service_fee,
+ funding_source: funding_source_primary}
+ console.log(data)
LNbits.api
.request(
'POST',
'/admin/api/v1/admin/',
self.g.user.wallets[0].adminkey,
- self.data.admin
+ data
)
.then(function (response) {
+ console.log(response.data)
self.$q.notify({
type: 'positive',
message:
diff --git a/lnbits/extensions/admin/views.py b/lnbits/extensions/admin/views.py
index 5e17919c..00a0c99f 100644
--- a/lnbits/extensions/admin/views.py
+++ b/lnbits/extensions/admin/views.py
@@ -1,20 +1,33 @@
-from quart import g, render_template, request, jsonify
-import json
+from email.policy import default
+from os import getenv
-from lnbits.decorators import check_user_exists, validate_uuids
+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_user_exists
from lnbits.extensions.admin import admin_ext
-from lnbits.core.crud import get_user, create_account
+from lnbits.requestvars import g
+
+from . import admin_ext, admin_renderer
from .crud import get_admin, get_funding
-from lnbits.settings import WALLET
+templates = Jinja2Templates(directory="templates")
-@admin_ext.route("/")
-@validate_uuids(["usr"], required=True)
-@check_user_exists()
-async def index():
- user_id = g.user
+@admin_ext.get("/", response_class=HTMLResponse)
+async def index(request: Request, user: User = Depends(check_user_exists)):
admin = await get_admin()
+ print(g())
+ funding = [f.dict() for f in await get_funding()]
- funding = [{**funding._asdict()} for funding in await get_funding()]
-
- return await render_template("admin/index.html", user=g.user, admin=admin, funding=funding)
+ print("ADMIN", admin.dict())
+ return admin_renderer().TemplateResponse(
+ "admin/index.html", {
+ "request": request,
+ "user": user.dict(),
+ "admin": admin.dict(),
+ "funding": funding
+ }
+ )
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index 2a61b6f5..b2c65be2 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -1,41 +1,42 @@
-from quart import jsonify, g, request
from http import HTTPStatus
-from .crud import update_wallet_balance
-from lnbits.extensions.admin import admin_ext
-from lnbits.decorators import api_check_wallet_key, api_validate_post_request
-from lnbits.core.crud import get_wallet
-from .crud import get_admin,update_admin
-import json
-@admin_ext.route("/api/v1/admin//", methods=["GET"])
-@api_check_wallet_key("admin")
-async def api_update_balance(wallet_id, topup_amount):
- print(g.data.wallet)
+from fastapi import Body, Depends, Request
+from starlette.exceptions import HTTPException
+
+from lnbits.core.crud import get_wallet
+from lnbits.decorators import WalletTypeInfo, require_admin_key
+from lnbits.extensions.admin import admin_ext
+from lnbits.extensions.admin.models import Admin, UpdateAdminSettings
+
+from .crud import get_admin, update_admin, update_wallet_balance
+
+
+@admin_ext.get("/api/v1/admin/{wallet_id}/{topup_amount}", status_code=HTTPStatus.OK)
+async def api_update_balance(wallet_id, topup_amount, g: WalletTypeInfo = Depends(require_admin_key)):
+ print(g.wallet)
try:
wallet = await get_wallet(wallet_id)
except:
- return (
- jsonify({"error": "Not allowed: not an admin"}),
- HTTPStatus.FORBIDDEN,
- )
+ raise HTTPException(
+ status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
+ )
print(wallet)
print(topup_amount)
- return jsonify({"status": "Success"}), HTTPStatus.OK
+ return {"status": "Success"}
-@admin_ext.route("/api/v1/admin/", methods=["POST"])
-@api_check_wallet_key("admin")
-@api_validate_post_request(schema={})
-async def api_update_admin():
- body = await request.get_json()
+@admin_ext.post("/api/v1/admin/", status_code=HTTPStatus.OK)
+async def api_update_admin(
+ request: Request,
+ data: UpdateAdminSettings = Body(...),
+ g: WalletTypeInfo = Depends(require_admin_key)
+ ):
admin = await get_admin()
- print(g.wallet[2])
- print(body["admin_user"])
- if not admin.admin_user == g.wallet[2] and admin.admin_user != None:
- return (
- jsonify({"error": "Not allowed: not an admin"}),
- HTTPStatus.FORBIDDEN,
- )
- updated = await update_admin(body)
+ print(data)
+ if not admin.user == g.wallet.user:
+ raise HTTPException(
+ status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
+ )
+ updated = await update_admin(user=g.wallet.user, **data.dict())
print(updated)
- return jsonify({"status": "Success"}), HTTPStatus.OK
\ No newline at end of file
+ return {"status": "Success"}
From b4885de9e2fcf598994dd5ca2360cc29629aaa23 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Sat, 12 Mar 2022 14:18:58 +0000
Subject: [PATCH 122/691] remove core admin html (renamed for now)
---
lnbits/core/templates/core/core_admin.html | 717 +++++++++++++++++++++
1 file changed, 717 insertions(+)
create mode 100644 lnbits/core/templates/core/core_admin.html
diff --git a/lnbits/core/templates/core/core_admin.html b/lnbits/core/templates/core/core_admin.html
new file mode 100644
index 00000000..835fc00a
--- /dev/null
+++ b/lnbits/core/templates/core/core_admin.html
@@ -0,0 +1,717 @@
+{% extends "public.html" %} {% from "macros.jinja" import window_vars with
+context %} {% block page %}
+
+
+
+
+
+ Welcome to LNbits
+
+
+ Fill in the information below to setup your LNbits instance. Details
+ can be changed later.
+
+
+
+
+
+
+ Branding
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Service settings
+
+
+
+ Funding source information (at least one required)
*if installed through RaspiBlitz, MyNode, etc, details
+ should be filled in for you
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ View project in GitHub
+ Donate
+
+
+
+
+
+{% endblock %} {% block scripts %} {{ window_vars(funding) }}
+
+{% endblock %}
From c41b4e714c2e20c36d6a262c77966598b1fd85c4 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Sat, 12 Mar 2022 14:21:38 +0000
Subject: [PATCH 123/691] typo
---
.env.example | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.env.example b/.env.example
index bfaeb515..4192f82e 100644
--- a/.env.example
+++ b/.env.example
@@ -5,7 +5,7 @@ DEBUG=false
LNBITS_ADMIN_USERS="" # User IDs seperated by comma
LNBITS_ADMIN_EXTENSIONS="ngrok" # Extensions only admin can access
-LNBITS_ADMIN_UI=false # Extensions only admin can access
+LNBITS_ADMIN_UI=false # Enable Admin GUI, available for the first user in LNBITS_ADMIN_USERS
LNBITS_ALLOWED_USERS="" # Restricts access, User IDs seperated by comma
From 922206b365cff523a12bf5a8014b544aa88398f3 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Sat, 12 Mar 2022 14:22:23 +0000
Subject: [PATCH 124/691] add admin_ui env
---
lnbits/settings.py | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lnbits/settings.py b/lnbits/settings.py
index 3f4e31cc..43cb87cb 100644
--- a/lnbits/settings.py
+++ b/lnbits/settings.py
@@ -1,5 +1,6 @@
import importlib
import subprocess
+from email.policy import default
from os import path
from typing import List
@@ -27,6 +28,7 @@ LNBITS_DATABASE_URL = env.str("LNBITS_DATABASE_URL", default=None)
LNBITS_ALLOWED_USERS: List[str] = [
x.strip(" ") for x in env.list("LNBITS_ALLOWED_USERS", default=[], subcast=str)
]
+LNBITS_ADMIN_UI = env.bool("LNBITS_ADMIN_UI", default=False)
LNBITS_ADMIN_USERS: List[str] = [
x.strip(" ") for x in env.list("LNBITS_ADMIN_USERS", default=[], subcast=str)
]
From b47ed3068105f2526365f6708efe5134a5fe1c0e Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Sat, 12 Mar 2022 14:23:16 +0000
Subject: [PATCH 125/691] add db config at startup
---
lnbits/commands.py | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/lnbits/commands.py b/lnbits/commands.py
index 0f7454f2..8c39c338 100644
--- a/lnbits/commands.py
+++ b/lnbits/commands.py
@@ -52,6 +52,25 @@ def bundle_vendored():
with open(outputpath, "w") as f:
f.write(output)
+async def get_admin_settings():
+ from lnbits.extensions.admin.models import Admin
+
+ async with core_db.connect() as conn:
+
+ if conn.type == SQLITE:
+ exists = await conn.fetchone(
+ "SELECT * FROM sqlite_master WHERE type='table' AND name='admin'"
+ )
+ elif conn.type in {POSTGRES, COCKROACH}:
+ exists = await conn.fetchone(
+ "SELECT * FROM information_schema.tables WHERE table_name = 'admin'"
+ )
+ if not exists:
+ return False
+
+ row = await conn.fetchone("SELECT * from admin")
+
+ return Admin(**row) if row else None
async def migrate_databases():
"""Creates the necessary databases if they don't exist already; or migrates them."""
From 4bf17c5df2d07443c972be9356be710e4578c79b Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Sat, 12 Mar 2022 14:23:53 +0000
Subject: [PATCH 126/691] get admin settings at startup
---
lnbits/app.py | 23 ++++++++++++++++++++++-
1 file changed, 22 insertions(+), 1 deletion(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 075828ef..7ff9e4eb 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -18,6 +18,7 @@ from loguru import logger
import lnbits.settings
from lnbits.core.tasks import register_task_listeners
+from .commands import get_admin_settings
from .core import core_app
from .core.views.generic import core_html_routes
from .helpers import (
@@ -42,6 +43,7 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
"""Create application factory.
:param config_object: The configuration object to use.
"""
+<<<<<<< HEAD
configure_logger()
app = FastAPI(
@@ -53,6 +55,14 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
},
)
app.mount("/static", StaticFiles(packages=[("lnbits", "static")]), name="static")
+=======
+ app = FastAPI()
+
+ if lnbits.settings.LNBITS_ADMIN_UI:
+ check_settings(app)
+
+ app.mount("/static", StaticFiles(directory="lnbits/static"), name="static")
+>>>>>>> e3a1b3ae (get admin settings at startup)
app.mount(
"/core/static",
StaticFiles(packages=[("lnbits.core", "static")]),
@@ -64,7 +74,6 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
app.add_middleware(
CORSMiddleware, allow_origins=origins, allow_methods=["*"], allow_headers=["*"]
)
-
g().config = lnbits.settings
g().base_url = f"http://{lnbits.settings.HOST}:{lnbits.settings.PORT}"
@@ -101,6 +110,18 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
return app
+def check_settings(app: FastAPI):
+ @app.on_event("startup")
+ async def check_settings_admin():
+ while True:
+ admin_set = await get_admin_settings()
+ if admin_set :
+ break
+ print("ERROR:", admin_set)
+ await asyncio.sleep(5)
+ # admin_set = await get_admin_settings()
+ g().admin_conf = admin_set
+
def check_funding_source(app: FastAPI) -> None:
@app.on_event("startup")
async def check_wallet_status():
From 48d6a89e5ba9e1e082a2ff189b3307d685f521e4 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Sat, 12 Mar 2022 14:24:11 +0000
Subject: [PATCH 127/691] remove core admin.html
---
lnbits/core/templates/core/admin.html | 717 --------------------------
1 file changed, 717 deletions(-)
delete mode 100644 lnbits/core/templates/core/admin.html
diff --git a/lnbits/core/templates/core/admin.html b/lnbits/core/templates/core/admin.html
deleted file mode 100644
index e8176555..00000000
--- a/lnbits/core/templates/core/admin.html
+++ /dev/null
@@ -1,717 +0,0 @@
-{% extends "public.html" %} {% from "macros.jinja" import window_vars with
-context %} {% block page %}
-
-
-
-
-
- Welcome to LNbits
-
-
- Fill in the information below to setup your LNbits instance. Details
- can be changed later.
-
-
-
-
-
-
- Branding
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Service settings
-
-
-
- Funding source information (at least one required)
*if installed through RaspiBlitz, MyNode, etc, details
- should be filled in for you
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- View project in GitHub
- Donate
-
-
-
-
-
-{% endblock %} {% block scripts %} {{ window_vars(funding) }}
-
-{% endblock %}
From 87bee88de403723b9d98f64716c573e21289a50a Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Fri, 18 Mar 2022 16:55:31 +0000
Subject: [PATCH 128/691] refactor ui
---
.../admin/templates/admin/index.html | 727 +++++++++++++++++-
1 file changed, 712 insertions(+), 15 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index a6b45625..65ac9f33 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -1,6 +1,670 @@
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
%} {% block page %}
+
+
+
+
+
+
+ tab = val.name"
+ >
+ tab = val.name"
+ >
+ tab = val.name"
+ >
+ tab = val.name"
+ >
+
+
+
+
+
+
+
+ Wallets Management
+
+
+
+
+
Funding Source Info
+
+ {%raw%}
+ - Funding Source: {{data.admin.funding_source}}
+ - Balance: {{data.admin.balance / 1000}} sats
+ {%endraw%}
+
+
+
+
+
+
+
+
+ TopUp a wallet
+
+
+
+
+
+
+
+
+
Funding Sources
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Save
+
+
+
+
+
+ User Management
+
+
+ Super Admin: {% raw
+ %}{{this.data.admin.user}}{% endraw %}
+
+
+
+
Admin Users
+
+
+
+
+ {% raw %}
+
+ {{ user }}
+
+ {% endraw %}
+
+
+
+
+
Allowed Users
+
+
+
+
+ {% raw %}
+
+ {{ user }}
+
+ {% endraw %}
+
+
+
+
+
+
+
Disabled Extensions
+
+
+
+
+
+ Save
+
+
+
+
+
+ Server Management
+
+
+
+
+
Server Info
+
+ {%raw%}
+ - SQlite: {{data.admin.data_folder}}
+ - Postgres: {{data.admin.database_url}}
+ {%endraw%}
+
+
+
+
+
+
+
+
Miscelaneous
+
+
+ Force HTTPS
+ Prefer secure URLs
+
+
+
+
+
+
+
+ Hide API
+ Hides wallet api, extensions can choose to honor
+
+
+
+
+
+
+
+
+
+
+
+ Save
+
+
+
+
+
+ UI Management
+
+
+
+
+
+
+
+
Default Wallet Name
+
+
+
+
+
+
+
+
+
Advertisement Slots
+
+
+
+
+ {% raw %}
+
+ {{ space.slice(0, 8) + " ... " + space.slice(-8) }}
+
+ {% endraw %}
+
+
+
+
+
+
+
+ Save
+
+
+
+
+
+
+
+
+
Admin
-
+
@@ -426,6 +1090,7 @@
return {
wallet: {data: {}},
cancel: {},
+ tab: 'funding',
data: {
funding_source: [
'CLightningWallet',
@@ -436,24 +1101,14 @@
'LnbitsWallet',
'OpenNodeWallet'
],
-
+
admin: {
- user: '{{ user.id }}',
- site_title: '{{admin.site_title}}',
- tagline: '{{admin.site_tagline}}',
- description: '{{admin.site_description}}',
- admin_users: '{{admin.admin_users}}',
- service_fee: parseFloat('{{admin.service_fee}}'),
- default_wallet_name: '{{admin.default_wallet_name}}',
- data_folder: '{{admin.data_folder}}',
- funding_source_primary: '{{admin.funding_source}}',
- disabled_ext: '{{admin.disabled_ext}}'.split(','),
edited: [],
funding: {},
senddata: {}
}
},
-
+ themes: ['classic', 'bitcoin', 'flamingo', 'mint', 'autumn', 'monochrome', 'salvador'],
options: [
'bleskomat',
'captcha',
@@ -489,9 +1144,51 @@
for (i = 0; i < funding.length; i++) {
self.data.admin.funding[funding[i].backend_wallet] = funding[i]
}
- console.log(self.data.admin)
+ let settings = JSON.parse('{{ settings | tojson|safe }}')
+ settings.balance = '{{ balance }}'
+ this.data.admin = {...this.data.admin, ...settings}
+ console.log(this.g.user)
},
methods: {
+ addAdminUser(){
+ let addUser = this.data.admin_users_add
+ let admin_users = this.data.admin.admin_users
+ if(addUser.length && !admin_users.includes(addUser)){
+ admin_users.push(addUser)
+ this.data.admin.admin_users = admin_users
+ this.data.admin_users_add = ""
+ }
+ },
+ removeAdminUser(user){
+ let admin_users = this.data.admin.admin_users
+ this.data.admin.admin_users = admin_users.filter(u => u !== user)
+ },
+ addAllowedUser(){
+ let addUser = this.data.allowed_users_add
+ let allowed_users = this.data.admin.allowed_users
+ if(addUser.length && !allowed_users.includes(addUser)){
+ allowed_users.push(addUser)
+ this.data.admin.allowed_users = allowed_users
+ this.data.allowed_users_add = ""
+ }
+ },
+ removeAllowedUser(user){
+ let allowed_users = this.data.admin.allowed_users
+ this.data.admin.allowed_users = allowed_users.filter(u => u !== user)
+ },
+ addAdSpace(){
+ let adSpace = this.data.ad_space_add
+ let spaces = this.data.admin.ad_space
+ if(adSpace.length && !spaces.includes(adSpace)){
+ spaces.push(adSpace)
+ this.data.admin.ad_space = spaces
+ this.data.ad_space_add = ""
+ }
+ },
+ removeAdSpace(ad){
+ let spaces = this.data.admin.ad_space
+ this.data.admin.ad_space = spaces.filter(s => s !== ad)
+ },
topupWallet: function () {
var self = this
LNbits.api
From 8c1c7d13b87ba7b7408dccd719a9a9c66e6e4325 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Fri, 18 Mar 2022 16:59:06 +0000
Subject: [PATCH 129/691] make it work from g()
---
lnbits/app.py | 34 +++---
lnbits/config.py | 62 ++++++++++
lnbits/extensions/admin/crud.py | 2 +-
lnbits/extensions/admin/migrations.py | 162 +++++++++++++++++---------
lnbits/extensions/admin/models.py | 27 +++--
lnbits/extensions/admin/views.py | 8 +-
lnbits/settings.py | 2 +-
7 files changed, 218 insertions(+), 79 deletions(-)
create mode 100644 lnbits/config.py
diff --git a/lnbits/app.py b/lnbits/app.py
index 7ff9e4eb..1ffedb54 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -19,6 +19,7 @@ import lnbits.settings
from lnbits.core.tasks import register_task_listeners
from .commands import get_admin_settings
+from .config import WALLET, conf
from .core import core_app
from .core.views.generic import core_html_routes
from .helpers import (
@@ -29,7 +30,8 @@ from .helpers import (
url_for_vendored,
)
from .requestvars import g
-from .settings import WALLET
+
+# from .settings import WALLET
from .tasks import (
catch_everything_and_restart,
check_pending_payments,
@@ -43,7 +45,6 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
"""Create application factory.
:param config_object: The configuration object to use.
"""
-<<<<<<< HEAD
configure_logger()
app = FastAPI(
@@ -55,20 +56,18 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
},
)
app.mount("/static", StaticFiles(packages=[("lnbits", "static")]), name="static")
-=======
- app = FastAPI()
-
- if lnbits.settings.LNBITS_ADMIN_UI:
- check_settings(app)
-
- app.mount("/static", StaticFiles(directory="lnbits/static"), name="static")
->>>>>>> e3a1b3ae (get admin settings at startup)
app.mount(
"/core/static",
StaticFiles(packages=[("lnbits.core", "static")]),
name="core_static",
)
+ if lnbits.settings.LNBITS_ADMIN_UI:
+ g().admin_conf = conf
+ check_settings(app)
+
+ g().WALLET = WALLET
+
origins = ["*"]
app.add_middleware(
@@ -109,18 +108,27 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
return app
-
def check_settings(app: FastAPI):
@app.on_event("startup")
async def check_settings_admin():
+
+ def removeEmptyString(arr):
+ return list(filter(None, arr))
+
while True:
admin_set = await get_admin_settings()
if admin_set :
break
print("ERROR:", admin_set)
await asyncio.sleep(5)
- # admin_set = await get_admin_settings()
- g().admin_conf = admin_set
+
+ admin_set.admin_users = removeEmptyString(admin_set.admin_users.split(','))
+ admin_set.allowed_users = removeEmptyString(admin_set.allowed_users.split(','))
+ admin_set.admin_ext = removeEmptyString(admin_set.admin_ext.split(','))
+ admin_set.disabled_ext = removeEmptyString(admin_set.disabled_ext.split(','))
+ admin_set.theme = removeEmptyString(admin_set.theme.split(','))
+ admin_set.ad_space = removeEmptyString(admin_set.ad_space.split(','))
+ g().admin_conf = conf.copy(update=admin_set.dict())
def check_funding_source(app: FastAPI) -> None:
@app.on_event("startup")
diff --git a/lnbits/config.py b/lnbits/config.py
new file mode 100644
index 00000000..02e8cf53
--- /dev/null
+++ b/lnbits/config.py
@@ -0,0 +1,62 @@
+import importlib
+import json
+from os import getenv, path
+from typing import List, Optional
+
+from pydantic import BaseSettings, Field, validator
+
+wallets_module = importlib.import_module("lnbits.wallets")
+wallet_class = getattr(
+ wallets_module, getenv("LNBITS_BACKEND_WALLET_CLASS", "VoidWallet")
+)
+
+WALLET = wallet_class()
+
+def list_parse_fallback(v):
+ try:
+ return json.loads(v)
+ except Exception as e:
+ return v.replace(' ','').split(',')
+
+class Settings(BaseSettings):
+ # users
+ admin_users: List[str] = Field(default_factory=list, env="LNBITS_ADMIN_USERS")
+ allowed_users: List[str] = Field(default_factory=list, env="LNBITS_ALLOWED_USERS")
+ admin_ext: List[str] = Field(default_factory=list, env="LNBITS_ADMIN_EXTENSIONS")
+ disabled_ext: List[str] = Field(default_factory=list, env="LNBITS_DISABLED_EXTENSIONS")
+ funding_source: str = Field(default="VoidWallet", env="LNBITS_BACKEND_WALLET_CLASS")
+ # ops
+ data_folder: str = Field(default=None, env="LNBITS_DATA_FOLDER")
+ database_url: str = Field(default=None, env="LNBITS_DATABASE_URL")
+ force_https: bool = Field(default=True, env="LNBITS_FORCE_HTTPS")
+ service_fee: float = Field(default=0, env="LNBITS_SERVICE_FEE")
+ hide_api: bool = Field(default=False, env="LNBITS_HIDE_API")
+ denomination: str = Field(default="sats", env="LNBITS_DENOMINATION")
+ # Change theme
+ site_title: str = Field(default=None, env="LNBITS_SITE_TITLE")
+ site_tagline: str = Field(default=None, env="LNBITS_SITE_TAGLINE")
+ site_description: str = Field(default=None, env="LNBITS_SITE_DESCRIPTION")
+ default_wallet_name: str = Field(default=None, env="LNBITS_DEFAULT_WALLET_NAME")
+ theme: List[str] = Field(default="classic, flamingo, mint, salvador, monochrome, autumn", env="LNBITS_THEME_OPTIONS")
+ ad_space: List[str] = Field(default_factory=list, env="LNBITS_AD_SPACE")
+ # .env
+ env: Optional[str]
+ debug: Optional[str]
+ host: Optional[str]
+ port: Optional[str]
+ lnbits_path: Optional[str] = path.dirname(path.realpath(__file__))
+
+ # @validator('admin_users', 'allowed_users', 'admin_ext', 'disabled_ext', pre=True)
+ # def validate(cls, val):
+ # print(val)
+ # return val.split(',')
+
+ class Config:
+ env_file = ".env"
+ env_file_encoding = "utf-8"
+ case_sensitive = False
+ json_loads = list_parse_fallback
+
+
+conf = Settings()
+WALLET = wallet_class()
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index 872d6c97..6fccb8ee 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -40,7 +40,7 @@ async def update_admin(user: str, **kwargs) -> Admin:
# new_settings = await get_admin()
# return new_settings
-async def get_admin() -> List[Admin]:
+async def get_admin() -> Admin:
row = await db.fetchone("SELECT * FROM admin")
return Admin(**row) if row else None
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 13b76923..574f772d 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -2,93 +2,151 @@ from os import getenv
from sqlalchemy.exc import OperationalError # type: ignore
+from lnbits.config import conf
from lnbits.helpers import urlsafe_short_hash
async def m001_create_admin_table(db):
- user = None
- site_title = None
- site_tagline = None
- site_description = None
- allowed_users = None
- admin_users = None
- default_wallet_name = None
- data_folder = None
- disabled_ext = None
- force_https = True
- service_fee = 0
- funding_source = ""
+ # users/server
+ user = conf.admin_users[0]
+ admin_users = ",".join(conf.admin_users)
+ allowed_users = ",".join(conf.allowed_users)
+ admin_ext = ",".join(conf.admin_ext)
+ disabled_ext = ",".join(conf.disabled_ext)
+ funding_source = conf.funding_source
+ #operational
+ data_folder = conf.data_folder
+ database_url = conf.database_url
+ force_https = conf.force_https
+ service_fee = conf.service_fee
+ hide_api = conf.hide_api
+ denomination = conf.denomination
+ # Theme'ing
+ site_title = conf.site_title
+ site_tagline = conf.site_tagline
+ site_description = conf.site_description
+ default_wallet_name = conf.default_wallet_name
+ theme = ",".join(conf.theme)
+ ad_space = ",".join(conf.ad_space)
- if getenv("LNBITS_SITE_TITLE"):
- site_title = getenv("LNBITS_SITE_TITLE")
+ # if getenv("LNBITS_ADMIN_EXTENSIONS"):
+ # admin_ext = getenv("LNBITS_ADMIN_EXTENSIONS")
- if getenv("LNBITS_SITE_TAGLINE"):
- site_tagline = getenv("LNBITS_SITE_TAGLINE")
+ # if getenv("LNBITS_DATABASE_URL"):
+ # database_url = getenv("LNBITS_DATABASE_URL")
- if getenv("LNBITS_SITE_DESCRIPTION"):
- site_description = getenv("LNBITS_SITE_DESCRIPTION")
+ # if getenv("LNBITS_HIDE_API"):
+ # hide_api = getenv("LNBITS_HIDE_API")
- if getenv("LNBITS_ALLOWED_USERS"):
- allowed_users = getenv("LNBITS_ALLOWED_USERS")
+ # if getenv("LNBITS_THEME_OPTIONS"):
+ # theme = getenv("LNBITS_THEME_OPTIONS")
- if getenv("LNBITS_ADMIN_USERS"):
- admin_users = "".join(getenv("LNBITS_ADMIN_USERS").split())
- user = admin_users.split(',')[0]
+ # if getenv("LNBITS_AD_SPACE"):
+ # ad_space = getenv("LNBITS_AD_SPACE")
- if getenv("LNBITS_DEFAULT_WALLET_NAME"):
- default_wallet_name = getenv("LNBITS_DEFAULT_WALLET_NAME")
+ # if getenv("LNBITS_SITE_TITLE"):
+ # site_title = getenv("LNBITS_SITE_TITLE")
- if getenv("LNBITS_DATA_FOLDER"):
- data_folder = getenv("LNBITS_DATA_FOLDER")
+ # if getenv("LNBITS_SITE_TAGLINE"):
+ # site_tagline = getenv("LNBITS_SITE_TAGLINE")
- if getenv("LNBITS_DISABLED_EXTENSIONS"):
- disabled_ext = getenv("LNBITS_DISABLED_EXTENSIONS")
+ # if getenv("LNBITS_SITE_DESCRIPTION"):
+ # site_description = getenv("LNBITS_SITE_DESCRIPTION")
- if getenv("LNBITS_FORCE_HTTPS"):
- force_https = getenv("LNBITS_FORCE_HTTPS")
+ # if getenv("LNBITS_ALLOWED_USERS"):
+ # allowed_users = getenv("LNBITS_ALLOWED_USERS")
- if getenv("LNBITS_SERVICE_FEE"):
- service_fee = getenv("LNBITS_SERVICE_FEE")
+ # if getenv("LNBITS_ADMIN_USERS"):
+ # admin_users = "".join(getenv("LNBITS_ADMIN_USERS").split())
+ # user = admin_users.split(',')[0]
+
+ # if getenv("LNBITS_DEFAULT_WALLET_NAME"):
+ # default_wallet_name = getenv("LNBITS_DEFAULT_WALLET_NAME")
- if getenv("LNBITS_BACKEND_WALLET_CLASS"):
- funding_source = getenv("LNBITS_BACKEND_WALLET_CLASS")
+ # if getenv("LNBITS_DATA_FOLDER"):
+ # data_folder = getenv("LNBITS_DATA_FOLDER")
+
+ # if getenv("LNBITS_DISABLED_EXTENSIONS"):
+ # disabled_ext = getenv("LNBITS_DISABLED_EXTENSIONS")
+
+ # if getenv("LNBITS_FORCE_HTTPS"):
+ # force_https = getenv("LNBITS_FORCE_HTTPS")
+
+ # if getenv("LNBITS_SERVICE_FEE"):
+ # service_fee = getenv("LNBITS_SERVICE_FEE")
+
+ # if getenv("LNBITS_DENOMINATION"):
+ # denomination = getenv("LNBITS_DENOMINATION", "sats")
+
+ # if getenv("LNBITS_BACKEND_WALLET_CLASS"):
+ # funding_source = getenv("LNBITS_BACKEND_WALLET_CLASS")
await db.execute(
"""
CREATE TABLE IF NOT EXISTS admin (
- "user" TEXT,
+ "user" TEXT PRIMARY KEY,
+ admin_users TEXT,
+ allowed_users TEXT,
+ admin_ext TEXT,
+ disabled_ext TEXT,
+ funding_source TEXT,
+ data_folder TEXT,
+ database_url TEXT,
+ force_https BOOLEAN,
+ service_fee REAL,
+ hide_api BOOLEAN,
+ denomination TEXT,
site_title TEXT,
site_tagline TEXT,
site_description TEXT,
- admin_users TEXT,
- allowed_users TEXT,
default_wallet_name TEXT,
- data_folder TEXT,
- disabled_ext TEXT,
- force_https BOOLEAN,
- service_fee REAL,
- funding_source TEXT
+ theme TEXT,
+ ad_space TEXT
);
"""
)
await db.execute(
"""
- INSERT INTO admin ("user", site_title, site_tagline, site_description, admin_users, allowed_users, default_wallet_name, data_folder, disabled_ext, force_https, service_fee, funding_source)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- """,
- (
- user.strip(),
+ INSERT INTO admin (
+ "user",
+ admin_users,
+ allowed_users,
+ admin_ext,
+ disabled_ext,
+ funding_source,
+ data_folder,
+ database_url,
+ force_https,
+ service_fee,
+ hide_api,
+ denomination,
site_title,
site_tagline,
site_description,
- admin_users[1:],
- allowed_users,
default_wallet_name,
- data_folder,
+ theme,
+ ad_space)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ """,
+ (
+ user,
+ admin_users,
+ allowed_users,
+ admin_ext,
disabled_ext,
+ funding_source,
+ data_folder,
+ database_url,
force_https,
service_fee,
- funding_source,
+ hide_api,
+ denomination,
+ site_title,
+ site_tagline,
+ site_description,
+ default_wallet_name,
+ theme,
+ ad_space,
),
)
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 4080ff01..f7c64de5 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -2,7 +2,7 @@ from sqlite3 import Row
from typing import List, Optional
from fastapi import Query
-from pydantic import BaseModel
+from pydantic import BaseModel, Field
class UpdateAdminSettings(BaseModel):
@@ -19,18 +19,27 @@ class UpdateAdminSettings(BaseModel):
funding_source: Optional[str]
class Admin(BaseModel):
+ # users
user: str
+ admin_users: Optional[str]
+ allowed_users: Optional[str]
+ admin_ext: Optional[str]
+ disabled_ext: Optional[str]
+ funding_source: Optional[str]
+ # ops
+ data_folder: Optional[str]
+ database_url: Optional[str]
+ force_https: bool = Field(default=True)
+ service_fee: float = Field(default=0)
+ hide_api: bool = Field(default=False)
+ # Change theme
site_title: Optional[str]
site_tagline: Optional[str]
site_description: Optional[str]
- allowed_users: Optional[str]
- admin_users: str
- default_wallet_name: str
- data_folder: str
- disabled_ext: str
- force_https: Optional[bool] = Query(True)
- service_fee: float
- funding_source: str
+ default_wallet_name: Optional[str]
+ denomination: str = Field(default="sats")
+ theme: Optional[str]
+ ad_space: Optional[str]
@classmethod
def from_row(cls, row: Row) -> "Admin":
diff --git a/lnbits/extensions/admin/views.py b/lnbits/extensions/admin/views.py
index 00a0c99f..105f05a1 100644
--- a/lnbits/extensions/admin/views.py
+++ b/lnbits/extensions/admin/views.py
@@ -19,15 +19,17 @@ templates = Jinja2Templates(directory="templates")
@admin_ext.get("/", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_user_exists)):
admin = await get_admin()
- print(g())
funding = [f.dict() for f in await get_funding()]
-
+ error, balance = await g().WALLET.status()
print("ADMIN", admin.dict())
+ print(g().admin_conf)
return admin_renderer().TemplateResponse(
"admin/index.html", {
"request": request,
"user": user.dict(),
"admin": admin.dict(),
- "funding": funding
+ "funding": funding,
+ "settings": g().admin_conf.dict(),
+ "balance": balance
}
)
diff --git a/lnbits/settings.py b/lnbits/settings.py
index 43cb87cb..ed5c77f7 100644
--- a/lnbits/settings.py
+++ b/lnbits/settings.py
@@ -4,7 +4,7 @@ from email.policy import default
from os import path
from typing import List
-from environs import Env # type: ignore
+from environs import Env
env = Env()
env.read_env()
From a72ed98997656a709b00d171c27c387c26dfe0bd Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 10:28:07 +0000
Subject: [PATCH 130/691] topup wallet endpoint
---
lnbits/extensions/admin/crud.py | 13 +++++++++----
1 file changed, 9 insertions(+), 4 deletions(-)
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index 6fccb8ee..683558f9 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -1,26 +1,31 @@
+import json
from typing import List, Optional
from lnbits.core.crud import create_payment
from lnbits.helpers import urlsafe_short_hash
from lnbits.settings import *
+from lnbits.tasks import internal_invoice_queue
from . import db
from .models import Admin, Funding
-def update_wallet_balance(wallet_id: str, amount: int) -> str:
+async def update_wallet_balance(wallet_id: str, amount: int) -> str:
temp_id = f"temp_{urlsafe_short_hash()}"
internal_id = f"internal_{urlsafe_short_hash()}"
- create_payment(
+
+ payment = await create_payment(
wallet_id=wallet_id,
checking_id=internal_id,
payment_request="admin_internal",
payment_hash="admin_internal",
- amount=amount * 1000,
+ amount=amount*1000,
memo="Admin top up",
pending=False,
)
- return "success"
+ # manually send this for now
+ await internal_invoice_queue.put(internal_id)
+ return payment
async def update_admin(user: str, **kwargs) -> Admin:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
From 42a9af986ab3620bdb61270961c6adbda4a66c95 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 10:28:44 +0000
Subject: [PATCH 131/691] update admin settings in db
---
lnbits/extensions/admin/models.py | 29 +++++++++++++++++-----------
lnbits/extensions/admin/views_api.py | 8 ++++----
2 files changed, 22 insertions(+), 15 deletions(-)
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index f7c64de5..36d9b815 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -6,17 +6,24 @@ from pydantic import BaseModel, Field
class UpdateAdminSettings(BaseModel):
- site_title: Optional[str]
- site_tagline: Optional[str]
- site_description: Optional[str]
- allowed_users: Optional[str]
- admin_users: Optional[str]
- default_wallet_name: Optional[str]
- data_folder: Optional[str]
- disabled_ext: Optional[str]
- force_https: Optional[bool]
- service_fee: Optional[float]
- funding_source: Optional[str]
+ # users
+ admin_users: str = Query(None)
+ allowed_users: str = Query(None)
+ admin_ext: str = Query(None)
+ disabled_ext: str = Query(None)
+ funding_source: str = Query(None)
+ # ops
+ force_https: bool = Query(None)
+ service_fee: float = Query(None, ge=0)
+ hide_api: bool = Query(None)
+ # Change theme
+ site_title: str = Query(None)
+ site_tagline: str = Query(None)
+ site_description: str = Query(None)
+ default_wallet_name: str = Query(None)
+ denomination: str = Query(None)
+ theme: str = Query(None)
+ ad_space: str = Query(None)
class Admin(BaseModel):
# users
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index b2c65be2..cb526aa5 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -12,16 +12,16 @@ from .crud import get_admin, update_admin, update_wallet_balance
@admin_ext.get("/api/v1/admin/{wallet_id}/{topup_amount}", status_code=HTTPStatus.OK)
-async def api_update_balance(wallet_id, topup_amount, g: WalletTypeInfo = Depends(require_admin_key)):
- print(g.wallet)
+async def api_update_balance(wallet_id, topup_amount: int, g: WalletTypeInfo = Depends(require_admin_key)):
try:
wallet = await get_wallet(wallet_id)
except:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
)
- print(wallet)
- print(topup_amount)
+
+ await update_wallet_balance(wallet_id=wallet_id, amount=int(topup_amount))
+
return {"status": "Success"}
From 2ebb4448d5ff8daa3b1c4729ce33dd4c5c744c7b Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 10:29:18 +0000
Subject: [PATCH 132/691] update settings and topup logic
---
.../admin/templates/admin/index.html | 91 ++++++++++++-------
1 file changed, 57 insertions(+), 34 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 65ac9f33..e9ddc7c4 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -30,7 +30,7 @@
-
+
@@ -61,7 +61,7 @@
@@ -577,7 +577,6 @@
Site Description
s !== ad)
},
- topupWallet: function () {
- var self = this
+ topupWallet() {
LNbits.api
.request(
'GET',
'/admin/api/v1/admin/' +
- self.wallet.id +
+ this.wallet.data.id +
'/' +
- self.wallet.data.amount,
- self.g.user.wallets[0].adminkey
+ this.wallet.data.amount,
+ this.g.user.wallets[0].adminkey
)
- .then(function (response) {
- self.$q.notify({
+ .then((response) => {
+ this.$q.notify({
type: 'positive',
message:
- 'Success! Added ' +
- self.wallet.amount +
- ' to ' +
- self.wallet.id,
+ 'Success! Added ' +
+ this.wallet.data.amount +
+ ' to ' +
+ this.wallet.data.id,
icon: null
})
+ this.wallet.data = {}
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
@@ -1224,36 +1224,59 @@
self.data.admin.edited.push(source)
console.log(self.data.admin.edited)
},
- UpdateLNbits: function () {
- var self = this
- let {site_title, admin_users, default_wallet_name, data_folder, disabled_ext, service_fee, funding_source_primary} = this.data.admin
+ UpdateLNbits() {
+ let {
+ admin_users,
+ allowed_users,
+ admin_ext,
+ disabled_ext,
+ funding_source,
+ force_https,
+ service_fee,
+ hide_api,
+ site_title,
+ site_tagline,
+ site_description,
+ default_wallet_name,
+ denomination,
+ theme,
+ ad_space
+ } = this.data.admin
+ //console.log("this", this.data.admin)
let data = {
- site_title,
- site_tagline: this.data.admin.tagline,
- site_description: this.data.admin.description,
- admin_users: admin_users.toString(),
- default_wallet_name,
- data_folder,
+ admin_users: admin_users.toString(),
+ allowed_users: allowed_users.toString(),
+ admin_ext: admin_ext.toString(),
disabled_ext: disabled_ext.toString(),
- service_fee,
- funding_source: funding_source_primary}
+ funding_source,
+ force_https,
+ service_fee,
+ hide_api,
+ site_title,
+ site_tagline,
+ site_description,
+ default_wallet_name,
+ denomination,
+ theme: theme.toString(),
+ ad_space: ad_space.toString()
+ }
console.log(data)
LNbits.api
.request(
'POST',
'/admin/api/v1/admin/',
- self.g.user.wallets[0].adminkey,
+ this.g.user.wallets[0].adminkey,
data
)
- .then(function (response) {
+ .then(response => {
console.log(response.data)
- self.$q.notify({
+ this.$q.notify({
type: 'positive',
message:
'Success! Added ' +
- self.wallet.amount +
+ this.wallet.amount +
' to ' +
- self.wallet.id,
+ this.wallet.id,
icon: null
})
})
From 3082a393436b88a24d860f87983560e758a02f66 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 11:34:47 +0000
Subject: [PATCH 133/691] make removeEmptyString fn as helper fn
---
lnbits/app.py | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 1ffedb54..c8f5c60a 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -26,6 +26,7 @@ from .helpers import (
get_css_vendored,
get_js_vendored,
get_valid_extensions,
+ removeEmptyString,
template_renderer,
url_for_vendored,
)
@@ -112,9 +113,6 @@ def check_settings(app: FastAPI):
@app.on_event("startup")
async def check_settings_admin():
- def removeEmptyString(arr):
- return list(filter(None, arr))
-
while True:
admin_set = await get_admin_settings()
if admin_set :
From c419bd27ebcd212da37f27994e630df08bdba7d4 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 11:35:15 +0000
Subject: [PATCH 134/691] add some defaults
---
lnbits/config.py | 6 +++---
lnbits/extensions/admin/models.py | 8 ++++----
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/lnbits/config.py b/lnbits/config.py
index 02e8cf53..b2fbfff1 100644
--- a/lnbits/config.py
+++ b/lnbits/config.py
@@ -33,10 +33,10 @@ class Settings(BaseSettings):
hide_api: bool = Field(default=False, env="LNBITS_HIDE_API")
denomination: str = Field(default="sats", env="LNBITS_DENOMINATION")
# Change theme
- site_title: str = Field(default=None, env="LNBITS_SITE_TITLE")
- site_tagline: str = Field(default=None, env="LNBITS_SITE_TAGLINE")
+ site_title: str = Field(default="LNbits", env="LNBITS_SITE_TITLE")
+ site_tagline: str = Field(default="free and open-source lightning wallet", env="LNBITS_SITE_TAGLINE")
site_description: str = Field(default=None, env="LNBITS_SITE_DESCRIPTION")
- default_wallet_name: str = Field(default=None, env="LNBITS_DEFAULT_WALLET_NAME")
+ default_wallet_name: str = Field(default="LNbits wallet", env="LNBITS_DEFAULT_WALLET_NAME")
theme: List[str] = Field(default="classic, flamingo, mint, salvador, monochrome, autumn", env="LNBITS_THEME_OPTIONS")
ad_space: List[str] = Field(default_factory=list, env="LNBITS_AD_SPACE")
# .env
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 36d9b815..0f25679d 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -17,11 +17,11 @@ class UpdateAdminSettings(BaseModel):
service_fee: float = Query(None, ge=0)
hide_api: bool = Query(None)
# Change theme
- site_title: str = Query(None)
- site_tagline: str = Query(None)
+ site_title: str = Query("LNbits")
+ site_tagline: str = Query("free and open-source lightning wallet")
site_description: str = Query(None)
- default_wallet_name: str = Query(None)
- denomination: str = Query(None)
+ default_wallet_name: str = Query("LNbits wallet")
+ denomination: str = Query("sats")
theme: str = Query(None)
ad_space: str = Query(None)
From 0897d0476356d1956711fc0f1c6448fbb88275fb Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 11:36:04 +0000
Subject: [PATCH 135/691] removeEmtpy sting as helper fn
---
lnbits/helpers.py | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/lnbits/helpers.py b/lnbits/helpers.py
index e213240c..e456f715 100644
--- a/lnbits/helpers.py
+++ b/lnbits/helpers.py
@@ -154,8 +154,20 @@ def url_for(endpoint: str, external: Optional[bool] = False, **params: Any) -> s
url = f"{base}{endpoint}{url_params}"
return url
+def removeEmptyString(arr):
+ return list(filter(None, arr))
def template_renderer(additional_folders: List = []) -> Jinja2Templates:
+ if(settings.LNBITS_ADMIN_UI):
+ _ = g().admin_conf
+ settings.LNBITS_AD_SPACE = _.ad_space
+ settings.LNBITS_HIDE_API = _.hide_api
+ settings.LNBITS_SITE_TITLE = _.site_title
+ settings.LNBITS_DENOMINATION = _.denomination
+ settings.LNBITS_SITE_TAGLINE = _.site_tagline
+ settings.LNBITS_SITE_DESCRIPTION = _.site_description
+ settings.LNBITS_THEME_OPTIONS = _.theme
+
t = Jinja2Templates(
loader=jinja2.FileSystemLoader(
["lnbits/templates", "lnbits/core/templates", *additional_folders]
From 8c93aa304f0d484e908cd40c0a851b95fbbfd992 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 11:41:11 +0000
Subject: [PATCH 136/691] cleanup
---
lnbits/extensions/admin/crud.py | 12 +-----------
1 file changed, 1 insertion(+), 11 deletions(-)
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index 683558f9..e14ad194 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -1,9 +1,7 @@
-import json
-from typing import List, Optional
+from typing import List
from lnbits.core.crud import create_payment
from lnbits.helpers import urlsafe_short_hash
-from lnbits.settings import *
from lnbits.tasks import internal_invoice_queue
from . import db
@@ -37,14 +35,6 @@ async def update_admin(user: str, **kwargs) -> Admin:
assert row, "Newly updated settings couldn't be retrieved"
return Admin(**row) if row else None
-# async def update_admin(user: str, **kwargs) -> Optional[Admin]:
-# q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
-# await db.execute(
-# f"UPDATE admin SET {q} WHERE user = ?", (*kwargs.values(), user)
-# )
-# new_settings = await get_admin()
-# return new_settings
-
async def get_admin() -> Admin:
row = await db.fetchone("SELECT * FROM admin")
return Admin(**row) if row else None
From 5ce73697d47aa6eb96bb6d69c7da1e4521bc4943 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 11:42:28 +0000
Subject: [PATCH 137/691] make string to list
---
lnbits/extensions/admin/views_api.py | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index cb526aa5..1d4e6a9c 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -1,5 +1,6 @@
from http import HTTPStatus
+# from config import conf
from fastapi import Body, Depends, Request
from starlette.exceptions import HTTPException
@@ -7,6 +8,8 @@ from lnbits.core.crud import get_wallet
from lnbits.decorators import WalletTypeInfo, require_admin_key
from lnbits.extensions.admin import admin_ext
from lnbits.extensions.admin.models import Admin, UpdateAdminSettings
+from lnbits.helpers import removeEmptyString
+from lnbits.requestvars import g
from .crud import get_admin, update_admin, update_wallet_balance
@@ -19,7 +22,7 @@ async def api_update_balance(wallet_id, topup_amount: int, g: WalletTypeInfo = D
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
)
-
+
await update_wallet_balance(wallet_id=wallet_id, amount=int(topup_amount))
return {"status": "Success"}
@@ -29,14 +32,24 @@ async def api_update_balance(wallet_id, topup_amount: int, g: WalletTypeInfo = D
async def api_update_admin(
request: Request,
data: UpdateAdminSettings = Body(...),
- g: WalletTypeInfo = Depends(require_admin_key)
+ w: WalletTypeInfo = Depends(require_admin_key)
):
admin = await get_admin()
print(data)
- if not admin.user == g.wallet.user:
+ if not admin.user == w.wallet.user:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
)
- updated = await update_admin(user=g.wallet.user, **data.dict())
- print(updated)
+ updated = await update_admin(user=w.wallet.user, **data.dict())
+
+ updated.admin_users = removeEmptyString(updated.admin_users.split(','))
+ updated.allowed_users = removeEmptyString(updated.allowed_users.split(','))
+ updated.admin_ext = removeEmptyString(updated.admin_ext.split(','))
+ updated.disabled_ext = removeEmptyString(updated.disabled_ext.split(','))
+ updated.theme = removeEmptyString(updated.theme.split(','))
+ updated.ad_space = removeEmptyString(updated.ad_space.split(','))
+
+ g().admin_conf = g().admin_conf.copy(update=updated.dict())
+
+ print(g().admin_conf)
return {"status": "Success"}
From c299927e7ca1e16c8bc29a98b5af38ed402496de Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 22 Mar 2022 11:42:47 +0000
Subject: [PATCH 138/691] success message
---
lnbits/extensions/admin/templates/admin/index.html | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index e9ddc7c4..9aa4f12a 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -1273,10 +1273,7 @@
this.$q.notify({
type: 'positive',
message:
- 'Success! Added ' +
- this.wallet.amount +
- ' to ' +
- this.wallet.id,
+ 'Success! Settings changed!',
icon: null
})
})
From 2a63fb191423b2f23de7f70e8197109a290f3689 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Thu, 14 Apr 2022 10:42:26 +0100
Subject: [PATCH 139/691] allow html to be passed to description
---
lnbits/core/templates/core/index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lnbits/core/templates/core/index.html b/lnbits/core/templates/core/index.html
index 68a7b7ed..146fc6ad 100644
--- a/lnbits/core/templates/core/index.html
+++ b/lnbits/core/templates/core/index.html
@@ -82,7 +82,7 @@
>
-
{{SITE_DESCRIPTION}}
+
{{SITE_DESCRIPTION | safe}}
From 3fbdac127adf9459d8af4453a802248f7c3d94fc Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Thu, 14 Apr 2022 16:37:13 +0100
Subject: [PATCH 140/691] update funding wallets
---
lnbits/extensions/admin/crud.py | 12 +
.../admin/templates/admin/index.html | 523 ++++++++++--------
lnbits/extensions/admin/views.py | 3 +-
lnbits/extensions/admin/views_api.py | 19 +-
4 files changed, 315 insertions(+), 242 deletions(-)
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index e14ad194..dd39e8e4 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -39,6 +39,18 @@ async def get_admin() -> Admin:
row = await db.fetchone("SELECT * FROM admin")
return Admin(**row) if row else None
+async def update_funding(data: Funding) -> Funding:
+ await db.execute(
+ """
+ UPDATE funding
+ SET backend_wallet = ?, endpoint = ?, port = ?, read_key = ?, invoice_key = ?, admin_key = ?, cert = ?, balance = ?, selected = ?
+ WHERE id = ?
+ """,
+ (data.backend_wallet, data.endpoint, data.port, data.read_key, data.invoice_key, data.admin_key, data.cert, data.balance, data.selected, data.id,),
+ )
+ row = await db.fetchone('SELECT * FROM funding WHERE "id" = ?', (data.id,))
+ assert row, "Newly updated settings couldn't be retrieved"
+ return Funding(**row) if row else None
async def get_funding() -> List[Funding]:
rows = await db.fetchall("SELECT * FROM funding")
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 9aa4f12a..d56b3d79 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -31,11 +31,11 @@
-
-
-
- Wallets Management
-
+
+
+
+ Wallets Management
+
@@ -62,43 +62,96 @@
-
TopUp a wallet
-
-
-
-
-
-
-
-
+
TopUp a wallet
+
Funding Sources
-
+ {% raw %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% endraw %}
+
+
+
+
+
+
+ User Management
+
+
+ Super Admin: {% raw %}{{this.data.admin.user}}{% endraw %}
+
+
Admin Users
+ hint="Users with admin privileges"
+ >
{% raw %}
-
-
-
- {% raw %}
-
Allowed Users
+
- {{ user }}
-
- {% endraw %}
+
+
+
+ {% raw %}
+
+ {{ user }}
+
+ {% endraw %}
+
+
+
+
+
+
Disabled Extensions
+
+
+
+
+
+ Save
+
+
+
+
+
+ Server Management
-
-
-
-
-
Disabled Extensions
-
-
-
-
-
- Save
-
-
-
-
-
- Server Management
-
Server Info
{%raw%}
- - SQlite: {{data.admin.data_folder}}
- - Postgres: {{data.admin.database_url}}
+ -
+ SQlite: {{data.admin.data_folder}}
+
+ -
+ Postgres: {{data.admin.database_url}}
+
{%endraw%}
@@ -520,7 +576,10 @@
Hide API
- Hides wallet api, extensions can choose to honor
+ Hides wallet api, extensions can choose to
+ honor
-
-
-
- Save
-
-
-
-
-
- UI Management
-
+
+
+
+ Save
+
+
+
+
+
+ UI Management
+
+
Default Wallet Name
@@ -628,12 +682,15 @@
@keydown.enter="addAdSpace"
type="text"
label="Ad image URL"
- hint="Ad image filepaths or urls, extensions can choose to honor">
+ hint="Ad image filepaths or urls, extensions can choose to honor"
+ >
{% raw %}
-
-
-
-
- Save
-
-
-
-
-
+
+
+
+ Save
+
+
+
+
+
-
-
-Admin
-
+
+
-
-
-
-
- Wallet topup
-
-
-
-
-
-
-
{% endblock %} {% block scripts %} {{ window_vars(user) }}
@@ -1100,14 +1114,22 @@
'LnbitsWallet',
'OpenNodeWallet'
],
-
+
admin: {
edited: [],
- funding: {},
+ funding: [],
senddata: {}
}
},
- themes: ['classic', 'bitcoin', 'flamingo', 'mint', 'autumn', 'monochrome', 'salvador'],
+ themes: [
+ 'classic',
+ 'bitcoin',
+ 'flamingo',
+ 'mint',
+ 'autumn',
+ 'monochrome',
+ 'salvador'
+ ],
options: [
'bleskomat',
'captcha',
@@ -1139,10 +1161,13 @@
self.cancel.on = true
}
funding = JSON.parse(String('{{ funding | tojson|safe }}'))
- var i
+ funding.map(f => {
+ this.data.admin.funding.push(f)
+ })
+ /*var i
for (i = 0; i < funding.length; i++) {
self.data.admin.funding[funding[i].backend_wallet] = funding[i]
- }
+ }*/
let settings = JSON.parse('{{ settings | tojson|safe }}')
settings.balance = '{{ balance }}'
this.data.admin = {...this.data.admin, ...settings}
@@ -1150,42 +1175,42 @@
console.log(settings)
},
methods: {
- addAdminUser(){
+ addAdminUser() {
let addUser = this.data.admin_users_add
let admin_users = this.data.admin.admin_users
- if(addUser.length && !admin_users.includes(addUser)){
+ if (addUser.length && !admin_users.includes(addUser)) {
admin_users.push(addUser)
this.data.admin.admin_users = admin_users
- this.data.admin_users_add = ""
+ this.data.admin_users_add = ''
}
},
- removeAdminUser(user){
+ removeAdminUser(user) {
let admin_users = this.data.admin.admin_users
this.data.admin.admin_users = admin_users.filter(u => u !== user)
},
- addAllowedUser(){
+ addAllowedUser() {
let addUser = this.data.allowed_users_add
let allowed_users = this.data.admin.allowed_users
- if(addUser.length && !allowed_users.includes(addUser)){
+ if (addUser.length && !allowed_users.includes(addUser)) {
allowed_users.push(addUser)
this.data.admin.allowed_users = allowed_users
- this.data.allowed_users_add = ""
+ this.data.allowed_users_add = ''
}
},
- removeAllowedUser(user){
+ removeAllowedUser(user) {
let allowed_users = this.data.admin.allowed_users
this.data.admin.allowed_users = allowed_users.filter(u => u !== user)
},
- addAdSpace(){
+ addAdSpace() {
let adSpace = this.data.ad_space_add
let spaces = this.data.admin.ad_space
- if(adSpace.length && !spaces.includes(adSpace)){
+ if (adSpace.length && !spaces.includes(adSpace)) {
spaces.push(adSpace)
this.data.admin.ad_space = spaces
- this.data.ad_space_add = ""
+ this.data.ad_space_add = ''
}
},
- removeAdSpace(ad){
+ removeAdSpace(ad) {
let spaces = this.data.admin.ad_space
this.data.admin.ad_space = spaces.filter(s => s !== ad)
},
@@ -1199,14 +1224,14 @@
this.wallet.data.amount,
this.g.user.wallets[0].adminkey
)
- .then((response) => {
+ .then(response => {
this.$q.notify({
type: 'positive',
message:
- 'Success! Added ' +
- this.wallet.data.amount +
- ' to ' +
- this.wallet.data.id,
+ 'Success! Added ' +
+ this.wallet.data.amount +
+ ' to ' +
+ this.wallet.data.id,
icon: null
})
this.wallet.data = {}
@@ -1224,6 +1249,29 @@
self.data.admin.edited.push(source)
console.log(self.data.admin.edited)
},
+ updateFunding(fund) {
+ let data = this.data.admin.funding.find(v => v.backend_wallet == fund)
+
+ LNbits.api
+ .request(
+ 'POST',
+ '/admin/api/v1/admin/funding',
+ this.g.user.wallets[0].adminkey,
+ data
+ )
+ .then(response => {
+ //let wallet = response.data.backend_wallet
+ //this.data.admin.funding[wallet] = response.data
+ //this.data.admin.funding[wallet].endpoint = response.data.endpoint
+ //console.log(this.data.admin.funding)
+ //console.log(this.data.admin)
+ this.$q.notify({
+ type: 'positive',
+ message: `Success! ${response.data.backend_wallet} changed!`,
+ icon: null
+ })
+ })
+ },
UpdateLNbits() {
let {
admin_users,
@@ -1272,8 +1320,7 @@
console.log(response.data)
this.$q.notify({
type: 'positive',
- message:
- 'Success! Settings changed!',
+ message: 'Success! Settings changed!',
icon: null
})
})
diff --git a/lnbits/extensions/admin/views.py b/lnbits/extensions/admin/views.py
index 105f05a1..24b8ca85 100644
--- a/lnbits/extensions/admin/views.py
+++ b/lnbits/extensions/admin/views.py
@@ -21,8 +21,7 @@ async def index(request: Request, user: User = Depends(check_user_exists)):
admin = await get_admin()
funding = [f.dict() for f in await get_funding()]
error, balance = await g().WALLET.status()
- print("ADMIN", admin.dict())
- print(g().admin_conf)
+
return admin_renderer().TemplateResponse(
"admin/index.html", {
"request": request,
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index 1d4e6a9c..b797dc2d 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -7,11 +7,11 @@ from starlette.exceptions import HTTPException
from lnbits.core.crud import get_wallet
from lnbits.decorators import WalletTypeInfo, require_admin_key
from lnbits.extensions.admin import admin_ext
-from lnbits.extensions.admin.models import Admin, UpdateAdminSettings
+from lnbits.extensions.admin.models import Admin, Funding, UpdateAdminSettings
from lnbits.helpers import removeEmptyString
from lnbits.requestvars import g
-from .crud import get_admin, update_admin, update_wallet_balance
+from .crud import get_admin, update_admin, update_funding, update_wallet_balance
@admin_ext.get("/api/v1/admin/{wallet_id}/{topup_amount}", status_code=HTTPStatus.OK)
@@ -53,3 +53,18 @@ async def api_update_admin(
print(g().admin_conf)
return {"status": "Success"}
+
+@admin_ext.post("/api/v1/admin/funding/", status_code=HTTPStatus.OK)
+async def api_update_funding(
+ request: Request,
+ data: Funding = Body(...),
+ w: WalletTypeInfo = Depends(require_admin_key)
+ ):
+ admin = await get_admin()
+
+ if not admin.user == w.wallet.user:
+ raise HTTPException(
+ status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
+ )
+ funding = await update_funding(data=data)
+ return funding
From a07fbf0187c72b45e0e102951faf3ed6cbfb75fc Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Mon, 18 Apr 2022 14:25:06 +0100
Subject: [PATCH 141/691] allow user settings without restart
---
lnbits/core/views/generic.py | 7 ++++++-
lnbits/decorators.py | 8 ++++++++
lnbits/helpers.py | 3 +++
3 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py
index 31a7b030..83648c44 100644
--- a/lnbits/core/views/generic.py
+++ b/lnbits/core/views/generic.py
@@ -15,7 +15,9 @@ from lnbits.core import db
from lnbits.core.models import User
from lnbits.decorators import check_user_exists
from lnbits.helpers import template_renderer, url_for
+from lnbits.requestvars import g
from lnbits.settings import (
+ LNBITS_ADMIN_UI,
LNBITS_ADMIN_USERS,
LNBITS_ALLOWED_USERS,
LNBITS_CUSTOM_LOGO,
@@ -37,7 +39,6 @@ from ..services import pay_invoice, redeem_lnurl_withdraw
core_html_routes: APIRouter = APIRouter(tags=["Core NON-API Website Routes"])
-
@core_html_routes.get("/favicon.ico", response_class=FileResponse)
async def favicon():
return FileResponse("lnbits/core/static/favicon.ico")
@@ -119,6 +120,10 @@ async def wallet(
wallet_name = nme
service_fee = int(SERVICE_FEE) if int(SERVICE_FEE) == SERVICE_FEE else SERVICE_FEE
+ if LNBITS_ADMIN_UI:
+ LNBITS_ADMIN_USERS = g().admin_conf.admin_users
+ LNBITS_ALLOWED_USERS = g().admin_conf.allowed_users
+
if not user_id:
user = await get_user((await create_account()).id)
logger.info(f"Create user {user.id}") # type: ignore
diff --git a/lnbits/decorators.py b/lnbits/decorators.py
index d4aa63ae..f951163f 100644
--- a/lnbits/decorators.py
+++ b/lnbits/decorators.py
@@ -16,6 +16,7 @@ from lnbits.core.models import User, Wallet
from lnbits.requestvars import g
from lnbits.settings import (
LNBITS_ADMIN_EXTENSIONS,
+ LNBITS_ADMIN_UI,
LNBITS_ADMIN_USERS,
LNBITS_ALLOWED_USERS,
)
@@ -138,6 +139,9 @@ async def get_key_type(
detail="Invoice (or Admin) key required.",
)
+ if LNBITS_ADMIN_UI:
+ LNBITS_ADMIN_USERS = g().admin_conf.admin_users
+
for typenr, WalletChecker in zip(
[0, 1], [WalletAdminKeyChecker, WalletInvoiceKeyChecker]
):
@@ -231,6 +235,10 @@ async def check_user_exists(usr: UUID4) -> User:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="User does not exist."
)
+
+ if LNBITS_ADMIN_UI:
+ LNBITS_ADMIN_USERS = g().admin_conf.admin_users
+ LNBITS_ALLOWED_USERS = g().admin_conf.allowed_users
if LNBITS_ALLOWED_USERS and g().user.id not in LNBITS_ALLOWED_USERS:
raise HTTPException(
diff --git a/lnbits/helpers.py b/lnbits/helpers.py
index e456f715..1167143f 100644
--- a/lnbits/helpers.py
+++ b/lnbits/helpers.py
@@ -24,6 +24,9 @@ class Extension(NamedTuple):
class ExtensionManager:
def __init__(self):
+ if settings.LNBITS_ADMIN_UI:
+ settings.LNBITS_DISABLED_EXTENSIONS = g().admin_conf.disabled_ext
+ settings.LNBITS_ADMIN_EXTENSIONS = g().admin_conf.admin_ext
self._disabled: List[str] = settings.LNBITS_DISABLED_EXTENSIONS
self._admin_only: List[str] = [
x.strip(" ") for x in settings.LNBITS_ADMIN_EXTENSIONS
From 931286b476bed767e3900a3b60cf10ab962c29e1 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Mon, 18 Apr 2022 14:25:26 +0100
Subject: [PATCH 142/691] advert for server restart option
---
lnbits/extensions/admin/templates/admin/index.html | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index d56b3d79..089c5f1c 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -51,7 +51,9 @@
-
Active Funding
+
+ Active Funding (Requires server restart)
+
Date: Thu, 21 Apr 2022 11:08:26 +0100
Subject: [PATCH 143/691] cleanup prints and console logs
---
lnbits/extensions/admin/crud.py | 2 +-
lnbits/extensions/admin/templates/admin/index.html | 4 ++--
lnbits/extensions/admin/views_api.py | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index dd39e8e4..f866bc1a 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -27,7 +27,7 @@ async def update_wallet_balance(wallet_id: str, amount: int) -> str:
async def update_admin(user: str, **kwargs) -> Admin:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
- print("UPDATE", q)
+ # print("UPDATE", q)
await db.execute(
f'UPDATE admin SET {q} WHERE "user" = ?', (*kwargs.values(), user)
)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 089c5f1c..584d3a33 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -1310,7 +1310,7 @@
theme: theme.toString(),
ad_space: ad_space.toString()
}
- console.log(data)
+ //console.log(data)
LNbits.api
.request(
'POST',
@@ -1319,7 +1319,7 @@
data
)
.then(response => {
- console.log(response.data)
+ //console.log(response.data)
this.$q.notify({
type: 'positive',
message: 'Success! Settings changed!',
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index b797dc2d..c0650c8a 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -35,7 +35,7 @@ async def api_update_admin(
w: WalletTypeInfo = Depends(require_admin_key)
):
admin = await get_admin()
- print(data)
+ # print(data)
if not admin.user == w.wallet.user:
raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
@@ -51,7 +51,7 @@ async def api_update_admin(
g().admin_conf = g().admin_conf.copy(update=updated.dict())
- print(g().admin_conf)
+ # print(g().admin_conf)
return {"status": "Success"}
@admin_ext.post("/api/v1/admin/funding/", status_code=HTTPStatus.OK)
From 3f38a9094b9c9e5e3c6b29df67b3508efbc41be6 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Mon, 16 May 2022 10:49:21 +0100
Subject: [PATCH 144/691] create first user on fresh install
---
.env.example | 4 ++--
lnbits/config.py | 3 ++-
lnbits/extensions/admin/README.md | 15 ++++++++-------
lnbits/extensions/admin/migrations.py | 15 ++++++++++++++-
4 files changed, 26 insertions(+), 11 deletions(-)
diff --git a/.env.example b/.env.example
index 4192f82e..f0e21aa8 100644
--- a/.env.example
+++ b/.env.example
@@ -4,8 +4,8 @@ PORT=5000
DEBUG=false
LNBITS_ADMIN_USERS="" # User IDs seperated by comma
-LNBITS_ADMIN_EXTENSIONS="ngrok" # Extensions only admin can access
-LNBITS_ADMIN_UI=false # Enable Admin GUI, available for the first user in LNBITS_ADMIN_USERS
+LNBITS_ADMIN_EXTENSIONS="ngrok, admin" # Extensions only admin can access
+LNBITS_ADMIN_UI=false # Enable Admin GUI, available for the first user in LNBITS_ADMIN_USERS if available
LNBITS_ALLOWED_USERS="" # Restricts access, User IDs seperated by comma
diff --git a/lnbits/config.py b/lnbits/config.py
index b2fbfff1..3ce51c3c 100644
--- a/lnbits/config.py
+++ b/lnbits/config.py
@@ -19,6 +19,7 @@ def list_parse_fallback(v):
return v.replace(' ','').split(',')
class Settings(BaseSettings):
+ admin_ui: bool = Field(default=True, env="LNBITS_ADMIN_UI")
# users
admin_users: List[str] = Field(default_factory=list, env="LNBITS_ADMIN_USERS")
allowed_users: List[str] = Field(default_factory=list, env="LNBITS_ALLOWED_USERS")
@@ -37,7 +38,7 @@ class Settings(BaseSettings):
site_tagline: str = Field(default="free and open-source lightning wallet", env="LNBITS_SITE_TAGLINE")
site_description: str = Field(default=None, env="LNBITS_SITE_DESCRIPTION")
default_wallet_name: str = Field(default="LNbits wallet", env="LNBITS_DEFAULT_WALLET_NAME")
- theme: List[str] = Field(default="classic, flamingo, mint, salvador, monochrome, autumn", env="LNBITS_THEME_OPTIONS")
+ theme: List[str] = Field(default=["classic, flamingo, mint, salvador, monochrome, autumn"], env="LNBITS_THEME_OPTIONS")
ad_space: List[str] = Field(default_factory=list, env="LNBITS_AD_SPACE")
# .env
env: Optional[str]
diff --git a/lnbits/extensions/admin/README.md b/lnbits/extensions/admin/README.md
index 27729459..6cf073a1 100644
--- a/lnbits/extensions/admin/README.md
+++ b/lnbits/extensions/admin/README.md
@@ -1,11 +1,12 @@
-Example Extension
-*tagline*
-This is an example extension to help you organise and build you own.
+# Admin Extension
-Try to include an image
-
+## Dashboard to manage LNbits from the UI
+With AdminUI you can manage your LNbits from the UI
-If your extension has API endpoints, include useful ones here
+![AdminUI](https://i.imgur.com/BIyLkyG.png)
-curl -H "Content-type: application/json" -X POST https://YOUR-LNBITS/YOUR-EXTENSION/api/v1/EXAMPLE -d '{"amount":"100","memo":"example"}' -H "X-Api-Key: YOUR_WALLET-ADMIN/INVOICE-KEY"
+## 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.
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 574f772d..0e22e667 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -6,9 +6,22 @@ from lnbits.config import conf
from lnbits.helpers import urlsafe_short_hash
+async def get_admin_user():
+ if(conf.admin_users[0]):
+ return conf.admin_users[0]
+ from lnbits.core.crud import create_account, get_user
+ print("Seems like there's no admin users yet. Let's create an account for you!")
+ account = await create_account()
+ user = account.id
+ assert user, "Newly created user couldn't be retrieved"
+ print(f"Your newly created account/user id is: {user}. This will be the Super Admin user.")
+ return user
+
+
+
async def m001_create_admin_table(db):
# users/server
- user = conf.admin_users[0]
+ user = await get_admin_user()
admin_users = ",".join(conf.admin_users)
allowed_users = ",".join(conf.allowed_users)
admin_ext = ",".join(conf.admin_ext)
From 0a29fb736093aeca3987122a7a78381b6f760499 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Mon, 16 May 2022 12:29:58 +0100
Subject: [PATCH 145/691] fix schemas for admin
---
lnbits/commands.py | 11 ++++++++---
lnbits/extensions/admin/crud.py | 12 ++++++------
lnbits/extensions/admin/migrations.py | 26 +++++++++++++-------------
3 files changed, 27 insertions(+), 22 deletions(-)
diff --git a/lnbits/commands.py b/lnbits/commands.py
index 8c39c338..7d9b49e2 100644
--- a/lnbits/commands.py
+++ b/lnbits/commands.py
@@ -55,8 +55,12 @@ def bundle_vendored():
async def get_admin_settings():
from lnbits.extensions.admin.models import Admin
- async with core_db.connect() as conn:
+ try:
+ ext_db = importlib.import_module(f"lnbits.extensions.admin").db
+ except:
+ return False
+ async with ext_db.connect() as conn:
if conn.type == SQLITE:
exists = await conn.fetchone(
"SELECT * FROM sqlite_master WHERE type='table' AND name='admin'"
@@ -65,11 +69,12 @@ async def get_admin_settings():
exists = await conn.fetchone(
"SELECT * FROM information_schema.tables WHERE table_name = 'admin'"
)
+ print("EXISTS", exists)
if not exists:
return False
- row = await conn.fetchone("SELECT * from admin")
-
+ row = await conn.fetchone("SELECT * from admin.admin")
+
return Admin(**row) if row else None
async def migrate_databases():
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index f866bc1a..67fbc614 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -29,30 +29,30 @@ async def update_admin(user: str, **kwargs) -> Admin:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
# print("UPDATE", q)
await db.execute(
- f'UPDATE admin SET {q} WHERE "user" = ?', (*kwargs.values(), user)
+ f'UPDATE admin.admin SET {q} WHERE "user" = ?', (*kwargs.values(), user)
)
- row = await db.fetchone('SELECT * FROM admin WHERE "user" = ?', (user,))
+ row = await db.fetchone('SELECT * FROM admin.admin WHERE "user" = ?', (user,))
assert row, "Newly updated settings couldn't be retrieved"
return Admin(**row) if row else None
async def get_admin() -> Admin:
- row = await db.fetchone("SELECT * FROM admin")
+ row = await db.fetchone("SELECT * FROM admin.admin")
return Admin(**row) if row else None
async def update_funding(data: Funding) -> Funding:
await db.execute(
"""
- UPDATE funding
+ UPDATE admin.funding
SET backend_wallet = ?, endpoint = ?, port = ?, read_key = ?, invoice_key = ?, admin_key = ?, cert = ?, balance = ?, selected = ?
WHERE id = ?
""",
(data.backend_wallet, data.endpoint, data.port, data.read_key, data.invoice_key, data.admin_key, data.cert, data.balance, data.selected, data.id,),
)
- row = await db.fetchone('SELECT * FROM funding WHERE "id" = ?', (data.id,))
+ row = await db.fetchone('SELECT * FROM admin.funding WHERE "id" = ?', (data.id,))
assert row, "Newly updated settings couldn't be retrieved"
return Funding(**row) if row else None
async def get_funding() -> List[Funding]:
- rows = await db.fetchall("SELECT * FROM funding")
+ rows = await db.fetchall("SELECT * FROM admin.funding")
return [Funding(**row) for row in rows]
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 0e22e667..c94d140b 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -96,7 +96,7 @@ async def m001_create_admin_table(db):
await db.execute(
"""
- CREATE TABLE IF NOT EXISTS admin (
+ CREATE TABLE IF NOT EXISTS admin.admin (
"user" TEXT PRIMARY KEY,
admin_users TEXT,
allowed_users TEXT,
@@ -120,7 +120,7 @@ async def m001_create_admin_table(db):
)
await db.execute(
"""
- INSERT INTO admin (
+ INSERT INTO admin.admin (
"user",
admin_users,
allowed_users,
@@ -171,7 +171,7 @@ async def m001_create_funding_table(db):
# Make the funding table, if it does not already exist
await db.execute(
"""
- CREATE TABLE IF NOT EXISTS funding (
+ CREATE TABLE IF NOT EXISTS admin.funding (
id TEXT PRIMARY KEY,
backend_wallet TEXT,
endpoint TEXT,
@@ -188,7 +188,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, selected)
VALUES (?, ?, ?, ?)
""",
(
@@ -200,7 +200,7 @@ async def m001_create_funding_table(db):
)
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
VALUES (?, ?, ?, ?, ?)
""",
(
@@ -214,7 +214,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
VALUES (?, ?, ?, ?, ?)
""",
(
@@ -228,7 +228,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, port, admin_key, cert, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, port, admin_key, cert, selected)
VALUES (?, ?, ?, ?, ?, ?, ?)
""",
(
@@ -244,7 +244,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, admin_key, cert, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, cert, selected)
VALUES (?, ?, ?, ?, ?, ?)
""",
(
@@ -259,7 +259,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, admin_key, cert, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, cert, selected)
VALUES (?, ?, ?, ?, ?, ?)
""",
(
@@ -274,7 +274,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
VALUES (?, ?, ?, ?, ?)
""",
(
@@ -288,7 +288,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
VALUES (?, ?, ?, ?, ?)
""",
(
@@ -302,7 +302,7 @@ async def m001_create_funding_table(db):
await db.execute(
"""
- INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
VALUES (?, ?, ?, ?, ?)
""",
(
@@ -317,7 +317,7 @@ async def m001_create_funding_table(db):
## PLACEHOLDER FOR ECLAIR WALLET
# await db.execute(
# """
- # INSERT INTO funding (id, backend_wallet, endpoint, admin_key, selected)
+ # INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
# VALUES (?, ?, ?, ?, ?)
# """,
# (
From ac74cfaab7e70d8df8229241e040403d473f04e1 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Mon, 16 May 2022 12:53:47 +0100
Subject: [PATCH 146/691] fix sqlite and show user account
---
lnbits/app.py | 1 +
lnbits/commands.py | 2 +-
lnbits/extensions/admin/migrations.py | 1 +
3 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index c8f5c60a..2b483758 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -116,6 +116,7 @@ def check_settings(app: FastAPI):
while True:
admin_set = await get_admin_settings()
if admin_set :
+ print(f"Access admin user account at: http://{lnbits.settings.HOST}:{lnbits.settings.PORT}/wallet?usr={admin_set.user}")
break
print("ERROR:", admin_set)
await asyncio.sleep(5)
diff --git a/lnbits/commands.py b/lnbits/commands.py
index 7d9b49e2..763a5b90 100644
--- a/lnbits/commands.py
+++ b/lnbits/commands.py
@@ -69,7 +69,7 @@ async def get_admin_settings():
exists = await conn.fetchone(
"SELECT * FROM information_schema.tables WHERE table_name = 'admin'"
)
- print("EXISTS", exists)
+
if not exists:
return False
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index c94d140b..6c5b507d 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -15,6 +15,7 @@ async def get_admin_user():
user = account.id
assert user, "Newly created user couldn't be retrieved"
print(f"Your newly created account/user id is: {user}. This will be the Super Admin user.")
+ conf.admin_users.insert(0, user)
return user
From 1ebd557b1d544f6baab770111a4bf89f31abea66 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Mon, 16 May 2022 15:35:04 +0100
Subject: [PATCH 147/691] cleanup and info to user on startup
---
lnbits/app.py | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 2b483758..eaa33136 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -112,13 +112,11 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
def check_settings(app: FastAPI):
@app.on_event("startup")
async def check_settings_admin():
-
while True:
admin_set = await get_admin_settings()
if admin_set :
- print(f"Access admin user account at: http://{lnbits.settings.HOST}:{lnbits.settings.PORT}/wallet?usr={admin_set.user}")
break
- print("ERROR:", admin_set)
+ print("Waiting for admin settings... retrying in 5 seconds!")
await asyncio.sleep(5)
admin_set.admin_users = removeEmptyString(admin_set.admin_users.split(','))
@@ -128,6 +126,7 @@ def check_settings(app: FastAPI):
admin_set.theme = removeEmptyString(admin_set.theme.split(','))
admin_set.ad_space = removeEmptyString(admin_set.ad_space.split(','))
g().admin_conf = conf.copy(update=admin_set.dict())
+ print(f" ✔️ Access admin user account at: http://{lnbits.settings.HOST}:{lnbits.settings.PORT}/wallet?usr={admin_set.user}")
def check_funding_source(app: FastAPI) -> None:
@app.on_event("startup")
From e04e24faec18e01c306d86a6bd45f238a74e1d38 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Wed, 8 Jun 2022 11:00:43 +0100
Subject: [PATCH 148/691] add custom logo
---
lnbits/config.py | 1 +
lnbits/extensions/admin/migrations.py | 58 ++-----------------
lnbits/extensions/admin/models.py | 2 +
.../admin/templates/admin/index.html | 20 +++++--
lnbits/helpers.py | 3 +-
5 files changed, 26 insertions(+), 58 deletions(-)
diff --git a/lnbits/config.py b/lnbits/config.py
index 3ce51c3c..d07ca044 100644
--- a/lnbits/config.py
+++ b/lnbits/config.py
@@ -39,6 +39,7 @@ class Settings(BaseSettings):
site_description: str = Field(default=None, env="LNBITS_SITE_DESCRIPTION")
default_wallet_name: str = Field(default="LNbits wallet", env="LNBITS_DEFAULT_WALLET_NAME")
theme: List[str] = Field(default=["classic, flamingo, mint, salvador, monochrome, autumn"], env="LNBITS_THEME_OPTIONS")
+ custom_logo: str = Field(default=None, env="LNBITS_CUSTOM_LOGO")
ad_space: List[str] = Field(default_factory=list, env="LNBITS_AD_SPACE")
# .env
env: Optional[str]
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 6c5b507d..aad66f02 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -41,60 +41,9 @@ async def m001_create_admin_table(db):
site_description = conf.site_description
default_wallet_name = conf.default_wallet_name
theme = ",".join(conf.theme)
+ custom_logo = conf.custom_logo
ad_space = ",".join(conf.ad_space)
- # if getenv("LNBITS_ADMIN_EXTENSIONS"):
- # admin_ext = getenv("LNBITS_ADMIN_EXTENSIONS")
-
- # if getenv("LNBITS_DATABASE_URL"):
- # database_url = getenv("LNBITS_DATABASE_URL")
-
- # if getenv("LNBITS_HIDE_API"):
- # hide_api = getenv("LNBITS_HIDE_API")
-
- # if getenv("LNBITS_THEME_OPTIONS"):
- # theme = getenv("LNBITS_THEME_OPTIONS")
-
- # if getenv("LNBITS_AD_SPACE"):
- # ad_space = getenv("LNBITS_AD_SPACE")
-
- # if getenv("LNBITS_SITE_TITLE"):
- # site_title = getenv("LNBITS_SITE_TITLE")
-
- # if getenv("LNBITS_SITE_TAGLINE"):
- # site_tagline = getenv("LNBITS_SITE_TAGLINE")
-
- # if getenv("LNBITS_SITE_DESCRIPTION"):
- # site_description = getenv("LNBITS_SITE_DESCRIPTION")
-
- # if getenv("LNBITS_ALLOWED_USERS"):
- # allowed_users = getenv("LNBITS_ALLOWED_USERS")
-
- # if getenv("LNBITS_ADMIN_USERS"):
- # admin_users = "".join(getenv("LNBITS_ADMIN_USERS").split())
- # user = admin_users.split(',')[0]
-
- # if getenv("LNBITS_DEFAULT_WALLET_NAME"):
- # default_wallet_name = getenv("LNBITS_DEFAULT_WALLET_NAME")
-
- # if getenv("LNBITS_DATA_FOLDER"):
- # data_folder = getenv("LNBITS_DATA_FOLDER")
-
- # if getenv("LNBITS_DISABLED_EXTENSIONS"):
- # disabled_ext = getenv("LNBITS_DISABLED_EXTENSIONS")
-
- # if getenv("LNBITS_FORCE_HTTPS"):
- # force_https = getenv("LNBITS_FORCE_HTTPS")
-
- # if getenv("LNBITS_SERVICE_FEE"):
- # service_fee = getenv("LNBITS_SERVICE_FEE")
-
- # if getenv("LNBITS_DENOMINATION"):
- # denomination = getenv("LNBITS_DENOMINATION", "sats")
-
- # if getenv("LNBITS_BACKEND_WALLET_CLASS"):
- # funding_source = getenv("LNBITS_BACKEND_WALLET_CLASS")
-
await db.execute(
"""
CREATE TABLE IF NOT EXISTS admin.admin (
@@ -115,6 +64,7 @@ async def m001_create_admin_table(db):
site_description TEXT,
default_wallet_name TEXT,
theme TEXT,
+ custom_logo TEXT,
ad_space TEXT
);
"""
@@ -139,8 +89,9 @@ async def m001_create_admin_table(db):
site_description,
default_wallet_name,
theme,
+ custom_logo,
ad_space)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
""",
(
user,
@@ -160,6 +111,7 @@ async def m001_create_admin_table(db):
site_description,
default_wallet_name,
theme,
+ custom_logo,
ad_space,
),
)
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 0f25679d..3b17e720 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -23,6 +23,7 @@ class UpdateAdminSettings(BaseModel):
default_wallet_name: str = Query("LNbits wallet")
denomination: str = Query("sats")
theme: str = Query(None)
+ custom_logo: str = Query(None)
ad_space: str = Query(None)
class Admin(BaseModel):
@@ -46,6 +47,7 @@ class Admin(BaseModel):
default_wallet_name: Optional[str]
denomination: str = Field(default="sats")
theme: Optional[str]
+ custom_logo: Optional[str]
ad_space: Optional[str]
@classmethod
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 584d3a33..d9790051 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -705,6 +705,19 @@
+
@@ -718,10 +731,7 @@
-
+
@@ -1292,6 +1323,8 @@
disabled_ext,
funding_source,
force_https,
+ reserve_fee_min,
+ reserve_fee_pct,
service_fee,
hide_api,
site_title,
@@ -1311,6 +1344,8 @@
disabled_ext: disabled_ext.toString(),
funding_source,
force_https,
+ reserve_fee_min,
+ reserve_fee_pct,
service_fee,
hide_api,
site_title,
diff --git a/lnbits/settings.py b/lnbits/settings.py
index ed5c77f7..8e5c321a 100644
--- a/lnbits/settings.py
+++ b/lnbits/settings.py
@@ -1,6 +1,5 @@
import importlib
import subprocess
-from email.policy import default
from os import path
from typing import List
From 929d174ba4bc20c074ff7bfd2741521c846d005b Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Wed, 8 Jun 2022 15:38:28 +0100
Subject: [PATCH 150/691] calle's semantics
---
lnbits/extensions/admin/templates/admin/index.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 832629bc..d34b9068 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -67,7 +67,7 @@
-
Minimum wallet reserve
+
Fee reserve
From 8e0baf7b2dcc2eb018ed972aba856ff3aca41b18 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Tue, 5 Jul 2022 16:25:02 +0100
Subject: [PATCH 151/691] blacked
---
lnbits/extensions/admin/__init__.py | 1 +
lnbits/extensions/admin/crud.py | 23 ++++++++++++---
lnbits/extensions/admin/migrations.py | 10 ++++---
lnbits/extensions/admin/models.py | 2 ++
lnbits/extensions/admin/views.py | 10 ++++---
lnbits/extensions/admin/views_api.py | 41 ++++++++++++++-------------
6 files changed, 56 insertions(+), 31 deletions(-)
diff --git a/lnbits/extensions/admin/__init__.py b/lnbits/extensions/admin/__init__.py
index 6a56b2bb..24b91fe2 100644
--- a/lnbits/extensions/admin/__init__.py
+++ b/lnbits/extensions/admin/__init__.py
@@ -7,6 +7,7 @@ db = Database("ext_admin")
admin_ext: APIRouter = APIRouter(prefix="/admin", tags=["admin"])
+
def admin_renderer():
return template_renderer(["lnbits/extensions/admin/templates"])
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index 67fbc614..0d7019cc 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -11,13 +11,13 @@ from .models import Admin, Funding
async def update_wallet_balance(wallet_id: str, amount: int) -> str:
temp_id = f"temp_{urlsafe_short_hash()}"
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,
+ amount=amount * 1000,
memo="Admin top up",
pending=False,
)
@@ -25,6 +25,7 @@ async def update_wallet_balance(wallet_id: str, amount: int) -> str:
await internal_invoice_queue.put(internal_id)
return payment
+
async def update_admin(user: str, **kwargs) -> Admin:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
# print("UPDATE", q)
@@ -35,23 +36,37 @@ async def update_admin(user: str, **kwargs) -> Admin:
assert row, "Newly updated settings couldn't be retrieved"
return Admin(**row) if row else None
+
async def get_admin() -> Admin:
row = await db.fetchone("SELECT * FROM admin.admin")
return Admin(**row) if row else None
+
async def update_funding(data: Funding) -> Funding:
await db.execute(
"""
UPDATE admin.funding
SET backend_wallet = ?, endpoint = ?, port = ?, read_key = ?, invoice_key = ?, admin_key = ?, cert = ?, balance = ?, selected = ?
WHERE id = ?
- """,
- (data.backend_wallet, data.endpoint, data.port, data.read_key, data.invoice_key, data.admin_key, data.cert, data.balance, data.selected, data.id,),
+ """,
+ (
+ data.backend_wallet,
+ data.endpoint,
+ data.port,
+ data.read_key,
+ data.invoice_key,
+ data.admin_key,
+ data.cert,
+ data.balance,
+ data.selected,
+ data.id,
+ ),
)
row = await db.fetchone('SELECT * FROM admin.funding WHERE "id" = ?', (data.id,))
assert row, "Newly updated settings couldn't be retrieved"
return Funding(**row) if row else None
+
async def get_funding() -> List[Funding]:
rows = await db.fetchall("SELECT * FROM admin.funding")
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index f3663435..388f5ec6 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -7,19 +7,21 @@ from lnbits.helpers import urlsafe_short_hash
async def get_admin_user():
- if(conf.admin_users[0]):
+ if conf.admin_users[0]:
return conf.admin_users[0]
from lnbits.core.crud import create_account, get_user
+
print("Seems like there's no admin users yet. Let's create an account for you!")
account = await create_account()
user = account.id
assert user, "Newly created user couldn't be retrieved"
- print(f"Your newly created account/user id is: {user}. This will be the Super Admin user.")
+ print(
+ f"Your newly created account/user id is: {user}. This will be the Super Admin user."
+ )
conf.admin_users.insert(0, user)
return user
-
async def m001_create_admin_table(db):
# users/server
user = await get_admin_user()
@@ -28,7 +30,7 @@ async def m001_create_admin_table(db):
admin_ext = ",".join(conf.admin_ext)
disabled_ext = ",".join(conf.disabled_ext)
funding_source = conf.funding_source
- #operational
+ # operational
data_folder = conf.data_folder
database_url = conf.database_url
force_https = conf.force_https
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 3d8efdcd..6e95d68f 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -28,6 +28,7 @@ class UpdateAdminSettings(BaseModel):
custom_logo: str = Query(None)
ad_space: str = Query(None)
+
class Admin(BaseModel):
# users
user: str
@@ -59,6 +60,7 @@ class Admin(BaseModel):
data = dict(row)
return cls(**data)
+
class Funding(BaseModel):
id: str
backend_wallet: str
diff --git a/lnbits/extensions/admin/views.py b/lnbits/extensions/admin/views.py
index 24b8ca85..ceda5192 100644
--- a/lnbits/extensions/admin/views.py
+++ b/lnbits/extensions/admin/views.py
@@ -16,19 +16,21 @@ from .crud import get_admin, get_funding
templates = Jinja2Templates(directory="templates")
+
@admin_ext.get("/", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_user_exists)):
admin = await get_admin()
funding = [f.dict() for f in await get_funding()]
error, balance = await g().WALLET.status()
-
+
return admin_renderer().TemplateResponse(
- "admin/index.html", {
+ "admin/index.html",
+ {
"request": request,
"user": user.dict(),
"admin": admin.dict(),
"funding": funding,
"settings": g().admin_conf.dict(),
- "balance": balance
- }
+ "balance": balance,
+ },
)
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index c0650c8a..784ad97f 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -15,16 +15,18 @@ from .crud import get_admin, update_admin, update_funding, update_wallet_balance
@admin_ext.get("/api/v1/admin/{wallet_id}/{topup_amount}", status_code=HTTPStatus.OK)
-async def api_update_balance(wallet_id, topup_amount: int, g: WalletTypeInfo = Depends(require_admin_key)):
+async def api_update_balance(
+ wallet_id, topup_amount: int, g: WalletTypeInfo = Depends(require_admin_key)
+):
try:
wallet = await get_wallet(wallet_id)
except:
raise HTTPException(
- status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
- )
+ status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
+ )
await update_wallet_balance(wallet_id=wallet_id, amount=int(topup_amount))
-
+
return {"status": "Success"}
@@ -32,39 +34,40 @@ async def api_update_balance(wallet_id, topup_amount: int, g: WalletTypeInfo = D
async def api_update_admin(
request: Request,
data: UpdateAdminSettings = Body(...),
- w: WalletTypeInfo = Depends(require_admin_key)
- ):
+ w: WalletTypeInfo = Depends(require_admin_key),
+):
admin = await get_admin()
# print(data)
if not admin.user == w.wallet.user:
raise HTTPException(
- status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
- )
+ status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
+ )
updated = await update_admin(user=w.wallet.user, **data.dict())
- updated.admin_users = removeEmptyString(updated.admin_users.split(','))
- updated.allowed_users = removeEmptyString(updated.allowed_users.split(','))
- updated.admin_ext = removeEmptyString(updated.admin_ext.split(','))
- updated.disabled_ext = removeEmptyString(updated.disabled_ext.split(','))
- updated.theme = removeEmptyString(updated.theme.split(','))
- updated.ad_space = removeEmptyString(updated.ad_space.split(','))
+ updated.admin_users = removeEmptyString(updated.admin_users.split(","))
+ updated.allowed_users = removeEmptyString(updated.allowed_users.split(","))
+ updated.admin_ext = removeEmptyString(updated.admin_ext.split(","))
+ updated.disabled_ext = removeEmptyString(updated.disabled_ext.split(","))
+ updated.theme = removeEmptyString(updated.theme.split(","))
+ updated.ad_space = removeEmptyString(updated.ad_space.split(","))
g().admin_conf = g().admin_conf.copy(update=updated.dict())
-
+
# print(g().admin_conf)
return {"status": "Success"}
+
@admin_ext.post("/api/v1/admin/funding/", status_code=HTTPStatus.OK)
async def api_update_funding(
request: Request,
data: Funding = Body(...),
- w: WalletTypeInfo = Depends(require_admin_key)
- ):
+ w: WalletTypeInfo = Depends(require_admin_key),
+):
admin = await get_admin()
if not admin.user == w.wallet.user:
raise HTTPException(
- status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
- )
+ status_code=HTTPStatus.FORBIDDEN, detail="Not allowed: not an admin"
+ )
funding = await update_funding(data=data)
return funding
From 429217f5a4876920277ad0719458daca52045b90 Mon Sep 17 00:00:00 2001
From: ben
Date: Wed, 21 Sep 2022 15:28:13 +0100
Subject: [PATCH 152/691] Had to add a couple of tries
---
lnbits/core/views/generic.py | 19 +++++++++++++------
1 file changed, 13 insertions(+), 6 deletions(-)
diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py
index 83648c44..63f7af68 100644
--- a/lnbits/core/views/generic.py
+++ b/lnbits/core/views/generic.py
@@ -133,12 +133,19 @@ async def wallet(
return template_renderer().TemplateResponse(
"error.html", {"request": request, "err": "User does not exist."}
)
- if LNBITS_ALLOWED_USERS and user_id not in LNBITS_ALLOWED_USERS:
- return template_renderer().TemplateResponse(
- "error.html", {"request": request, "err": "User not authorized."}
- )
- if LNBITS_ADMIN_USERS and user_id in LNBITS_ADMIN_USERS:
- user.admin = True
+ try:
+ if LNBITS_ALLOWED_USERS and user_id not in LNBITS_ALLOWED_USERS:
+ return template_renderer().TemplateResponse(
+ "error.html", {"request": request, "err": "User not authorized."}
+ )
+ except:
+ pass
+
+ try:
+ if LNBITS_ADMIN_USERS and user_id in LNBITS_ADMIN_USERS:
+ user.admin = True
+ except:
+ pass
if not wallet_id:
if user.wallets and not wallet_name: # type: ignore
wallet = user.wallets[0] # type: ignore
From 1aa2f01d29a25dd5fffac385afd3b5814e10b45c Mon Sep 17 00:00:00 2001
From: ben
Date: Wed, 21 Sep 2022 15:31:31 +0100
Subject: [PATCH 153/691] Added couple more tries
---
lnbits/decorators.py | 21 ++++++++++++---------
1 file changed, 12 insertions(+), 9 deletions(-)
diff --git a/lnbits/decorators.py b/lnbits/decorators.py
index f951163f..a810892d 100644
--- a/lnbits/decorators.py
+++ b/lnbits/decorators.py
@@ -239,13 +239,16 @@ async def check_user_exists(usr: UUID4) -> User:
if LNBITS_ADMIN_UI:
LNBITS_ADMIN_USERS = g().admin_conf.admin_users
LNBITS_ALLOWED_USERS = g().admin_conf.allowed_users
-
- if LNBITS_ALLOWED_USERS and g().user.id not in LNBITS_ALLOWED_USERS:
- raise HTTPException(
- status_code=HTTPStatus.UNAUTHORIZED, detail="User not authorized."
- )
-
- if LNBITS_ADMIN_USERS and g().user.id in LNBITS_ADMIN_USERS:
- g().user.admin = True
-
+ try:
+ if LNBITS_ALLOWED_USERS and g().user.id not in LNBITS_ALLOWED_USERS:
+ raise HTTPException(
+ status_code=HTTPStatus.UNAUTHORIZED, detail="User not authorized."
+ )
+ except:
+ pass
+ try:
+ if LNBITS_ADMIN_USERS and g().user.id in LNBITS_ADMIN_USERS:
+ g().user.admin = True
+ except:
+ pass
return g().user
From 10a065a7ca4f98c725e690d66f9c4f5c60d0c4e3 Mon Sep 17 00:00:00 2001
From: ben
Date: Wed, 21 Sep 2022 15:35:06 +0100
Subject: [PATCH 154/691] Reverted try
---
lnbits/decorators.py | 16 ++++++----------
1 file changed, 6 insertions(+), 10 deletions(-)
diff --git a/lnbits/decorators.py b/lnbits/decorators.py
index a810892d..904ca1c2 100644
--- a/lnbits/decorators.py
+++ b/lnbits/decorators.py
@@ -239,16 +239,12 @@ async def check_user_exists(usr: UUID4) -> User:
if LNBITS_ADMIN_UI:
LNBITS_ADMIN_USERS = g().admin_conf.admin_users
LNBITS_ALLOWED_USERS = g().admin_conf.allowed_users
- try:
- if LNBITS_ALLOWED_USERS and g().user.id not in LNBITS_ALLOWED_USERS:
- raise HTTPException(
- status_code=HTTPStatus.UNAUTHORIZED, detail="User not authorized."
- )
- except:
- pass
- try:
- if LNBITS_ADMIN_USERS and g().user.id in LNBITS_ADMIN_USERS:
- g().user.admin = True
+ if LNBITS_ALLOWED_USERS and g().user.id not in LNBITS_ALLOWED_USERS:
+ raise HTTPException(
+ status_code=HTTPStatus.UNAUTHORIZED, detail="User not authorized."
+ )
+ if LNBITS_ADMIN_USERS and g().user.id in LNBITS_ADMIN_USERS:
+ g().user.admin = True
except:
pass
return g().user
From 3129692ab16fbd66727faba6fb04c87e56b6e0f7 Mon Sep 17 00:00:00 2001
From: ben
Date: Wed, 21 Sep 2022 15:37:07 +0100
Subject: [PATCH 155/691] reverted other try
---
lnbits/core/views/generic.py | 19 ++++++-------------
lnbits/decorators.py | 2 --
2 files changed, 6 insertions(+), 15 deletions(-)
diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py
index 63f7af68..83648c44 100644
--- a/lnbits/core/views/generic.py
+++ b/lnbits/core/views/generic.py
@@ -133,19 +133,12 @@ async def wallet(
return template_renderer().TemplateResponse(
"error.html", {"request": request, "err": "User does not exist."}
)
- try:
- if LNBITS_ALLOWED_USERS and user_id not in LNBITS_ALLOWED_USERS:
- return template_renderer().TemplateResponse(
- "error.html", {"request": request, "err": "User not authorized."}
- )
- except:
- pass
-
- try:
- if LNBITS_ADMIN_USERS and user_id in LNBITS_ADMIN_USERS:
- user.admin = True
- except:
- pass
+ if LNBITS_ALLOWED_USERS and user_id not in LNBITS_ALLOWED_USERS:
+ return template_renderer().TemplateResponse(
+ "error.html", {"request": request, "err": "User not authorized."}
+ )
+ if LNBITS_ADMIN_USERS and user_id in LNBITS_ADMIN_USERS:
+ user.admin = True
if not wallet_id:
if user.wallets and not wallet_name: # type: ignore
wallet = user.wallets[0] # type: ignore
diff --git a/lnbits/decorators.py b/lnbits/decorators.py
index 904ca1c2..dd26d8fe 100644
--- a/lnbits/decorators.py
+++ b/lnbits/decorators.py
@@ -245,6 +245,4 @@ async def check_user_exists(usr: UUID4) -> User:
)
if LNBITS_ADMIN_USERS and g().user.id in LNBITS_ADMIN_USERS:
g().user.admin = True
- except:
- pass
return g().user
From 42f6acd9f4f2f076cf278a843d48db11cbfb2b63 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Wed, 21 Sep 2022 18:40:46 +0100
Subject: [PATCH 156/691] fix main merge missing settings
---
lnbits/app.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lnbits/app.py b/lnbits/app.py
index eaa33136..176c6bb9 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -56,6 +56,11 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
"url": "https://raw.githubusercontent.com/lnbits/lnbits-legend/main/LICENSE",
},
)
+ if lnbits.settings.LNBITS_ADMIN_UI:
+ g().admin_conf = conf
+ check_settings(app)
+
+ g().WALLET = WALLET
app.mount("/static", StaticFiles(packages=[("lnbits", "static")]), name="static")
app.mount(
"/core/static",
From a6bdd8c575f74685c9f71dfd142c908543b1d210 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Thu, 22 Sep 2022 10:46:11 +0200
Subject: [PATCH 157/691] format
---
lnbits/app.py | 22 +++++++++++++---------
lnbits/commands.py | 6 +++++-
lnbits/config.py | 25 ++++++++++++++++++-------
lnbits/core/views/generic.py | 1 +
lnbits/decorators.py | 2 +-
lnbits/helpers.py | 8 +++++---
6 files changed, 43 insertions(+), 21 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 176c6bb9..f4e44a0f 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -114,24 +114,28 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
return app
+
def check_settings(app: FastAPI):
@app.on_event("startup")
async def check_settings_admin():
while True:
admin_set = await get_admin_settings()
- if admin_set :
+ if admin_set:
break
print("Waiting for admin settings... retrying in 5 seconds!")
await asyncio.sleep(5)
-
- admin_set.admin_users = removeEmptyString(admin_set.admin_users.split(','))
- admin_set.allowed_users = removeEmptyString(admin_set.allowed_users.split(','))
- admin_set.admin_ext = removeEmptyString(admin_set.admin_ext.split(','))
- admin_set.disabled_ext = removeEmptyString(admin_set.disabled_ext.split(','))
- admin_set.theme = removeEmptyString(admin_set.theme.split(','))
- admin_set.ad_space = removeEmptyString(admin_set.ad_space.split(','))
+
+ admin_set.admin_users = removeEmptyString(admin_set.admin_users.split(","))
+ admin_set.allowed_users = removeEmptyString(admin_set.allowed_users.split(","))
+ admin_set.admin_ext = removeEmptyString(admin_set.admin_ext.split(","))
+ admin_set.disabled_ext = removeEmptyString(admin_set.disabled_ext.split(","))
+ admin_set.theme = removeEmptyString(admin_set.theme.split(","))
+ admin_set.ad_space = removeEmptyString(admin_set.ad_space.split(","))
g().admin_conf = conf.copy(update=admin_set.dict())
- print(f" ✔️ Access admin user account at: http://{lnbits.settings.HOST}:{lnbits.settings.PORT}/wallet?usr={admin_set.user}")
+ print(
+ f" ✔️ Access admin user account at: http://{lnbits.settings.HOST}:{lnbits.settings.PORT}/wallet?usr={admin_set.user}"
+ )
+
def check_funding_source(app: FastAPI) -> None:
@app.on_event("startup")
diff --git a/lnbits/commands.py b/lnbits/commands.py
index 763a5b90..86868f1f 100644
--- a/lnbits/commands.py
+++ b/lnbits/commands.py
@@ -5,6 +5,7 @@ import re
import warnings
import click
+from genericpath import exists
from loguru import logger
from .core import db as core_db
@@ -52,6 +53,7 @@ def bundle_vendored():
with open(outputpath, "w") as f:
f.write(output)
+
async def get_admin_settings():
from lnbits.extensions.admin.models import Admin
@@ -61,6 +63,7 @@ async def get_admin_settings():
return False
async with ext_db.connect() as conn:
+
if conn.type == SQLITE:
exists = await conn.fetchone(
"SELECT * FROM sqlite_master WHERE type='table' AND name='admin'"
@@ -69,7 +72,7 @@ async def get_admin_settings():
exists = await conn.fetchone(
"SELECT * FROM information_schema.tables WHERE table_name = 'admin'"
)
-
+
if not exists:
return False
@@ -77,6 +80,7 @@ async def get_admin_settings():
return Admin(**row) if row else None
+
async def migrate_databases():
"""Creates the necessary databases if they don't exist already; or migrates them."""
diff --git a/lnbits/config.py b/lnbits/config.py
index 37b700fd..cf26ad21 100644
--- a/lnbits/config.py
+++ b/lnbits/config.py
@@ -6,17 +6,19 @@ from typing import List, Optional
from pydantic import BaseSettings, Field
wallets_module = importlib.import_module("lnbits.wallets")
-wallet_class = getattr(
+wallet_class = getattr(
wallets_module, getenv("LNBITS_BACKEND_WALLET_CLASS", "VoidWallet")
)
WALLET = wallet_class()
+
def list_parse_fallback(v):
try:
return json.loads(v)
except Exception as e:
- return v.replace(' ','').split(',')
+ return v.replace(" ", "").split(",")
+
class Settings(BaseSettings):
admin_ui: bool = Field(default=True, env="LNBITS_ADMIN_UI")
@@ -24,7 +26,9 @@ class Settings(BaseSettings):
admin_users: List[str] = Field(default_factory=list, env="LNBITS_ADMIN_USERS")
allowed_users: List[str] = Field(default_factory=list, env="LNBITS_ALLOWED_USERS")
admin_ext: List[str] = Field(default_factory=list, env="LNBITS_ADMIN_EXTENSIONS")
- disabled_ext: List[str] = Field(default_factory=list, env="LNBITS_DISABLED_EXTENSIONS")
+ disabled_ext: List[str] = Field(
+ default_factory=list, env="LNBITS_DISABLED_EXTENSIONS"
+ )
funding_source: str = Field(default="VoidWallet", env="LNBITS_BACKEND_WALLET_CLASS")
# ops
data_folder: str = Field(default=None, env="LNBITS_DATA_FOLDER")
@@ -37,10 +41,17 @@ class Settings(BaseSettings):
denomination: str = Field(default="sats", env="LNBITS_DENOMINATION")
# Change theme
site_title: str = Field(default="LNbits", env="LNBITS_SITE_TITLE")
- site_tagline: str = Field(default="free and open-source lightning wallet", env="LNBITS_SITE_TAGLINE")
+ site_tagline: str = Field(
+ default="free and open-source lightning wallet", env="LNBITS_SITE_TAGLINE"
+ )
site_description: str = Field(default=None, env="LNBITS_SITE_DESCRIPTION")
- default_wallet_name: str = Field(default="LNbits wallet", env="LNBITS_DEFAULT_WALLET_NAME")
- theme: List[str] = Field(default=["classic, flamingo, mint, salvador, monochrome, autumn"], env="LNBITS_THEME_OPTIONS")
+ default_wallet_name: str = Field(
+ default="LNbits wallet", env="LNBITS_DEFAULT_WALLET_NAME"
+ )
+ theme: List[str] = Field(
+ default=["classic, flamingo, mint, salvador, monochrome, autumn"],
+ env="LNBITS_THEME_OPTIONS",
+ )
custom_logo: str = Field(default=None, env="LNBITS_CUSTOM_LOGO")
ad_space: List[str] = Field(default_factory=list, env="LNBITS_AD_SPACE")
# .env
@@ -48,7 +59,7 @@ class Settings(BaseSettings):
debug: Optional[str]
host: Optional[str]
port: Optional[str]
- lnbits_path: Optional[str] = path.dirname(path.realpath(__file__))
+ lnbits_path: Optional[str] = path.dirname(path.realpath(__file__))
# @validator('admin_users', 'allowed_users', 'admin_ext', 'disabled_ext', pre=True)
# def validate(cls, val):
diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py
index 83648c44..3a1fbdfc 100644
--- a/lnbits/core/views/generic.py
+++ b/lnbits/core/views/generic.py
@@ -39,6 +39,7 @@ from ..services import pay_invoice, redeem_lnurl_withdraw
core_html_routes: APIRouter = APIRouter(tags=["Core NON-API Website Routes"])
+
@core_html_routes.get("/favicon.ico", response_class=FileResponse)
async def favicon():
return FileResponse("lnbits/core/static/favicon.ico")
diff --git a/lnbits/decorators.py b/lnbits/decorators.py
index dd26d8fe..58b025aa 100644
--- a/lnbits/decorators.py
+++ b/lnbits/decorators.py
@@ -235,7 +235,7 @@ async def check_user_exists(usr: UUID4) -> User:
raise HTTPException(
status_code=HTTPStatus.NOT_FOUND, detail="User does not exist."
)
-
+
if LNBITS_ADMIN_UI:
LNBITS_ADMIN_USERS = g().admin_conf.admin_users
LNBITS_ALLOWED_USERS = g().admin_conf.allowed_users
diff --git a/lnbits/helpers.py b/lnbits/helpers.py
index 7bd1b54a..f4255c86 100644
--- a/lnbits/helpers.py
+++ b/lnbits/helpers.py
@@ -157,11 +157,13 @@ def url_for(endpoint: str, external: Optional[bool] = False, **params: Any) -> s
url = f"{base}{endpoint}{url_params}"
return url
+
def removeEmptyString(arr):
return list(filter(None, arr))
+
def template_renderer(additional_folders: List = []) -> Jinja2Templates:
- if(settings.LNBITS_ADMIN_UI):
+ if settings.LNBITS_ADMIN_UI:
_ = g().admin_conf
settings.LNBITS_AD_SPACE = _.ad_space
settings.LNBITS_HIDE_API = _.hide_api
@@ -170,8 +172,8 @@ def template_renderer(additional_folders: List = []) -> Jinja2Templates:
settings.LNBITS_SITE_TAGLINE = _.site_tagline
settings.LNBITS_SITE_DESCRIPTION = _.site_description
settings.LNBITS_THEME_OPTIONS = _.theme
- settings.LNBITS_CUSTOM_LOGO = _.custom_logo
-
+ settings.LNBITS_CUSTOM_LOGO = _.custom_logo
+
t = Jinja2Templates(
loader=jinja2.FileSystemLoader(
["lnbits/templates", "lnbits/core/templates", *additional_folders]
From 635bcf66d6f8cf7a65322a41abed92153039cd9e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Thu, 22 Sep 2022 11:47:24 +0200
Subject: [PATCH 158/691] format black
---
lnbits/app.py | 1 +
1 file changed, 1 insertion(+)
diff --git a/lnbits/app.py b/lnbits/app.py
index f4e44a0f..118bea98 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -56,6 +56,7 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
"url": "https://raw.githubusercontent.com/lnbits/lnbits-legend/main/LICENSE",
},
)
+
if lnbits.settings.LNBITS_ADMIN_UI:
g().admin_conf = conf
check_settings(app)
From 11393ef7e9ed808d9034baa8515eabcd37918a02 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Thu, 22 Sep 2022 15:29:12 +0200
Subject: [PATCH 159/691] fix AD_SPACE
---
lnbits/core/templates/core/wallet.html | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/lnbits/core/templates/core/wallet.html b/lnbits/core/templates/core/wallet.html
index 4bf6067c..cc45eb68 100644
--- a/lnbits/core/templates/core/wallet.html
+++ b/lnbits/core/templates/core/wallet.html
@@ -385,12 +385,9 @@
- {% endif %} {% if AD_SPACE %} {% for ADS in AD_SPACE %} {% set AD =
- ADS.split(';') %}
+ {% endif %} {% if AD_SPACE %} {% for AD in AD_SPACE %}
- {% endfor %} {% endif %}
From 0beb112d5b4f938201adfc6fc2814717ddac20a8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Thu, 22 Sep 2022 15:55:37 +0200
Subject: [PATCH 160/691] fix some javascript errors when adding users
---
lnbits/extensions/admin/templates/admin/index.html | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index d34b9068..1e881cb6 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -1221,7 +1221,7 @@
addAdminUser() {
let addUser = this.data.admin_users_add
let admin_users = this.data.admin.admin_users
- if (addUser.length && !admin_users.includes(addUser)) {
+ if (addUser && addUser.length && !admin_users.includes(addUser)) {
admin_users.push(addUser)
this.data.admin.admin_users = admin_users
this.data.admin_users_add = ''
@@ -1234,7 +1234,7 @@
addAllowedUser() {
let addUser = this.data.allowed_users_add
let allowed_users = this.data.admin.allowed_users
- if (addUser.length && !allowed_users.includes(addUser)) {
+ if (addUser && addUser.length && !allowed_users.includes(addUser)) {
allowed_users.push(addUser)
this.data.admin.allowed_users = allowed_users
this.data.allowed_users_add = ''
@@ -1336,7 +1336,6 @@
custom_logo,
ad_space
} = this.data.admin
- //console.log("this", this.data.admin)
let data = {
admin_users: admin_users.toString(),
allowed_users: allowed_users.toString(),
From bfff5f3775cd090b454869c434042b4acdb37434 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Thu, 22 Sep 2022 16:04:55 +0200
Subject: [PATCH 161/691] fix ADMIN_UI=false errors
---
lnbits/core/views/generic.py | 3 +++
lnbits/decorators.py | 6 ++++++
2 files changed, 9 insertions(+)
diff --git a/lnbits/core/views/generic.py b/lnbits/core/views/generic.py
index 3a1fbdfc..db4fac43 100644
--- a/lnbits/core/views/generic.py
+++ b/lnbits/core/views/generic.py
@@ -124,6 +124,9 @@ async def wallet(
if LNBITS_ADMIN_UI:
LNBITS_ADMIN_USERS = g().admin_conf.admin_users
LNBITS_ALLOWED_USERS = g().admin_conf.allowed_users
+ else:
+ LNBITS_ADMIN_USERS = []
+ LNBITS_ALLOWED_USERS = []
if not user_id:
user = await get_user((await create_account()).id)
diff --git a/lnbits/decorators.py b/lnbits/decorators.py
index 58b025aa..5a3c0a5c 100644
--- a/lnbits/decorators.py
+++ b/lnbits/decorators.py
@@ -141,6 +141,8 @@ async def get_key_type(
if LNBITS_ADMIN_UI:
LNBITS_ADMIN_USERS = g().admin_conf.admin_users
+ else:
+ LNBITS_ADMIN_USERS = []
for typenr, WalletChecker in zip(
[0, 1], [WalletAdminKeyChecker, WalletInvoiceKeyChecker]
@@ -239,6 +241,10 @@ async def check_user_exists(usr: UUID4) -> User:
if LNBITS_ADMIN_UI:
LNBITS_ADMIN_USERS = g().admin_conf.admin_users
LNBITS_ALLOWED_USERS = g().admin_conf.allowed_users
+ else:
+ LNBITS_ADMIN_USERS = []
+ LNBITS_ALLOWED_USERS = []
+
if LNBITS_ALLOWED_USERS and g().user.id not in LNBITS_ALLOWED_USERS:
raise HTTPException(
status_code=HTTPStatus.UNAUTHORIZED, detail="User not authorized."
From cede3317f3655c09b196c5293174a1dbaaaa18ee Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Thu, 22 Sep 2022 16:14:17 +0200
Subject: [PATCH 162/691] prettier
---
lnbits/core/templates/core/wallet.html | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/lnbits/core/templates/core/wallet.html b/lnbits/core/templates/core/wallet.html
index cc45eb68..5393007d 100644
--- a/lnbits/core/templates/core/wallet.html
+++ b/lnbits/core/templates/core/wallet.html
@@ -386,8 +386,7 @@
{% endif %} {% if AD_SPACE %} {% for AD in AD_SPACE %}
-
- {% endfor %} {% endif %}
From b442acc24f02c91971d29fbfe03dda9d5b5fc34c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Thu, 22 Sep 2022 18:35:47 +0200
Subject: [PATCH 163/691] fix migration tests
---
lnbits/extensions/admin/migrations.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 388f5ec6..196c9fc0 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -7,7 +7,7 @@ from lnbits.helpers import urlsafe_short_hash
async def get_admin_user():
- if conf.admin_users[0]:
+ if len(conf.admin_users) > 0:
return conf.admin_users[0]
from lnbits.core.crud import create_account, get_user
From 6db5fb16c85d3fd654afd55ee8d6969d243572bf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Mon, 26 Sep 2022 16:54:19 +0200
Subject: [PATCH 164/691] change comments to use multiple lines
---
.env.example | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/.env.example b/.env.example
index f0e21aa8..673470b7 100644
--- a/.env.example
+++ b/.env.example
@@ -3,11 +3,15 @@ PORT=5000
DEBUG=false
-LNBITS_ADMIN_USERS="" # User IDs seperated by comma
-LNBITS_ADMIN_EXTENSIONS="ngrok, admin" # Extensions only admin can access
-LNBITS_ADMIN_UI=false # Enable Admin GUI, available for the first user in LNBITS_ADMIN_USERS if available
+# User IDs seperated by comma
+LNBITS_ADMIN_USERS=""
+# Extensions only admin can access
+LNBITS_ADMIN_EXTENSIONS="ngrok, admin"
+# Enable Admin GUI, available for the first user in LNBITS_ADMIN_USERS if available
+LNBITS_ADMIN_UI=false
-LNBITS_ALLOWED_USERS="" # Restricts access, User IDs seperated by comma
+# Restricts access, User IDs seperated by comma
+LNBITS_ALLOWED_USERS=""
LNBITS_DEFAULT_WALLET_NAME="LNbits wallet"
From affec50a3da3ac812b5046c49483676e93962b2c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Mon, 26 Sep 2022 16:59:30 +0200
Subject: [PATCH 165/691] fix merge error
---
lnbits/app.py | 4 ----
1 file changed, 4 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 118bea98..82a8f20e 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -57,10 +57,6 @@ def create_app(config_object="lnbits.settings") -> FastAPI:
},
)
- if lnbits.settings.LNBITS_ADMIN_UI:
- g().admin_conf = conf
- check_settings(app)
-
g().WALLET = WALLET
app.mount("/static", StaticFiles(packages=[("lnbits", "static")]), name="static")
app.mount(
From 7aba2f989cdd78539ca22c69dc1a2e7d5ceb3d37 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Tue, 27 Sep 2022 14:14:36 +0200
Subject: [PATCH 166/691] use logger in app.py
---
lnbits/app.py | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 82a8f20e..e07d2ada 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -31,8 +31,6 @@ from .helpers import (
url_for_vendored,
)
from .requestvars import g
-
-# from .settings import WALLET
from .tasks import (
catch_everything_and_restart,
check_pending_payments,
@@ -119,7 +117,7 @@ def check_settings(app: FastAPI):
admin_set = await get_admin_settings()
if admin_set:
break
- print("Waiting for admin settings... retrying in 5 seconds!")
+ logger.info("Waiting for admin settings... retrying in 5 seconds!")
await asyncio.sleep(5)
admin_set.admin_users = removeEmptyString(admin_set.admin_users.split(","))
@@ -129,7 +127,7 @@ def check_settings(app: FastAPI):
admin_set.theme = removeEmptyString(admin_set.theme.split(","))
admin_set.ad_space = removeEmptyString(admin_set.ad_space.split(","))
g().admin_conf = conf.copy(update=admin_set.dict())
- print(
+ logger.info(
f" ✔️ Access admin user account at: http://{lnbits.settings.HOST}:{lnbits.settings.PORT}/wallet?usr={admin_set.user}"
)
From 212b8f9fdd67c73b16f2c0d97cd549bc7bb8f29e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Tue, 27 Sep 2022 14:14:57 +0200
Subject: [PATCH 167/691] fix config
---
lnbits/config.py | 12 +++++++-----
1 file changed, 7 insertions(+), 5 deletions(-)
diff --git a/lnbits/config.py b/lnbits/config.py
index cf26ad21..874effae 100644
--- a/lnbits/config.py
+++ b/lnbits/config.py
@@ -17,7 +17,11 @@ def list_parse_fallback(v):
try:
return json.loads(v)
except Exception as e:
- return v.replace(" ", "").split(",")
+ replaced = v.replace(" ", "")
+ if replaced:
+ return replaced.split(",")
+ else:
+ return []
class Settings(BaseSettings):
@@ -48,10 +52,7 @@ class Settings(BaseSettings):
default_wallet_name: str = Field(
default="LNbits wallet", env="LNBITS_DEFAULT_WALLET_NAME"
)
- theme: List[str] = Field(
- default=["classic, flamingo, mint, salvador, monochrome, autumn"],
- env="LNBITS_THEME_OPTIONS",
- )
+ theme: List[str] = Field(default_factory=list, env="LNBITS_THEME_OPTIONS")
custom_logo: str = Field(default=None, env="LNBITS_CUSTOM_LOGO")
ad_space: List[str] = Field(default_factory=list, env="LNBITS_AD_SPACE")
# .env
@@ -74,4 +75,5 @@ class Settings(BaseSettings):
conf = Settings()
+print(conf)
WALLET = wallet_class()
From b6a0a321844ff8a185f728b42f4ede3142334637 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Tue, 27 Sep 2022 14:17:20 +0200
Subject: [PATCH 168/691] concatenate first migrations script
fixup
---
lnbits/config.py | 1 -
lnbits/extensions/admin/migrations.py | 7 +++----
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/lnbits/config.py b/lnbits/config.py
index 874effae..fe8dabf9 100644
--- a/lnbits/config.py
+++ b/lnbits/config.py
@@ -75,5 +75,4 @@ class Settings(BaseSettings):
conf = Settings()
-print(conf)
WALLET = wallet_class()
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 196c9fc0..2d48a8e4 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -23,6 +23,8 @@ async def get_admin_user():
async def m001_create_admin_table(db):
+
+
# users/server
user = await get_admin_user()
admin_users = ",".join(conf.admin_users)
@@ -78,7 +80,7 @@ async def m001_create_admin_table(db):
await db.execute(
"""
INSERT INTO admin.admin (
- "user",
+ "user",
admin_users,
allowed_users,
admin_ext,
@@ -126,9 +128,6 @@ async def m001_create_admin_table(db):
),
)
-
-async def m001_create_funding_table(db):
-
funding_wallet = getenv("LNBITS_BACKEND_WALLET_CLASS")
# Make the funding table, if it does not already exist
From 1eeb9de7de8c2409f9a1d6b828e051ea640870d0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Tue, 27 Sep 2022 16:37:08 +0200
Subject: [PATCH 169/691] add restart button to frontend
---
.../admin/templates/admin/index.html | 28 ++++++++++++++++++-
1 file changed, 27 insertions(+), 1 deletion(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 1e881cb6..319ca3f0 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -65,6 +65,14 @@
:options="data.funding_source"
>
+
+
+
Fee reserve
@@ -89,7 +97,7 @@
>
-
+
@@ -1257,6 +1265,24 @@
let spaces = this.data.admin.ad_space
this.data.admin.ad_space = spaces.filter(s => s !== ad)
},
+ restartServer() {
+ LNbits.api
+ .request(
+ 'GET',
+ '/admin/api/v1/admin/restart/',
+ this.g.user.wallets[0].adminkey
+ )
+ .then(response => {
+ this.$q.notify({
+ type: 'positive',
+ message: 'Success! Restarted Server',
+ icon: null
+ })
+ })
+ .catch(function (error) {
+ LNbits.utils.notifyApiError(error)
+ })
+ },
topupWallet() {
LNbits.api
.request(
From 82e322ae43658bef7735974324fd3bec7919b756 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Mon, 3 Oct 2022 16:34:52 +0200
Subject: [PATCH 170/691] make extension use new settings
---
lnbits/extensions/boltz/boltz.py | 14 ++++++--------
lnbits/extensions/boltz/mempool.py | 15 ++++++---------
lnbits/extensions/boltz/views_api.py | 4 ++--
lnbits/extensions/lndhub/views_api.py | 4 ++--
lnbits/extensions/tpos/views.py | 14 +++++++-------
5 files changed, 23 insertions(+), 28 deletions(-)
diff --git a/lnbits/extensions/boltz/boltz.py b/lnbits/extensions/boltz/boltz.py
index ac99d4f4..424d0bf7 100644
--- a/lnbits/extensions/boltz/boltz.py
+++ b/lnbits/extensions/boltz/boltz.py
@@ -12,7 +12,7 @@ from loguru import logger
from lnbits.core.services import create_invoice, pay_invoice
from lnbits.helpers import urlsafe_short_hash
-from lnbits.settings import BOLTZ_NETWORK, BOLTZ_URL
+from lnbits.settings import settings
from .crud import update_swap_status
from .mempool import (
@@ -33,9 +33,7 @@ from .models import (
)
from .utils import check_balance, get_timestamp, req_wrap
-net = NETWORKS[BOLTZ_NETWORK]
-logger.trace(f"BOLTZ_URL: {BOLTZ_URL}")
-logger.trace(f"Bitcoin Network: {net['name']}")
+net = NETWORKS[settings.boltz_network]
async def create_swap(data: CreateSubmarineSwap) -> SubmarineSwap:
@@ -62,7 +60,7 @@ async def create_swap(data: CreateSubmarineSwap) -> SubmarineSwap:
res = req_wrap(
"post",
- f"{BOLTZ_URL}/createswap",
+ f"{settings.boltz_url}/createswap",
json={
"type": "submarine",
"pairId": "BTC/BTC",
@@ -129,7 +127,7 @@ async def create_reverse_swap(
res = req_wrap(
"post",
- f"{BOLTZ_URL}/createswap",
+ f"{settings.boltz_url}/createswap",
json={
"type": "reversesubmarine",
"pairId": "BTC/BTC",
@@ -409,7 +407,7 @@ def check_boltz_limits(amount):
def get_boltz_pairs():
res = req_wrap(
"get",
- f"{BOLTZ_URL}/getpairs",
+ f"{settings.boltz_url}/getpairs",
headers={"Content-Type": "application/json"},
)
return res.json()
@@ -418,7 +416,7 @@ def get_boltz_pairs():
def get_boltz_status(boltzid):
res = req_wrap(
"post",
- f"{BOLTZ_URL}/swapstatus",
+ f"{settings.boltz_url}/swapstatus",
json={"id": boltzid},
)
return res.json()
diff --git a/lnbits/extensions/boltz/mempool.py b/lnbits/extensions/boltz/mempool.py
index a44c0f02..a64cadad 100644
--- a/lnbits/extensions/boltz/mempool.py
+++ b/lnbits/extensions/boltz/mempool.py
@@ -7,14 +7,11 @@ import websockets
from embit.transaction import Transaction
from loguru import logger
-from lnbits.settings import BOLTZ_MEMPOOL_SPACE_URL, BOLTZ_MEMPOOL_SPACE_URL_WS
+from lnbits.settings import settings
from .utils import req_wrap
-logger.trace(f"BOLTZ_MEMPOOL_SPACE_URL: {BOLTZ_MEMPOOL_SPACE_URL}")
-logger.trace(f"BOLTZ_MEMPOOL_SPACE_URL_WS: {BOLTZ_MEMPOOL_SPACE_URL_WS}")
-
-websocket_url = f"{BOLTZ_MEMPOOL_SPACE_URL_WS}/api/v1/ws"
+websocket_url = f"{settings.boltz_mempool_space_url_ws}/api/v1/ws"
async def wait_for_websocket_message(send, message_string):
@@ -33,7 +30,7 @@ async def wait_for_websocket_message(send, message_string):
def get_mempool_tx(address):
res = req_wrap(
"get",
- f"{BOLTZ_MEMPOOL_SPACE_URL}/api/address/{address}/txs",
+ f"{settings.boltz_mempool_space_url}/api/address/{address}/txs",
headers={"Content-Type": "text/plain"},
)
txs = res.json()
@@ -70,7 +67,7 @@ def get_fee_estimation() -> int:
def get_mempool_fees() -> int:
res = req_wrap(
"get",
- f"{BOLTZ_MEMPOOL_SPACE_URL}/api/v1/fees/recommended",
+ f"{settings.boltz_mempool_space_url}/api/v1/fees/recommended",
headers={"Content-Type": "text/plain"},
)
fees = res.json()
@@ -80,7 +77,7 @@ def get_mempool_fees() -> int:
def get_mempool_blockheight() -> int:
res = req_wrap(
"get",
- f"{BOLTZ_MEMPOOL_SPACE_URL}/api/blocks/tip/height",
+ f"{settings.boltz_mempool_space_url}/api/blocks/tip/height",
headers={"Content-Type": "text/plain"},
)
return int(res.text)
@@ -91,7 +88,7 @@ async def send_onchain_tx(tx: Transaction):
logger.debug(f"Boltz - mempool sending onchain tx...")
req_wrap(
"post",
- f"{BOLTZ_MEMPOOL_SPACE_URL}/api/tx",
+ f"{settings.boltz_mempool_space_url}/api/tx",
headers={"Content-Type": "text/plain"},
content=raw,
)
diff --git a/lnbits/extensions/boltz/views_api.py b/lnbits/extensions/boltz/views_api.py
index a4b7d318..18ca14cb 100644
--- a/lnbits/extensions/boltz/views_api.py
+++ b/lnbits/extensions/boltz/views_api.py
@@ -14,7 +14,7 @@ from starlette.requests import Request
from lnbits.core.crud import get_user
from lnbits.decorators import WalletTypeInfo, get_key_type, require_admin_key
-from lnbits.settings import BOLTZ_MEMPOOL_SPACE_URL
+from lnbits.settings import settings
from . import boltz_ext
from .boltz import (
@@ -55,7 +55,7 @@ from .utils import check_balance
response_model=str,
)
async def api_mempool_url():
- return BOLTZ_MEMPOOL_SPACE_URL
+ return settings.boltz_mempool_space_url
# NORMAL SWAP
diff --git a/lnbits/extensions/lndhub/views_api.py b/lnbits/extensions/lndhub/views_api.py
index 8cbe5a6b..b2328c39 100644
--- a/lnbits/extensions/lndhub/views_api.py
+++ b/lnbits/extensions/lndhub/views_api.py
@@ -12,7 +12,7 @@ from lnbits import bolt11
from lnbits.core.crud import delete_expired_invoices, get_payments
from lnbits.core.services import create_invoice, pay_invoice
from lnbits.decorators import WalletTypeInfo
-from lnbits.settings import LNBITS_SITE_TITLE, WALLET
+from lnbits.settings import WALLET, settings
from . import lndhub_ext
from .decorators import check_wallet, require_admin_key
@@ -56,7 +56,7 @@ async def lndhub_addinvoice(
_, pr = await create_invoice(
wallet_id=wallet.wallet.id,
amount=int(data.amt),
- memo=data.memo or LNBITS_SITE_TITLE,
+ memo=data.memo or settings.lnbits_site_title,
extra={"tag": "lndhub"},
)
except:
diff --git a/lnbits/extensions/tpos/views.py b/lnbits/extensions/tpos/views.py
index e1f1d21e..dac129a9 100644
--- a/lnbits/extensions/tpos/views.py
+++ b/lnbits/extensions/tpos/views.py
@@ -8,7 +8,7 @@ from starlette.responses import HTMLResponse
from lnbits.core.models import User
from lnbits.decorators import check_user_exists
-from lnbits.settings import LNBITS_CUSTOM_LOGO, LNBITS_SITE_TITLE
+from lnbits.settings import settings
from . import tpos_ext, tpos_renderer
from .crud import get_tpos
@@ -50,12 +50,12 @@ async def manifest(tpos_id: str):
)
return {
- "short_name": LNBITS_SITE_TITLE,
- "name": tpos.name + " - " + LNBITS_SITE_TITLE,
+ "short_name": settings.lnbits_site_title,
+ "name": tpos.name + " - " + settings.lnbits_site_title,
"icons": [
{
- "src": LNBITS_CUSTOM_LOGO
- if LNBITS_CUSTOM_LOGO
+ "src": settings.lnbits_custom_logo
+ if settings.lnbits_custom_logo
else "https://cdn.jsdelivr.net/gh/lnbits/lnbits@0.3.0/docs/logos/lnbits.png",
"type": "image/png",
"sizes": "900x900",
@@ -69,9 +69,9 @@ async def manifest(tpos_id: str):
"theme_color": "#1F2234",
"shortcuts": [
{
- "name": tpos.name + " - " + LNBITS_SITE_TITLE,
+ "name": tpos.name + " - " + settings.lnbits_site_title,
"short_name": tpos.name,
- "description": tpos.name + " - " + LNBITS_SITE_TITLE,
+ "description": tpos.name + " - " + settings.lnbits_site_title,
"url": "/tpos/" + tpos_id,
}
],
From 5aa9cdd45631379341f31d17d9484c5e3ad05a4b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Mon, 3 Oct 2022 16:35:26 +0200
Subject: [PATCH 171/691] remove enviroms
---
pyproject.toml | 1 -
1 file changed, 1 deletion(-)
diff --git a/pyproject.toml b/pyproject.toml
index 7418de27..92c43dce 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -20,7 +20,6 @@ charset-normalizer = "2.0.6"
click = "8.0.1"
ecdsa = "0.17.0"
embit = "0.4.9"
-environs = "9.3.3"
fastapi = "0.78.0"
h11 = "0.12.0"
httpcore = "0.15.0"
From 6a2c7414783a5edb4b7932355f3fe145053332a5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Mon, 3 Oct 2022 16:36:14 +0200
Subject: [PATCH 172/691] fix admin
---
lnbits/extensions/admin/crud.py | 24 +-
lnbits/extensions/admin/migrations.py | 337 +----
lnbits/extensions/admin/models.py | 58 +-
.../admin/templates/admin/_tab_funding.html | 158 +++
.../admin/templates/admin/_tab_server.html | 78 ++
.../admin/templates/admin/_tab_theme.html | 122 ++
.../admin/templates/admin/_tab_users.html | 96 ++
.../admin/templates/admin/index.html | 1133 +----------------
lnbits/extensions/admin/views.py | 16 +-
lnbits/extensions/admin/views_api.py | 28 +-
10 files changed, 576 insertions(+), 1474 deletions(-)
create mode 100644 lnbits/extensions/admin/templates/admin/_tab_funding.html
create mode 100644 lnbits/extensions/admin/templates/admin/_tab_server.html
create mode 100644 lnbits/extensions/admin/templates/admin/_tab_theme.html
create mode 100644 lnbits/extensions/admin/templates/admin/_tab_users.html
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index 0d7019cc..e4cb5d77 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -2,10 +2,11 @@ from typing import List
from lnbits.core.crud import create_payment
from lnbits.helpers import urlsafe_short_hash
+from lnbits.settings import Settings
from lnbits.tasks import internal_invoice_queue
from . import db
-from .models import Admin, Funding
+from .models import Funding
async def update_wallet_balance(wallet_id: str, amount: int) -> str:
@@ -23,26 +24,26 @@ async def update_wallet_balance(wallet_id: str, amount: int) -> str:
)
# manually send this for now
await internal_invoice_queue.put(internal_id)
- return payment
-async def update_admin(user: str, **kwargs) -> Admin:
+async def update_settings(user: str, **kwargs) -> Settings:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
# print("UPDATE", q)
await db.execute(
- f'UPDATE admin.admin SET {q} WHERE "user" = ?', (*kwargs.values(), user)
+ f'UPDATE admin.settings SET {q} WHERE "user" = ?', (*kwargs.values(), user)
)
- row = await db.fetchone('SELECT * FROM admin.admin WHERE "user" = ?', (user,))
+ row = await db.fetchone('SELECT * FROM admin.settings WHERE "user" = ?', (user,))
assert row, "Newly updated settings couldn't be retrieved"
- return Admin(**row) if row else None
-
-
-async def get_admin() -> Admin:
- row = await db.fetchone("SELECT * FROM admin.admin")
- return Admin(**row) if row else None
+ return Settings(**row) if row else None
async def update_funding(data: Funding) -> Funding:
+ await db.execute(
+ """
+ UPDATE admin.settings SET funding_source = ? WHERE user = ?
+ """,
+ (data.backend_wallet, data.user),
+ )
await db.execute(
"""
UPDATE admin.funding
@@ -69,5 +70,4 @@ async def update_funding(data: Funding) -> Funding:
async def get_funding() -> List[Funding]:
rows = await db.fetchall("SELECT * FROM admin.funding")
-
return [Funding(**row) for row in rows]
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index 2d48a8e4..8f6c76a0 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -1,292 +1,57 @@
-from os import getenv
-
-from sqlalchemy.exc import OperationalError # type: ignore
-
-from lnbits.config import conf
-from lnbits.helpers import urlsafe_short_hash
-
-
-async def get_admin_user():
- if len(conf.admin_users) > 0:
- return conf.admin_users[0]
- from lnbits.core.crud import create_account, get_user
-
- print("Seems like there's no admin users yet. Let's create an account for you!")
- account = await create_account()
- user = account.id
- assert user, "Newly created user couldn't be retrieved"
- print(
- f"Your newly created account/user id is: {user}. This will be the Super Admin user."
- )
- conf.admin_users.insert(0, user)
- return user
-
-
-async def m001_create_admin_table(db):
-
-
- # users/server
- user = await get_admin_user()
- admin_users = ",".join(conf.admin_users)
- allowed_users = ",".join(conf.allowed_users)
- admin_ext = ",".join(conf.admin_ext)
- disabled_ext = ",".join(conf.disabled_ext)
- funding_source = conf.funding_source
- # operational
- data_folder = conf.data_folder
- database_url = conf.database_url
- force_https = conf.force_https
- reserve_fee_min = conf.reserve_fee_min
- reserve_fee_pct = conf.reserve_fee_pct
- service_fee = conf.service_fee
- hide_api = conf.hide_api
- denomination = conf.denomination
- # Theme'ing
- site_title = conf.site_title
- site_tagline = conf.site_tagline
- site_description = conf.site_description
- default_wallet_name = conf.default_wallet_name
- theme = ",".join(conf.theme)
- custom_logo = conf.custom_logo
- ad_space = ",".join(conf.ad_space)
-
+async def m001_create_admin_settings_table(db):
await db.execute(
"""
- CREATE TABLE IF NOT EXISTS admin.admin (
- "user" TEXT PRIMARY KEY,
- admin_users TEXT,
- allowed_users TEXT,
- admin_ext TEXT,
- disabled_ext TEXT,
- funding_source TEXT,
- data_folder TEXT,
- database_url TEXT,
- force_https BOOLEAN,
- reserve_fee_min INT,
- reserve_fee_pct REAL,
- service_fee REAL,
- hide_api BOOLEAN,
- denomination TEXT,
- site_title TEXT,
- site_tagline TEXT,
- site_description TEXT,
- default_wallet_name TEXT,
- theme TEXT,
- custom_logo TEXT,
- ad_space TEXT
- );
- """
- )
- await db.execute(
- """
- INSERT INTO admin.admin (
- "user",
- admin_users,
- allowed_users,
- admin_ext,
- disabled_ext,
- funding_source,
- data_folder,
- database_url,
- force_https,
- reserve_fee_min,
- reserve_fee_pct,
- service_fee,
- hide_api,
- denomination,
- site_title,
- site_tagline,
- site_description,
- default_wallet_name,
- theme,
- custom_logo,
- ad_space)
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
- """,
- (
- user,
- admin_users,
- allowed_users,
- admin_ext,
- disabled_ext,
- funding_source,
- data_folder,
- database_url,
- force_https,
- reserve_fee_min,
- reserve_fee_pct,
- service_fee,
- hide_api,
- denomination,
- site_title,
- site_tagline,
- site_description,
- default_wallet_name,
- theme,
- custom_logo,
- ad_space,
- ),
- )
-
- funding_wallet = getenv("LNBITS_BACKEND_WALLET_CLASS")
-
- # Make the funding table, if it does not already exist
- await db.execute(
- """
- CREATE TABLE IF NOT EXISTS admin.funding (
- id TEXT PRIMARY KEY,
- backend_wallet TEXT,
- endpoint TEXT,
+ CREATE TABLE IF NOT EXISTS admin.settings (
+ lnbits_admin_ui TEXT,
+ debug TEXT,
+ host TEXT,
port INT,
- read_key TEXT,
- invoice_key TEXT,
- admin_key TEXT,
- cert TEXT,
- balance INT,
- selected INT
+ lnbits_path TEXT,
+ lnbits_commit TEXT,
+ lnbits_admin_users TEXT,
+ lnbits_allowed_users TEXT,
+ lnbits_allowed_funding_sources TEXT,
+ lnbits_admin_extensions 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_data_folder TEXT,
+ lnbits_database_url TEXT,
+ 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,
+ fake_wallet_secret TEXT,
+ lnbits_endpoint TEXT,
+ lnbits_key TEXT,
+ cliche_endpoint TEXT,
+ corelightning_rpc TEXT,
+ eclair_url TEXT,
+ eclair_pass TEXT,
+ lnd_rest_endpoint TEXT,
+ lnd_rest_cert TEXT,
+ lnd_rest_macaroon 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
);
"""
)
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, selected)
- VALUES (?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "CLightningWallet",
- getenv("CLIGHTNING_RPC"),
- 1 if funding_wallet == "CLightningWallet" else 0,
- ),
- )
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
- VALUES (?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "SparkWallet",
- getenv("SPARK_URL"),
- getenv("SPARK_TOKEN"),
- 1 if funding_wallet == "SparkWallet" else 0,
- ),
- )
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
- VALUES (?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "LnbitsWallet",
- getenv("LNBITS_ENDPOINT"),
- getenv("LNBITS_KEY"),
- 1 if funding_wallet == "LnbitsWallet" else 0,
- ),
- )
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, port, admin_key, cert, selected)
- VALUES (?, ?, ?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "LndWallet",
- getenv("LND_GRPC_ENDPOINT"),
- getenv("LND_GRPC_PORT"),
- getenv("LND_GRPC_MACAROON"),
- getenv("LND_GRPC_CERT"),
- 1 if funding_wallet == "LndWallet" else 0,
- ),
- )
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, cert, selected)
- VALUES (?, ?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "LndRestWallet",
- getenv("LND_REST_ENDPOINT"),
- getenv("LND_REST_MACAROON"),
- getenv("LND_REST_CERT"),
- 1 if funding_wallet == "LndWallet" else 0,
- ),
- )
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, cert, selected)
- VALUES (?, ?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "LNPayWallet",
- getenv("LNPAY_API_ENDPOINT"),
- getenv("LNPAY_WALLET_KEY"),
- getenv("LNPAY_API_KEY"), # this is going in as the cert
- 1 if funding_wallet == "LNPayWallet" else 0,
- ),
- )
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
- VALUES (?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "LntxbotWallet",
- getenv("LNTXBOT_API_ENDPOINT"),
- getenv("LNTXBOT_KEY"),
- 1 if funding_wallet == "LntxbotWallet" else 0,
- ),
- )
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
- VALUES (?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "OpenNodeWallet",
- getenv("OPENNODE_API_ENDPOINT"),
- getenv("OPENNODE_KEY"),
- 1 if funding_wallet == "OpenNodeWallet" else 0,
- ),
- )
-
- await db.execute(
- """
- INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
- VALUES (?, ?, ?, ?, ?)
- """,
- (
- urlsafe_short_hash(),
- "SparkWallet",
- getenv("SPARK_URL"),
- getenv("SPARK_TOKEN"),
- 1 if funding_wallet == "SparkWallet" else 0,
- ),
- )
-
- ## PLACEHOLDER FOR ECLAIR WALLET
- # await db.execute(
- # """
- # INSERT INTO admin.funding (id, backend_wallet, endpoint, admin_key, selected)
- # VALUES (?, ?, ?, ?, ?)
- # """,
- # (
- # urlsafe_short_hash(),
- # "EclairWallet",
- # getenv("ECLAIR_URL"),
- # getenv("ECLAIR_PASS"),
- # 1 if funding_wallet == "EclairWallet" else 0,
- # ),
- # )
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 6e95d68f..ef57cadd 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -29,36 +29,36 @@ class UpdateAdminSettings(BaseModel):
ad_space: str = Query(None)
-class Admin(BaseModel):
- # users
- user: str
- admin_users: Optional[str]
- allowed_users: Optional[str]
- admin_ext: Optional[str]
- disabled_ext: Optional[str]
- funding_source: Optional[str]
- # ops
- data_folder: Optional[str]
- database_url: Optional[str]
- force_https: bool = Field(default=True)
- reserve_fee_min: Optional[int]
- reserve_fee_pct: Optional[float]
- service_fee: float = Optional[float]
- hide_api: bool = Field(default=False)
- # Change theme
- site_title: Optional[str]
- site_tagline: Optional[str]
- site_description: Optional[str]
- default_wallet_name: Optional[str]
- denomination: str = Field(default="sats")
- theme: Optional[str]
- custom_logo: Optional[str]
- ad_space: Optional[str]
+# class Admin(BaseModel):
+# # users
+# user: str
+# admin_users: Optional[str]
+# allowed_users: Optional[str]
+# admin_ext: Optional[str]
+# disabled_ext: Optional[str]
+# funding_source: Optional[str]
+# # ops
+# data_folder: Optional[str]
+# database_url: Optional[str]
+# force_https: bool = Field(default=True)
+# reserve_fee_min: Optional[int]
+# reserve_fee_pct: Optional[float]
+# service_fee: float = Optional[float]
+# hide_api: bool = Field(default=False)
+# # Change theme
+# site_title: Optional[str]
+# site_tagline: Optional[str]
+# site_description: Optional[str]
+# default_wallet_name: Optional[str]
+# denomination: str = Field(default="sats")
+# theme: Optional[str]
+# custom_logo: Optional[str]
+# ad_space: Optional[str]
- @classmethod
- def from_row(cls, row: Row) -> "Admin":
- data = dict(row)
- return cls(**data)
+# @classmethod
+# def from_row(cls, row: Row) -> "Admin":
+# data = dict(row)
+# return cls(**data)
class Funding(BaseModel):
diff --git a/lnbits/extensions/admin/templates/admin/_tab_funding.html b/lnbits/extensions/admin/templates/admin/_tab_funding.html
new file mode 100644
index 00000000..2ed0aae2
--- /dev/null
+++ b/lnbits/extensions/admin/templates/admin/_tab_funding.html
@@ -0,0 +1,158 @@
+
+
+ Wallets Management
+
+
+
+
+
Funding Source Info
+
+ {%raw%}
+ -
+ Funding Source: {{data.settings.lnbits_backend_wallet_class}}
+
+ - Balance: {{data.balance / 1000}} sats
+ {%endraw%}
+
+
+
+
+
+
+
+
+
Active Funding (Requires server restart)
+
+
+
+
+
+
+
+
+
+
+
TopUp a wallet
+
+
+
+
+
+
+
+
Funding Sources
+ {% raw %}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {% endraw %}
+
+
+
diff --git a/lnbits/extensions/admin/templates/admin/_tab_server.html b/lnbits/extensions/admin/templates/admin/_tab_server.html
new file mode 100644
index 00000000..2924e6a4
--- /dev/null
+++ b/lnbits/extensions/admin/templates/admin/_tab_server.html
@@ -0,0 +1,78 @@
+
+
+ Server Management
+
+
+
+
+
Server Info
+
+ {%raw%}
+ -
+ SQlite: {{data.settings.lnbits_data_folder}}
+
+ -
+ Postgres: {{data.settings.lnbits_database_url}}
+
+ {%endraw%}
+
+
+
+
+
+
+
+
Miscelaneous
+
+
+ Force HTTPS
+ Prefer secure URLs
+
+
+
+
+
+
+
+ Hide API
+ Hides wallet api, extensions can choose to honor
+
+
+
+
+
+
+
+
+
+
+
+ Save
+
+
+
diff --git a/lnbits/extensions/admin/templates/admin/_tab_theme.html b/lnbits/extensions/admin/templates/admin/_tab_theme.html
new file mode 100644
index 00000000..41dc0447
--- /dev/null
+++ b/lnbits/extensions/admin/templates/admin/_tab_theme.html
@@ -0,0 +1,122 @@
+
+
+ UI Management
+
+
+
+
+
+
+
+
Default Wallet Name
+
+
+
+
+
+
+
+
+
Advertisement Slots
+
+
+
+
+ {% raw %}
+
+ {{ space.slice(0, 8) + " ... " + space.slice(-8) }}
+
+ {% endraw %}
+
+
+
+
+
+
+
+
+ Save
+
+
+
diff --git a/lnbits/extensions/admin/templates/admin/_tab_users.html b/lnbits/extensions/admin/templates/admin/_tab_users.html
new file mode 100644
index 00000000..3eb53ac4
--- /dev/null
+++ b/lnbits/extensions/admin/templates/admin/_tab_users.html
@@ -0,0 +1,96 @@
+
+
+ User Management
+
+
+ Super Admin: {% raw %}{{this.data.settings.lnbits_admin_users[0]}}{%
+ endraw %}
+
+
+
+
Admin Users
+
+
+
+
+ {% raw %}
+
+ {{ user }}
+
+ {% endraw %}
+
+
+
+
+
Allowed Users
+
+
+
+
+ {% raw %}
+
+ {{ user }}
+
+ {% endraw %}
+
+
+
+
+
+
+
Disabled Extensions
+
+
+
+
+
+ Save
+
+
+
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 319ca3f0..87e89321 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -29,1118 +29,16 @@
-
-
-
- Wallets Management
-
-
-
-
-
Funding Source Info
-
- {%raw%}
- - Funding Source: {{data.admin.funding_source}}
- - Balance: {{data.admin.balance / 1000}} sats
- {%endraw%}
-
-
-
-
-
-
-
-
-
- Active Funding
- (Requires server restart)
-
-
-
-
-
-
-
-
-
-
-
-
-
TopUp a wallet
-
-
-
-
-
-
-
-
-
Funding Sources
- {% raw %}
-
-
-
-
-
-
-
-
-
-
-
-
-
- {% endraw %}
-
-
-
-
-
-
- User Management
-
-
- Super Admin: {% raw %}{{this.data.admin.user}}{% endraw %}
-
-
-
-
Admin Users
-
-
-
-
- {% raw %}
-
- {{ user }}
-
- {% endraw %}
-
-
-
-
-
Allowed Users
-
-
-
-
- {% raw %}
-
- {{ user }}
-
- {% endraw %}
-
-
-
-
-
-
-
Disabled Extensions
-
-
-
-
-
- Save
-
-
-
-
-
- Server Management
-
-
-
-
-
Server Info
-
- {%raw%}
- -
- SQlite: {{data.admin.data_folder}}
-
- -
- Postgres: {{data.admin.database_url}}
-
- {%endraw%}
-
-
-
-
-
-
-
-
Miscelaneous
-
-
- Force HTTPS
- Prefer secure URLs
-
-
-
-
-
-
-
- Hide API
- Hides wallet api, extensions can choose to
- honor
-
-
-
-
-
-
-
-
-
-
-
- Save
-
-
-
-
-
- UI Management
-
-
-
-
-
-
-
-
Default Wallet Name
-
-
-
-
-
-
-
-
-
Advertisement Slots
-
-
-
-
- {% raw %}
-
- {{ space.slice(0, 8) + " ... " + space.slice(-8) }}
-
- {% endraw %}
-
-
-
-
-
-
-
-
- Save
-
-
-
+ {% include "admin/_tab_funding.html" %} {% include
+ "admin/_tab_users.html" %} {% include "admin/_tab_server.html" %} {%
+ include "admin/_tab_theme.html" %}
-
-
-
-
-
{% endblock %} {% block scripts %} {{ window_vars(user) }}
{% endblock %}
From 04b37458983094ff9deec4ba010ec2a93c002cd9 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Fri, 7 Oct 2022 19:24:07 +0100
Subject: [PATCH 198/691] make saving possible (possible will change in future)
---
.../admin/templates/admin/index.html | 36 ++++++++++++-------
1 file changed, 24 insertions(+), 12 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 72352651..18df16a9 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -121,8 +121,11 @@
created: function () {
this.settings = JSON.parse('{{ settings|tojson|safe }}') //DB data
this.balance = +'{{ balance|safe }}'
- this.formData = this.settings //model
+ this.formData = _.clone(this.settings) //model
+ //this.formData.lnbits_ad_space = "hdh"
console.log(this.formData)
+ console.log(_.isEqual(this.settings, this.formData))
+
},
methods: {
addAdminUser() {
@@ -206,18 +209,27 @@
},
updateSettings() {
let data = {
- ...this.settings,
- ...this.formData
+ lnbits_backend_wallet_class: this.formData.lnbits_backend_wallet_class,
+ lnbits_admin_users: this.formData.lnbits_admin_users.toString(),
+ lnbits_allowed_users: this.formData.lnbits_allowed_users.toString(),
+ lnbits_admin_ext: this.formData.lnbits_admin_ext,
+ lnbits_disabled_ext: this.formData.lnbits_disabled_ext,
+ lnbits_funding_source: this.formData.lnbits_funding_source,
+ lnbits_force_https: this.formData.lnbits_force_https,
+ lnbits_reserve_fee_min: this.formData.lnbits_reserve_fee_min,
+ lnbits_reserve_fee_percent: this.formData.lnbits_reserve_fee_percent,
+ lnbits_service_fee: this.formData.lnbits_service_fee,
+ lnbits_hide_api: this.formData.lnbits_hide_api,
+ lnbits_site_title: this.formData.lnbits_site_title,
+ lnbits_site_tagline: this.formData.lnbits_site_tagline,
+ lnbits_site_description: this.formData.lnbits_site_description,
+ lnbits_default_wallet_name: this.formData.lnbits_default_wallet_name,
+ lnbits_denomination: this.formData.lnbits_denomination,
+ lnbits_theme: this.formData.lnbits_theme,
+ lnbits_custom_logo: this.formData.lnbits_custom_logo,
+ lnbits_ad_space: this.formData.lnbits_ad_space.toString()
}
- /*
- 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`)
- }*/
+ console.log(data)
LNbits.api
.request(
'PUT',
From cc42df12f4d3927c854675f114aff0b75bef6d19 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Fri, 7 Oct 2022 19:44:03 +0100
Subject: [PATCH 199/691] some more refining
---
lnbits/extensions/admin/models.py | 10 +++++-----
.../extensions/admin/templates/admin/_tab_users.html | 2 ++
lnbits/extensions/admin/templates/admin/index.html | 12 +++++++++---
3 files changed, 16 insertions(+), 8 deletions(-)
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 13a6cd23..45cd990d 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -4,10 +4,10 @@ from pydantic import BaseModel
class UpdateSettings(BaseModel):
lnbits_backend_wallet_class: str = Query(None)
- lnbits_admin_users: str = Query(None)
- lnbits_allowed_users: str = Query(None)
- lnbits_admin_ext: str = Query(None)
- lnbits_disabled_ext: str = Query(None)
+ lnbits_admin_users: str = Query(None) #this should be List[str] ??
+ lnbits_allowed_users: str = Query(None) #this should be List[str] ??
+ lnbits_admin_ext: str = Query(None) #this should be List[str] ??
+ lnbits_disabled_ext: str = Query(None) #this should be List[str] ??
lnbits_funding_source: str = Query(None)
lnbits_force_https: bool = Query(None)
lnbits_reserve_fee_min: int = Query(None, ge=0)
@@ -21,4 +21,4 @@ class UpdateSettings(BaseModel):
lnbits_denomination: str = Query(None)
lnbits_theme: str = Query(None)
lnbits_custom_logo: str = Query(None)
- lnbits_ad_space: str = Query(None)
+ lnbits_ad_space: str = Query(None) #this should be List[str] ??
diff --git a/lnbits/extensions/admin/templates/admin/_tab_users.html b/lnbits/extensions/admin/templates/admin/_tab_users.html
index c396ba7d..08b08a62 100644
--- a/lnbits/extensions/admin/templates/admin/_tab_users.html
+++ b/lnbits/extensions/admin/templates/admin/_tab_users.html
@@ -71,6 +71,7 @@
multiple
hint="Extensions only user with admin privileges can use"
label="Admin extensions"
+ :options="g.extensions.map(e => e.name)"
>
@@ -79,6 +80,7 @@
-
+
Date: Mon, 10 Oct 2022 12:17:35 +0100
Subject: [PATCH 200/691] get saved data and alert when data changed
---
.../admin/templates/admin/index.html | 18 +++++++-----------
lnbits/extensions/admin/views_api.py | 5 +++--
2 files changed, 10 insertions(+), 13 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 4754656d..4e401cb4 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -3,7 +3,7 @@
-
+
{
+ this.settings = response.data.settings
+ this.formData = _.clone(this.settings)
this.$q.notify({
type: 'positive',
message: 'Success! Settings changed!',
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index c8120564..c2079e37 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -43,8 +43,9 @@ async def api_update_settings(
user: User = Depends(check_admin),
data: UpdateSettings = Body(...),
):
- await update_settings(data)
- return {"status": "Success"}
+ settings = await update_settings(data)
+ logger.debug(settings)
+ return {"status": "Success", "settings": settings.dict()}
@admin_ext.delete("/api/v1/settings/", status_code=HTTPStatus.OK)
From 001f6589bb3c173c9ada0f86ec0a2eca08f3b051 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Mon, 10 Oct 2022 12:23:19 +0100
Subject: [PATCH 201/691] cleanup and typing fix for data
---
lnbits/extensions/admin/models.py | 12 +++++-----
.../admin/templates/admin/index.html | 22 ++-----------------
lnbits/extensions/admin/views_api.py | 1 -
3 files changed, 9 insertions(+), 26 deletions(-)
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 45cd990d..94fa56bb 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -1,13 +1,15 @@
+from typing import List
+
from fastapi import Query
from pydantic import BaseModel
class UpdateSettings(BaseModel):
lnbits_backend_wallet_class: str = Query(None)
- lnbits_admin_users: str = Query(None) #this should be List[str] ??
- lnbits_allowed_users: str = Query(None) #this should be List[str] ??
- lnbits_admin_ext: str = Query(None) #this should be List[str] ??
- lnbits_disabled_ext: str = Query(None) #this should be List[str] ??
+ lnbits_admin_users: List[str] = Query(None)
+ lnbits_allowed_users: List[str] = Query(None)
+ lnbits_admin_ext: List[str] = Query(None)
+ lnbits_disabled_ext: List[str] = Query(None)
lnbits_funding_source: str = Query(None)
lnbits_force_https: bool = Query(None)
lnbits_reserve_fee_min: int = Query(None, ge=0)
@@ -21,4 +23,4 @@ class UpdateSettings(BaseModel):
lnbits_denomination: str = Query(None)
lnbits_theme: str = Query(None)
lnbits_custom_logo: str = Query(None)
- lnbits_ad_space: str = Query(None) #this should be List[str] ??
+ lnbits_ad_space: List[str] = Query(None)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 4e401cb4..d8111595 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -209,26 +209,8 @@
})
},
updateSettings() {
- let data = {
- lnbits_backend_wallet_class: this.formData.lnbits_backend_wallet_class,
- lnbits_admin_users: this.formData.lnbits_admin_users.toString(),
- lnbits_allowed_users: this.formData.lnbits_allowed_users.toString(),
- lnbits_admin_ext: this.formData.lnbits_admin_ext,
- lnbits_disabled_ext: this.formData.lnbits_disabled_ext,
- lnbits_funding_source: this.formData.lnbits_funding_source,
- lnbits_force_https: this.formData.lnbits_force_https,
- lnbits_reserve_fee_min: this.formData.lnbits_reserve_fee_min,
- lnbits_reserve_fee_percent: this.formData.lnbits_reserve_fee_percent,
- lnbits_service_fee: this.formData.lnbits_service_fee,
- lnbits_hide_api: this.formData.lnbits_hide_api,
- lnbits_site_title: this.formData.lnbits_site_title,
- lnbits_site_tagline: this.formData.lnbits_site_tagline,
- lnbits_site_description: this.formData.lnbits_site_description,
- lnbits_default_wallet_name: this.formData.lnbits_default_wallet_name,
- lnbits_denomination: this.formData.lnbits_denomination,
- lnbits_theme: this.formData.lnbits_theme,
- lnbits_custom_logo: this.formData.lnbits_custom_logo,
- lnbits_ad_space: this.formData.lnbits_ad_space.toString()
+ let data = {
+ ...this.formData
}
LNbits.api
.request(
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index c2079e37..19b52e35 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -44,7 +44,6 @@ async def api_update_settings(
data: UpdateSettings = Body(...),
):
settings = await update_settings(data)
- logger.debug(settings)
return {"status": "Success", "settings": settings.dict()}
From 1cc54ff4b7e19366499743fc9cb881bb58ccf2c6 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Wed, 12 Oct 2022 19:04:46 +0100
Subject: [PATCH 202/691] add funding sources options
---
lnbits/app.py | 1 +
lnbits/extensions/admin/models.py | 41 +++-
.../admin/templates/admin/_tab_funding.html | 25 +-
.../admin/templates/admin/index.html | 217 +++++++++++++++++-
4 files changed, 259 insertions(+), 25 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index a8371950..50f218b7 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -84,6 +84,7 @@ async def check_funding_source() -> None:
def signal_handler(signal, frame):
logger.debug(f"SIGINT received, terminating LNbits.")
sys.exit(1)
+
signal.signal(signal.SIGINT, signal_handler)
WALLET = get_wallet_class()
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index 94fa56bb..d9d2b22f 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -6,10 +6,10 @@ from pydantic import BaseModel
class UpdateSettings(BaseModel):
lnbits_backend_wallet_class: str = Query(None)
- lnbits_admin_users: List[str] = Query(None)
- lnbits_allowed_users: List[str] = Query(None)
- lnbits_admin_ext: List[str] = Query(None)
- lnbits_disabled_ext: List[str] = Query(None)
+ lnbits_admin_users: List[str] = Query(None)
+ lnbits_allowed_users: List[str] = Query(None)
+ lnbits_admin_ext: List[str] = Query(None)
+ lnbits_disabled_ext: List[str] = Query(None)
lnbits_funding_source: str = Query(None)
lnbits_force_https: bool = Query(None)
lnbits_reserve_fee_min: int = Query(None, ge=0)
@@ -23,4 +23,35 @@ class UpdateSettings(BaseModel):
lnbits_denomination: str = Query(None)
lnbits_theme: str = Query(None)
lnbits_custom_logo: str = Query(None)
- lnbits_ad_space: List[str] = Query(None)
+ lnbits_ad_space: List[str] = 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_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)
diff --git a/lnbits/extensions/admin/templates/admin/_tab_funding.html b/lnbits/extensions/admin/templates/admin/_tab_funding.html
index 8b5456f1..a523d4e5 100644
--- a/lnbits/extensions/admin/templates/admin/_tab_funding.html
+++ b/lnbits/extensions/admin/templates/admin/_tab_funding.html
@@ -8,9 +8,7 @@
Funding Source Info
{%raw%}
- -
- Funding Source: {{settings.lnbits_backend_wallet_class}}
-
+ - Funding Source: {{settings.lnbits_backend_wallet_class}}
- Balance: {{balance / 1000}} sats
{%endraw%}
@@ -60,21 +58,30 @@
- Funding Sources
+ Funding Sources (Requires server restart)
-
+
-
-
+
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index d8111595..ccaddda4 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -3,7 +3,13 @@
-
+
u !== user
- )
+ this.settings.lnbits_admin_users = admin_users.filter(u => u !== user)
},
addAllowedUser() {
let addUser = this.formData.allowed_users_add
@@ -155,7 +335,9 @@
},
removeAllowedUser(user) {
let allowed_users = this.settings.lnbits_allowed_users
- this.settings.lnbits_allowed_users = allowed_users.filter(u => u !== user)
+ this.settings.lnbits_allowed_users = allowed_users.filter(
+ u => u !== user
+ )
},
addAdSpace() {
let adSpace = this.formData.ad_space_add
@@ -208,8 +390,19 @@
LNbits.utils.notifyApiError(error)
})
},
+ updateFundingData(){
+ this.settings.lnbits_allowed_funding_sources.map(f => {
+ let opts = this.funding_sources.get(f)
+ if (!opts) return
+
+ Object.keys(opts).forEach(e => {
+ opts[e].value = this.settings[e]
+ })
+ })
+ console.log("funding", this.funding_sources)
+ },
updateSettings() {
- let data = {
+ let data = {
...this.formData
}
LNbits.api
@@ -222,11 +415,13 @@
.then(response => {
this.settings = response.data.settings
this.formData = _.clone(this.settings)
+ this.updateFundingData()
this.$q.notify({
type: 'positive',
message: 'Success! Settings changed!',
icon: null
})
+ console.log(this.settings)
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
@@ -262,7 +457,7 @@
LNbits.utils.notifyApiError(error)
})
}
- },
+ }
})
{% endblock %}
From 761fc427defc590913124f1ad2f1b518633fbad4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Mon, 10 Oct 2022 23:27:46 +0200
Subject: [PATCH 203/691] add callback for saas app
---
lnbits/app.py | 2 +-
lnbits/extensions/admin/migrations.py | 3 +++
lnbits/extensions/admin/views_api.py | 5 -----
lnbits/settings.py | 32 +++++++++++++++++++++++----
4 files changed, 32 insertions(+), 10 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 50f218b7..49ad8d77 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -64,7 +64,7 @@ def create_app() -> FastAPI:
# TODO: why those 2?
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)
diff --git a/lnbits/extensions/admin/migrations.py b/lnbits/extensions/admin/migrations.py
index c4bc98d8..ea698c27 100644
--- a/lnbits/extensions/admin/migrations.py
+++ b/lnbits/extensions/admin/migrations.py
@@ -6,6 +6,9 @@ async def m001_create_admin_settings_table(db):
debug TEXT,
host TEXT,
port INTEGER,
+ lnbits_saas_instance_id TEXT,
+ lnbits_saas_callback TEXT,
+ lnbits_saas_secret TEXT,
lnbits_path TEXT,
lnbits_commit TEXT,
lnbits_admin_users TEXT,
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index 19b52e35..ae2959bc 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -53,8 +53,3 @@ async def api_delete_settings(
):
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"}
diff --git a/lnbits/settings.py b/lnbits/settings.py
index ffcdcc0a..f183211c 100644
--- a/lnbits/settings.py
+++ b/lnbits/settings.py
@@ -1,6 +1,7 @@
import importlib
import json
import subprocess
+import httpx
from os import path
from sqlite3 import Row
from typing import List, Optional
@@ -9,6 +10,7 @@ from loguru import logger
from pydantic import BaseSettings, Field, validator
+
def list_parse_fallback(v):
try:
return json.loads(v)
@@ -34,6 +36,11 @@ class Settings(BaseSettings):
lnbits_path: str = Field(default=".")
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
lnbits_admin_users: List[str] = Field(default=[])
lnbits_allowed_users: List[str] = Field(default=[])
@@ -230,11 +237,28 @@ async def check_admin_settings():
http = "https" if settings.lnbits_force_https else "http"
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:
+ r = client.post(settings.lnbits_saas_callback, headers=headers, json=payload)
+ logger.warning("sent admin user to saas application")
+ except:
+ logger.error(f"error sending admin user to saas: {settings.lnbits_saas_callback}")
+
except:
- logger.warning("admin.settings tables does not exist.")
+ logger.error("admin.settings tables does not exist.")
raise
From 620fd2569655aa0f45b486201bcac75654f28326 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Wed, 12 Oct 2022 13:08:59 +0200
Subject: [PATCH 204/691] bugfixes and fix topup wallet
---
.../admin/templates/admin/index.html | 6 ++--
lnbits/extensions/admin/views_api.py | 36 ++++++++++---------
lnbits/server.py | 1 +
lnbits/settings.py | 29 ++++++++++-----
lnbits/wallets/fake.py | 2 +-
5 files changed, 44 insertions(+), 30 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index ccaddda4..575b377f 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -369,10 +369,10 @@
topupWallet() {
LNbits.api
.request(
- 'POST',
+ 'PUT',
'/admin/api/v1/topup/?usr=' + this.g.user.id,
- this.wallet.id,
- this.wallet.amount
+ this.g.user.wallets[0].adminkey,
+ this.wallet
)
.then(response => {
this.$q.notify({
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index ae2959bc..63ed5b3c 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -1,7 +1,6 @@
from http import HTTPStatus
-from fastapi import Body, Depends, Request
-from loguru import logger
+from fastapi import Body, Depends, Query
from starlette.exceptions import HTTPException
from lnbits.core.crud import get_wallet
@@ -9,47 +8,50 @@ from lnbits.core.models import User
from lnbits.decorators import check_admin
from lnbits.extensions.admin import admin_ext
from lnbits.extensions.admin.models import UpdateSettings
-from lnbits.requestvars import g
from lnbits.server import server_restart
-from lnbits.settings import settings
from .crud import delete_settings, update_settings, update_wallet_balance
-@admin_ext.get("/api/v1/restart/", status_code=HTTPStatus.OK)
-async def api_restart_server(user: User = Depends(check_admin)):
+@admin_ext.get(
+ "/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.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(
- wallet_id, topup_amount: int, user: User = Depends(check_admin)
-):
+ id: str = Body(...), amount: int = Body(...)
+) -> dict[str, str]:
try:
- wallet = await get_wallet(wallet_id)
+ await get_wallet(id)
except:
raise HTTPException(
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"}
-@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(
- user: User = Depends(check_admin),
data: UpdateSettings = Body(...),
):
settings = await update_settings(data)
return {"status": "Success", "settings": settings.dict()}
-@admin_ext.delete("/api/v1/settings/", status_code=HTTPStatus.OK)
-async def api_delete_settings(
- user: User = Depends(check_admin),
-):
+@admin_ext.delete(
+ "/api/v1/settings/", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
+)
+async def api_delete_settings() -> dict[str, str]:
await delete_settings()
return {"status": "Success"}
diff --git a/lnbits/server.py b/lnbits/server.py
index 79af8112..6d4cd2e7 100644
--- a/lnbits/server.py
+++ b/lnbits/server.py
@@ -52,6 +52,7 @@ def main(ctx, port: int, host: str, ssl_keyfile: str, ssl_certfile: str, reload:
port=port,
host=host,
reload=reload,
+ forwarded_allow_ips="*",
ssl_keyfile=ssl_keyfile,
ssl_certfile=ssl_certfile,
**d
diff --git a/lnbits/settings.py b/lnbits/settings.py
index f183211c..61dbd6f2 100644
--- a/lnbits/settings.py
+++ b/lnbits/settings.py
@@ -1,20 +1,19 @@
import importlib
import json
import subprocess
-import httpx
from os import path
from sqlite3 import Row
from typing import List, Optional
+import httpx
from loguru import logger
from pydantic import BaseSettings, Field, validator
-
def list_parse_fallback(v):
try:
return json.loads(v)
- except Exception as e:
+ except Exception:
replaced = v.replace(" ", "")
if replaced:
return replaced.split(",")
@@ -238,24 +237,36 @@ async def check_admin_settings():
http = "https" if settings.lnbits_force_https else "http"
user = settings.lnbits_admin_users[0]
- admin_url = f"{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:
+ 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
+ "X-API-KEY": settings.lnbits_saas_secret,
}
payload = {
"instance_id": settings.lnbits_saas_instance_id,
- "adminuser": user
+ "adminuser": user,
}
try:
- r = client.post(settings.lnbits_saas_callback, headers=headers, json=payload)
+ client.post(
+ settings.lnbits_saas_callback,
+ headers=headers,
+ json=payload,
+ )
logger.warning("sent admin user to saas application")
except:
- logger.error(f"error sending admin user to saas: {settings.lnbits_saas_callback}")
+ logger.error(
+ f"error sending admin user to saas: {settings.lnbits_saas_callback}"
+ )
except:
logger.error("admin.settings tables does not exist.")
diff --git a/lnbits/wallets/fake.py b/lnbits/wallets/fake.py
index 73458e8c..94ff5f48 100644
--- a/lnbits/wallets/fake.py
+++ b/lnbits/wallets/fake.py
@@ -19,7 +19,6 @@ from .base import (
class FakeWallet(Wallet):
- queue: asyncio.Queue = asyncio.Queue(0)
secret: str = settings.fake_wallet_secret
privkey: str = hashlib.pbkdf2_hmac(
"sha256",
@@ -98,6 +97,7 @@ class FakeWallet(Wallet):
return PaymentStatus(None)
async def paid_invoices_stream(self) -> AsyncGenerator[str, None]:
+ self.queue: asyncio.Queue = asyncio.Queue(0)
while True:
value: Invoice = await self.queue.get()
yield value.payment_hash
From 9dbcd89c6ebdba4db6c0bc7d70d570a8ee5fffaa Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Thu, 13 Oct 2022 15:52:02 +0100
Subject: [PATCH 205/691] added tooltips, moved reset, and warnings
---
.../admin/templates/admin/index.html | 97 ++++++++++++-------
1 file changed, 61 insertions(+), 36 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 575b377f..7d268301 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -1,8 +1,14 @@
{% extends "base.html" %} {% from "macros.jinja" import window_vars with context
%} {% block page %}
-
-
+
+
+ Save your changes
-
-
-
+
+
+ Restart the server for changes to take effect
+
+
+
+
+ Add funds to a wallet.
+
+ > -->
+
+ Delete all settings and reset to defaults.
+
@@ -121,6 +136,7 @@
show: false
},
tab: 'funding',
+ needsRestart: false,
funding_sources: new Map([
['VoidWallet', null],
[
@@ -302,13 +318,12 @@
this.balance = +'{{ balance|safe }}'
this.formData = _.clone(this.settings) //model
this.updateFundingData()
-
console.log(this.settings)
},
computed: {
checkChanges() {
return !_.isEqual(this.settings, this.formData)
- },
+ }
},
methods: {
addAdminUser() {
@@ -361,6 +376,7 @@
message: 'Success! Restarted Server',
icon: null
})
+ this.needsRestart = false
})
.catch(function (error) {
LNbits.utils.notifyApiError(error)
@@ -390,16 +406,15 @@
LNbits.utils.notifyApiError(error)
})
},
- updateFundingData(){
+ updateFundingData() {
this.settings.lnbits_allowed_funding_sources.map(f => {
let opts = this.funding_sources.get(f)
if (!opts) return
-
+
Object.keys(opts).forEach(e => {
opts[e].value = this.settings[e]
})
})
- console.log("funding", this.funding_sources)
},
updateSettings() {
let data = {
@@ -415,31 +430,41 @@
.then(response => {
this.settings = response.data.settings
this.formData = _.clone(this.settings)
+ this.needsRestart = true
this.updateFundingData()
this.$q.notify({
type: 'positive',
message: 'Success! Settings changed!',
icon: null
})
- console.log(this.settings)
})
.catch(function (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)
+ LNbits.utils
+ .confirmDialog(
+ 'Are you sure you want to restore settings to default?'
+ )
+ .onOk(() => {
+ 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
+ })
+ this.needsRestart = true
+ })
+ .catch(function (error) {
+ LNbits.utils.notifyApiError(error)
+ })
})
},
downloadBackup() {
From 31a7a87774e5fcd87962440bc8c20510f607a328 Mon Sep 17 00:00:00 2001
From: Tiago vasconcelos
Date: Thu, 13 Oct 2022 15:52:26 +0100
Subject: [PATCH 206/691] moved to columns
---
.../admin/templates/admin/_tab_funding.html | 54 +++++++++----------
1 file changed, 27 insertions(+), 27 deletions(-)
diff --git a/lnbits/extensions/admin/templates/admin/_tab_funding.html b/lnbits/extensions/admin/templates/admin/_tab_funding.html
index a523d4e5..a69ecb47 100644
--- a/lnbits/extensions/admin/templates/admin/_tab_funding.html
+++ b/lnbits/extensions/admin/templates/admin/_tab_funding.html
@@ -27,38 +27,38 @@
:options="settings.lnbits_allowed_funding_sources"
>
-
+
-
-
-
- Funding Sources (Requires server restart)
+
+ Funding Sources (Requires server restart)
+
Date: Thu, 13 Oct 2022 15:52:39 +0100
Subject: [PATCH 207/691] themes not displaying fixed
---
lnbits/extensions/admin/templates/admin/_tab_theme.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lnbits/extensions/admin/templates/admin/_tab_theme.html b/lnbits/extensions/admin/templates/admin/_tab_theme.html
index 46bf83e9..c327733f 100644
--- a/lnbits/extensions/admin/templates/admin/_tab_theme.html
+++ b/lnbits/extensions/admin/templates/admin/_tab_theme.html
@@ -63,7 +63,7 @@
Themes
Date: Fri, 21 Oct 2022 10:00:47 +0200
Subject: [PATCH 208/691] add loop to uvicorn
---
lnbits/server.py | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/lnbits/server.py b/lnbits/server.py
index 6d4cd2e7..eb7c12b1 100644
--- a/lnbits/server.py
+++ b/lnbits/server.py
@@ -1,12 +1,7 @@
-import asyncio
-
import uvloop
-
uvloop.install()
-import contextlib
import multiprocessing as mp
-import sys
import time
import click
@@ -49,6 +44,7 @@ def main(ctx, port: int, host: str, ssl_keyfile: str, ssl_certfile: str, reload:
while True:
config = uvicorn.Config(
"lnbits.__main__:app",
+ loop="uvloop",
port=port,
host=host,
reload=reload,
@@ -65,9 +61,10 @@ def main(ctx, port: int, host: str, ssl_keyfile: str, ssl_certfile: str, reload:
server_restart.clear()
server.should_exit = True
server.force_exit = True
+ time.sleep(3)
process.terminate()
process.join()
- time.sleep(3)
+ time.sleep(1)
server_restart = mp.Event()
From b14b9f3b3a48f5a2544864783de7129e8ae5bfb3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Fri, 21 Oct 2022 11:13:40 +0200
Subject: [PATCH 209/691] add get settings endpoint with only values you can
also save
---
lnbits/app.py | 6 +----
lnbits/extensions/admin/crud.py | 12 +++++++++-
lnbits/extensions/admin/models.py | 6 ++++-
.../admin/templates/admin/index.html | 22 +++++++++++++++----
lnbits/extensions/admin/views_api.py | 7 +++++-
lnbits/server.py | 1 +
6 files changed, 42 insertions(+), 12 deletions(-)
diff --git a/lnbits/app.py b/lnbits/app.py
index 49ad8d77..959a8168 100644
--- a/lnbits/app.py
+++ b/lnbits/app.py
@@ -62,10 +62,6 @@ def create_app() -> FastAPI:
CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]
)
- # TODO: why those 2?
- g().config = settings
- g().base_url = f"http://{settings.host}:{settings.port}"
-
app.add_middleware(GZipMiddleware, minimum_size=1000)
register_startup(app)
@@ -174,7 +170,7 @@ def register_assets(app: FastAPI):
@app.on_event("startup")
async def vendored_assets_variable():
- if g().config.debug:
+ if settings.debug:
g().VENDORED_JS = map(url_for_vendored, get_js_vendored())
g().VENDORED_CSS = map(url_for_vendored, get_css_vendored())
else:
diff --git a/lnbits/extensions/admin/crud.py b/lnbits/extensions/admin/crud.py
index cc937b5e..2ce91612 100644
--- a/lnbits/extensions/admin/crud.py
+++ b/lnbits/extensions/admin/crud.py
@@ -6,7 +6,7 @@ from lnbits.settings import Settings, read_only_variables
from lnbits.tasks import internal_invoice_queue
from . import db
-from .models import UpdateSettings
+from .models import AdminSettings, UpdateSettings
async def update_wallet_balance(wallet_id: str, amount: int) -> str:
@@ -26,6 +26,16 @@ async def update_wallet_balance(wallet_id: str, amount: int) -> str:
await internal_invoice_queue.put(internal_id)
+async def get_settings() -> AdminSettings:
+ row = await db.fetchone("SELECT * FROM admin.settings")
+ all_settings = Settings(**row)
+ settings = AdminSettings()
+ for key, value in row.items():
+ if hasattr(settings, key):
+ setattr(settings, key, getattr(all_settings, key))
+ return settings
+
+
async def update_settings(data: UpdateSettings) -> Settings:
fields = []
for key, value in data.dict(exclude_none=True).items():
diff --git a/lnbits/extensions/admin/models.py b/lnbits/extensions/admin/models.py
index d9d2b22f..31811659 100644
--- a/lnbits/extensions/admin/models.py
+++ b/lnbits/extensions/admin/models.py
@@ -1,4 +1,4 @@
-from typing import List
+from typing import List, Optional
from fastapi import Query
from pydantic import BaseModel
@@ -55,3 +55,7 @@ class UpdateSettings(BaseModel):
opennode_key: str = Query(None)
spark_url: str = Query(None)
spark_token: str = Query(None)
+
+
+class AdminSettings(UpdateSettings):
+ lnbits_allowed_funding_sources: Optional[List[str]]
diff --git a/lnbits/extensions/admin/templates/admin/index.html b/lnbits/extensions/admin/templates/admin/index.html
index 7d268301..10391261 100644
--- a/lnbits/extensions/admin/templates/admin/index.html
+++ b/lnbits/extensions/admin/templates/admin/index.html
@@ -314,11 +314,8 @@
}
},
created: function () {
- this.settings = JSON.parse('{{ settings|tojson|safe }}') //DB data
+ this.getSettings()
this.balance = +'{{ balance|safe }}'
- this.formData = _.clone(this.settings) //model
- this.updateFundingData()
- console.log(this.settings)
},
computed: {
checkChanges() {
@@ -416,6 +413,23 @@
})
})
},
+ getSettings() {
+ LNbits.api
+ .request(
+ 'GET',
+ '/admin/api/v1/settings/?usr=' + this.g.user.id,
+ this.g.user.wallets[0].adminkey
+ )
+ .then(response => {
+ this.settings = response.data
+ this.formData = _.clone(this.settings)
+ this.updateFundingData()
+ console.log(this.settings)
+ })
+ .catch(function (error) {
+ LNbits.utils.notifyApiError(error)
+ })
+ },
updateSettings() {
let data = {
...this.formData
diff --git a/lnbits/extensions/admin/views_api.py b/lnbits/extensions/admin/views_api.py
index 63ed5b3c..57d62ed4 100644
--- a/lnbits/extensions/admin/views_api.py
+++ b/lnbits/extensions/admin/views_api.py
@@ -10,7 +10,7 @@ from lnbits.extensions.admin import admin_ext
from lnbits.extensions.admin.models import UpdateSettings
from lnbits.server import server_restart
-from .crud import delete_settings, update_settings, update_wallet_balance
+from .crud import delete_settings, get_settings, update_settings, update_wallet_balance
@admin_ext.get(
@@ -21,6 +21,11 @@ async def api_restart_server() -> dict[str, str]:
return {"status": "Success"}
+@admin_ext.get("/api/v1/settings/", dependencies=[Depends(check_admin)])
+async def api_get_settings() -> UpdateSettings:
+ return await get_settings()
+
+
@admin_ext.put(
"/api/v1/topup/", status_code=HTTPStatus.OK, dependencies=[Depends(check_admin)]
)
diff --git a/lnbits/server.py b/lnbits/server.py
index eb7c12b1..ecf7ff62 100644
--- a/lnbits/server.py
+++ b/lnbits/server.py
@@ -1,4 +1,5 @@
import uvloop
+
uvloop.install()
import multiprocessing as mp
From 8fbf10909961c13b6c39008ae4ce3aaa750b9a51 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?dni=20=E2=9A=A1?=
Date: Tue, 25 Oct 2022 09:25:37 +0200
Subject: [PATCH 210/691] fix poetry lockCCC
---
poetry.lock | 24 +-----------------------
1 file changed, 1 insertion(+), 23 deletions(-)
diff --git a/poetry.lock b/poetry.lock
index 45968390..bbce3c5c 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -258,24 +258,6 @@ category = "main"
optional = false
python-versions = "*"
-[[package]]
-name = "environs"
-version = "9.3.3"
-description = "simplified environment variable parsing"
-category = "main"
-optional = false
-python-versions = ">=3.6"
-
-[package.dependencies]
-marshmallow = ">=3.0.0"
-python-dotenv = "*"
-
-[package.extras]
-dev = ["dj-database-url", "dj-email-url", "django-cache-url", "flake8 (==3.9.2)", "flake8-bugbear (==21.4.3)", "mypy (==0.910)", "pre-commit (>=2.4,<3.0)", "pytest", "tox"]
-django = ["dj-database-url", "dj-email-url", "django-cache-url"]
-lint = ["flake8 (==3.9.2)", "flake8-bugbear (==21.4.3)", "mypy (==0.910)", "pre-commit (>=2.4,<3.0)"]
-tests = ["dj-database-url", "dj-email-url", "django-cache-url", "pytest"]
-
[[package]]
name = "fastapi"
version = "0.78.0"
@@ -1051,7 +1033,7 @@ testing = ["func-timeout", "jaraco.itertools", "pytest (>=4.6)", "pytest-black (
[metadata]
lock-version = "1.1"
python-versions = "^3.10 | ^3.9 | ^3.8 | ^3.7"
-content-hash = "c4a01d5bfc24a8008348b6bd954717354554310afaaecbfc2a14222ad25aca42"
+content-hash = "e798b36b5941b43ee249bc196fcfb28d8ee712947336d21467651c672ba0106b"
[metadata.files]
aiofiles = [
@@ -1307,10 +1289,6 @@ enum34 = [
{file = "enum34-1.1.10-py3-none-any.whl", hash = "sha256:c3858660960c984d6ab0ebad691265180da2b43f07e061c0f8dca9ef3cffd328"},
{file = "enum34-1.1.10.tar.gz", hash = "sha256:cce6a7477ed816bd2542d03d53db9f0db935dd013b70f336a95c73979289f248"},
]
-environs = [
- {file = "environs-9.3.3-py2.py3-none-any.whl", hash = "sha256:ee5466156b50fe03aa9fec6e720feea577b5bf515d7f21b2c46608272557ba26"},
- {file = "environs-9.3.3.tar.gz", hash = "sha256:72b867ff7b553076cdd90f3ee01ecc1cf854987639c9c459f0ed0d3d44ae490c"},
-]
fastapi = [
{file = "fastapi-0.78.0-py3-none-any.whl", hash = "sha256:15fcabd5c78c266fa7ae7d8de9b384bfc2375ee0503463a6febbe3bab69d6f65"},
{file = "fastapi-0.78.0.tar.gz", hash = "sha256:3233d4a789ba018578658e2af1a4bb5e38bdd122ff722b313666a9b2c6786a83"},
From 678c269a9124a967300a34d75542ed0c0c35150a Mon Sep 17 00:00:00 2001
From: Gene Takavic
Date: Fri, 18 Nov 2022 16:57:39 +0100
Subject: [PATCH 211/691] wipe card
---
.../extensions/boltcards/static/js/index.js | 16 ++-
.../boltcards/templates/boltcards/index.html | 102 ++++++++++++++----
2 files changed, 97 insertions(+), 21 deletions(-)
diff --git a/lnbits/extensions/boltcards/static/js/index.js b/lnbits/extensions/boltcards/static/js/index.js
index e13c14fb..1949050b 100644
--- a/lnbits/extensions/boltcards/static/js/index.js
+++ b/lnbits/extensions/boltcards/static/js/index.js
@@ -150,6 +150,7 @@ new Vue({
},
qrCodeDialog: {
show: false,
+ wipe: false,
data: null
}
}
@@ -260,9 +261,10 @@ new Vue({
})
})
},
- openQrCodeDialog(cardId) {
+ openQrCodeDialog(cardId, wipe) {
var card = _.findWhere(this.cards, {id: cardId})
this.qrCodeDialog.data = {
+ id: card.id,
link: window.location.origin + '/boltcards/api/v1/auth?a=' + card.otp,
name: card.card_name,
uid: card.uid,
@@ -274,6 +276,18 @@ new Vue({
k4: card.k2,
webhook_url: card.webhook_url
}
+ this.qrCodeDialog.data_wipe = JSON.stringify({
+ action: 'wipe',
+ id: 1,
+ k0: card.k0,
+ k1: card.k1,
+ k2: card.k2,
+ k3: card.k1,
+ k4: card.k2,
+ uid: card.uid,
+ version: 1
+ })
+ this.qrCodeDialog.wipe = wipe
this.qrCodeDialog.show = true
},
addCardOpen: function () {
diff --git a/lnbits/extensions/boltcards/templates/boltcards/index.html b/lnbits/extensions/boltcards/templates/boltcards/index.html
index 7b9713e2..b80e9685 100644
--- a/lnbits/extensions/boltcards/templates/boltcards/index.html
+++ b/lnbits/extensions/boltcards/templates/boltcards/index.html
@@ -48,6 +48,7 @@
+
@@ -58,7 +59,7 @@
dense
icon="qr_code"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
- @click="openQrCodeDialog(props.row.id)"
+ @click="openQrCodeDialog(props.row.id, false)"
>
Card key credentials
@@ -99,7 +100,7 @@
flat
dense
size="xs"
- @click="deleteCard(props.row.id)"
+ @click="openQrCodeDialog(props.row.id, true)"
icon="cancel"
color="pink"
>
@@ -367,21 +368,61 @@
{% raw %}
-
-
-
-
- (Keys for
- Boltcard NFC Card Creator)
-
+
+
+
+
+
+ (QR for create the card in
+ Boltcard NFC Card Creator)
+
+
+
+
+
+ (QR for for wipe the card in
+ Boltcard NFC Card Creator)
+
+
+
+
+
+
Name: {{ qrCodeDialog.data.name }}
UID: {{ qrCodeDialog.data.uid }}
@@ -398,11 +439,32 @@
outline
color="grey"
@click="copyText(qrCodeDialog.data.link)"
- label="Keys/Auth link"
+ label="Create link"
+ v-show="!qrCodeDialog.wipe"
>
+ Click to copy, then paste to NFC Card Creator
+
+
+ Click to copy, then paste to NFC Card Creator
+
+
+ Backup the keys, or wipe the card first!
- Click to copy, then add to NFC card
-
{% endraw %}
Close
From 8d05cddc877f2e00a7c542c034a91a6c13db5493 Mon Sep 17 00:00:00 2001
From: Gene Takavic
Date: Sat, 19 Nov 2022 13:50:53 +0100
Subject: [PATCH 212/691] wipe card readme
---
lnbits/extensions/boltcards/README.md | 17 +++++++++++++++--
lnbits/extensions/boltcards/static/js/index.js | 1 -
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/lnbits/extensions/boltcards/README.md b/lnbits/extensions/boltcards/README.md
index 5140ecc2..f612ae2f 100644
--- a/lnbits/extensions/boltcards/README.md
+++ b/lnbits/extensions/boltcards/README.md
@@ -21,7 +21,7 @@ The key #00, K0 (also know as auth key) is skipped to be used as authentificatio
***Always backup all keys that you're trying to write on the card. Without them you may not be able to change them in the future!***
## Setting the card - Boltcard NFC Card Creator (easy way)
-Updated for v0.1.1
+Updated for v0.1.2
- Add new card in the extension.
- Set a max sats per transaction. Any transaction greater than this amount will be rejected.
@@ -38,7 +38,20 @@ Updated for v0.1.1
- Click the QR code button next to a card to view its details. Backup the keys now! They'll be comfortable in your password manager.
- Now you can scan the QR code with the Android app (Create Bolt Card -> SCAN QR CODE).
- Or you can Click the "KEYS / AUTH LINK" button to copy the auth URL to the clipboard. Then paste it into the Android app (Create Bolt Card -> PASTE AUTH URL).
-- Click WRITE CARD NOW and tap the NFC card to set it up. DO NOT REMOVE THE CARD PREMATURELY!
+- Click WRITE CARD NOW and approach the NFC card to set it up. DO NOT REMOVE THE CARD PREMATURELY!
+
+## Erasing the card - Boltcard NFC Card Creator
+Updated for v0.1.2
+
+Since v0.1.2 of Boltcard NFC Card Creator it is possible not only reset the keys but also disable the SUN function and do the complete erase so the card can be use again as a static tag (or set as a new Bolt Card, ofc).
+
+- Click the QR code button next to a card to view its details and select WIPE
+- OR click the red cross icon on the right side to reach the same
+- In the android app (Advanced -> Reset Keys)
+ - Click SCAN QR CODE to scan the QR
+ - Or click WIPE DATA in LNbits to copy and paste in to the app (PASTE KEY JSON)
+- Click RESET CARD NOW and approach the NFC card to erase it. DO NOT REMOVE THE CARD PREMATURELY!
+- Now if there is all success the card can be safely delete from LNbits (but keep the keys backuped anyway; batter safe than brick).
## Setting the card - computer (hard way)
diff --git a/lnbits/extensions/boltcards/static/js/index.js b/lnbits/extensions/boltcards/static/js/index.js
index 1949050b..95a95afc 100644
--- a/lnbits/extensions/boltcards/static/js/index.js
+++ b/lnbits/extensions/boltcards/static/js/index.js
@@ -278,7 +278,6 @@ new Vue({
}
this.qrCodeDialog.data_wipe = JSON.stringify({
action: 'wipe',
- id: 1,
k0: card.k0,
k1: card.k1,
k2: card.k2,
From 95ad55775df5ad625997b568662f086d42deb13b Mon Sep 17 00:00:00 2001
From: Gene Takavic
Date: Sun, 20 Nov 2022 09:51:54 +0100
Subject: [PATCH 213/691] fixes
---
.../boltcards/templates/boltcards/index.html | 37 ++++++++++---------
1 file changed, 19 insertions(+), 18 deletions(-)
diff --git a/lnbits/extensions/boltcards/templates/boltcards/index.html b/lnbits/extensions/boltcards/templates/boltcards/index.html
index b80e9685..15af9db5 100644
--- a/lnbits/extensions/boltcards/templates/boltcards/index.html
+++ b/lnbits/extensions/boltcards/templates/boltcards/index.html
@@ -379,16 +379,16 @@
:options="{width: 800}"
class="rounded-borders"
>
-
-
- (QR for create the card in
- Boltcard NFC Card Creator)
-
+
+ (QR for create the card in
+ Boltcard NFC Card Creator)
+
-
- (QR for for wipe the card in
- Boltcard NFC Card Creator)
-
+
+ (QR for for wipe the card in
+ Boltcard NFC Card Creator)
+
-