feat: basic account UI

This commit is contained in:
Vlad Stan 2023-02-15 14:17:01 +02:00
parent 2099a8b7bb
commit d0f38346e3
7 changed files with 116 additions and 16 deletions

12
crud.py
View file

@ -374,3 +374,15 @@ async def get_account(
)
return NostrAccount.from_row(row) if row else None
async def get_accounts(
relay_id: str,
allowed = True,
blocked = False,
) -> List[NostrAccount]:
rows = await db.fetchall(
"SELECT * FROM nostrrelay.accounts WHERE relay_id = ? AND allowed = ? AND blocked = ?",
(relay_id, allowed, blocked),
)
return [NostrAccount.from_row(row) for row in rows]

View file

@ -52,6 +52,7 @@ async def m001_initial(db):
CREATE TABLE nostrrelay.accounts (
relay_id TEXT NOT NULL,
pubkey TEXT NOT NULL,
sats {db.big_int} DEFAULT 0,
storage {db.big_int} DEFAULT 0,
paid_to_join BOOLEAN DEFAULT false,
allowed BOOLEAN DEFAULT false,

View file

@ -344,14 +344,18 @@ class BuyOrder(BaseModel):
def is_valid_action(self):
return self.action in ["join", "storage"]
class NostrPartialAccount(BaseModel):
relay_id: str
pubkey: str
allowed: Optional[bool]
blocked: Optional[bool]
class NostrAccount(BaseModel):
pubkey: str
allowed = False
blocked = False
sats = 0
storage = 0
paid_to_join = False
allowed = False
blocked = False
@classmethod
def null_account(cls) -> "NostrAccount":

View file

@ -3,7 +3,7 @@
<q-tab name="info" label="Relay Info"></q-tab>
<q-tab name="payment" label="Payment"></q-tab>
<q-tab name="config" label="Config"></q-tab>
<q-tab name="access" label="Access"></q-tab>
<q-tab name="accounts" label="Accounts"></q-tab>
</q-tabs>
<q-tab-panels v-model="tab">
<q-tab-panel name="info">
@ -527,7 +527,7 @@
</div>
</div>
</q-tab-panel>
<q-tab-panel name="access">
<q-tab-panel name="accounts">
<div v-if="relay">
<div class="row items-center no-wrap q-mb-md">
<div class="col-2 q-pr-lg">Public Key: </div>

View file

@ -114,9 +114,29 @@ async function relayDetails(path) {
this.relay.config.wallet =
this.relay.config.wallet || this.walletOptions[0].value
},
allowPublicKey: function () {
this.relay.config.allowedPublicKeys.push(this.allowedPubkey)
allowPublicKey: async function () {
try {
const {data} = await LNbits.api.request(
'PUT',
'/nostrrelay/api/v1/account',
this.adminkey,
{
pubkey: this.allowedPubkey,
allowed: true
}
)
this.relay = data
this.$emit('relay-updated', this.relay)
this.$q.notify({
type: 'positive',
message: 'Account Updated',
timeout: 5000
})
this.allowedPubkey = ''
} catch (error) {
LNbits.utils.notifyApiError(error)
}
},
blockPublicKey: function () {
this.relay.config.blockedPublicKeys.push(this.blockedPubkey)

View file

@ -27,21 +27,21 @@ async def on_invoice_paid(payment: Payment):
pubkey = payment.extra.get("pubkey")
if payment.extra.get("action") == "join":
await invoice_paid_to_join(relay_id, pubkey)
await invoice_paid_to_join(relay_id, pubkey, payment.amount)
return
if payment.extra.get("action") == "storage":
storage_to_buy = payment.extra.get("storage_to_buy")
await invoice_paid_for_storage(relay_id, pubkey, storage_to_buy)
await invoice_paid_for_storage(relay_id, pubkey, storage_to_buy, payment.amount)
return
async def invoice_paid_to_join(relay_id: str, pubkey: str):
async def invoice_paid_to_join(relay_id: str, pubkey: str, amount: int):
try:
account = await get_account(relay_id, pubkey)
if not account:
await create_account(
relay_id, NostrAccount(pubkey=pubkey, paid_to_join=True)
relay_id, NostrAccount(pubkey=pubkey, paid_to_join=True, sats=amount)
)
return
@ -49,18 +49,19 @@ async def invoice_paid_to_join(relay_id: str, pubkey: str):
return
account.paid_to_join = True
account.sats += amount
await update_account(relay_id, account)
except Exception as ex:
logger.warning(ex)
async def invoice_paid_for_storage(relay_id: str, pubkey: str, storage_to_buy: int):
async def invoice_paid_for_storage(relay_id: str, pubkey: str, storage_to_buy: int, amount: str):
try:
account = await get_account(relay_id, pubkey)
if not account:
await create_account(
relay_id, NostrAccount(pubkey=pubkey, storage=storage_to_buy)
relay_id, NostrAccount(pubkey=pubkey, storage=storage_to_buy, sats=amount)
)
return
@ -68,6 +69,7 @@ async def invoice_paid_for_storage(relay_id: str, pubkey: str, storage_to_buy: i
return
account.storage = storage_to_buy
account.sats += amount
await update_account(relay_id, account)
except Exception as ex:

View file

@ -18,16 +18,20 @@ from lnbits.helpers import urlsafe_short_hash
from . import nostrrelay_ext
from .client_manager import NostrClientConnection, NostrClientManager
from .crud import (
create_account,
create_relay,
delete_all_events,
delete_relay,
get_account,
get_accounts,
get_relay,
get_relay_by_id,
get_relays,
update_account,
update_relay,
)
from .helpers import extract_domain, normalize_public_key
from .models import BuyOrder, NostrRelay
from .models import BuyOrder, NostrAccount, NostrPartialAccount, NostrRelay
client_manager = NostrClientManager()
@ -141,6 +145,64 @@ async def api_get_relay(
return relay
@nostrrelay_ext.put("/api/v1/account")
async def api_create_or_update_account(
data: NostrPartialAccount,
wallet: WalletTypeInfo = Depends(require_admin_key),
) -> NostrAccount:
try:
data.pubkey = normalize_public_key(data.pubkey)
account = await get_account(data.relay_id, data.pubkey)
if not account:
return await create_account(data.relay_id, NostrAccount.parse_obj(data.dict()))
if data.blocked is not None:
account.blocked = data.blocked
if data.allowed is not None:
account.allowed = data.allowed
return await update_account(data.relay_id, account)
except ValueError as ex:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail=str(ex),
)
except HTTPException as ex:
raise ex
except Exception as ex:
logger.warning(ex)
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail="Cannot create account",
)
@nostrrelay_ext.get("/api/v1/account")
async def api_get_accounts(
relay_id: str, allowed: bool, blocked: bool, wallet: WalletTypeInfo = Depends(require_invoice_key)
) -> List[NostrAccount]:
try:
# make sure the user has access to the relay
relay = await get_relay(wallet.wallet.user, relay_id)
accounts = await get_accounts(relay.id, allowed, blocked)
return accounts
except ValueError as ex:
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail=str(ex),
)
except HTTPException as ex:
raise ex
except Exception as ex:
logger.warning(ex)
raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail="Cannot fetch accounts",
)
@nostrrelay_ext.delete("/api/v1/relay/{relay_id}")
async def api_delete_relay(
relay_id: str, wallet: WalletTypeInfo = Depends(require_admin_key)
@ -193,7 +255,6 @@ async def api_pay_to_join(data: BuyOrder):
"storage_to_buy": storage_to_buy,
},
)
print("### payment_request", payment_request)
return {"invoice": payment_request}
except ValueError as ex:
raise HTTPException(