feat: basic account UI
This commit is contained in:
parent
2099a8b7bb
commit
d0f38346e3
7 changed files with 116 additions and 16 deletions
12
crud.py
12
crud.py
|
|
@ -374,3 +374,15 @@ async def get_account(
|
||||||
)
|
)
|
||||||
|
|
||||||
return NostrAccount.from_row(row) if row else None
|
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]
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ async def m001_initial(db):
|
||||||
CREATE TABLE nostrrelay.accounts (
|
CREATE TABLE nostrrelay.accounts (
|
||||||
relay_id TEXT NOT NULL,
|
relay_id TEXT NOT NULL,
|
||||||
pubkey TEXT NOT NULL,
|
pubkey TEXT NOT NULL,
|
||||||
|
sats {db.big_int} DEFAULT 0,
|
||||||
storage {db.big_int} DEFAULT 0,
|
storage {db.big_int} DEFAULT 0,
|
||||||
paid_to_join BOOLEAN DEFAULT false,
|
paid_to_join BOOLEAN DEFAULT false,
|
||||||
allowed BOOLEAN DEFAULT false,
|
allowed BOOLEAN DEFAULT false,
|
||||||
|
|
|
||||||
10
models.py
10
models.py
|
|
@ -344,14 +344,18 @@ class BuyOrder(BaseModel):
|
||||||
def is_valid_action(self):
|
def is_valid_action(self):
|
||||||
return self.action in ["join", "storage"]
|
return self.action in ["join", "storage"]
|
||||||
|
|
||||||
|
class NostrPartialAccount(BaseModel):
|
||||||
|
relay_id: str
|
||||||
|
pubkey: str
|
||||||
|
allowed: Optional[bool]
|
||||||
|
blocked: Optional[bool]
|
||||||
class NostrAccount(BaseModel):
|
class NostrAccount(BaseModel):
|
||||||
pubkey: str
|
pubkey: str
|
||||||
|
allowed = False
|
||||||
|
blocked = False
|
||||||
sats = 0
|
sats = 0
|
||||||
storage = 0
|
storage = 0
|
||||||
paid_to_join = False
|
paid_to_join = False
|
||||||
allowed = False
|
|
||||||
blocked = False
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def null_account(cls) -> "NostrAccount":
|
def null_account(cls) -> "NostrAccount":
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
<q-tab name="info" label="Relay Info"></q-tab>
|
<q-tab name="info" label="Relay Info"></q-tab>
|
||||||
<q-tab name="payment" label="Payment"></q-tab>
|
<q-tab name="payment" label="Payment"></q-tab>
|
||||||
<q-tab name="config" label="Config"></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-tabs>
|
||||||
<q-tab-panels v-model="tab">
|
<q-tab-panels v-model="tab">
|
||||||
<q-tab-panel name="info">
|
<q-tab-panel name="info">
|
||||||
|
|
@ -527,7 +527,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
<q-tab-panel name="access">
|
<q-tab-panel name="accounts">
|
||||||
<div v-if="relay">
|
<div v-if="relay">
|
||||||
<div class="row items-center no-wrap q-mb-md">
|
<div class="row items-center no-wrap q-mb-md">
|
||||||
<div class="col-2 q-pr-lg">Public Key: </div>
|
<div class="col-2 q-pr-lg">Public Key: </div>
|
||||||
|
|
|
||||||
|
|
@ -114,9 +114,29 @@ async function relayDetails(path) {
|
||||||
this.relay.config.wallet =
|
this.relay.config.wallet =
|
||||||
this.relay.config.wallet || this.walletOptions[0].value
|
this.relay.config.wallet || this.walletOptions[0].value
|
||||||
},
|
},
|
||||||
allowPublicKey: function () {
|
allowPublicKey: async function () {
|
||||||
this.relay.config.allowedPublicKeys.push(this.allowedPubkey)
|
try {
|
||||||
this.allowedPubkey = ''
|
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 () {
|
blockPublicKey: function () {
|
||||||
this.relay.config.blockedPublicKeys.push(this.blockedPubkey)
|
this.relay.config.blockedPublicKeys.push(this.blockedPubkey)
|
||||||
|
|
|
||||||
14
tasks.py
14
tasks.py
|
|
@ -27,21 +27,21 @@ async def on_invoice_paid(payment: Payment):
|
||||||
pubkey = payment.extra.get("pubkey")
|
pubkey = payment.extra.get("pubkey")
|
||||||
|
|
||||||
if payment.extra.get("action") == "join":
|
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
|
return
|
||||||
|
|
||||||
if payment.extra.get("action") == "storage":
|
if payment.extra.get("action") == "storage":
|
||||||
storage_to_buy = payment.extra.get("storage_to_buy")
|
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
|
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:
|
try:
|
||||||
account = await get_account(relay_id, pubkey)
|
account = await get_account(relay_id, pubkey)
|
||||||
if not account:
|
if not account:
|
||||||
await create_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
|
return
|
||||||
|
|
||||||
|
|
@ -49,18 +49,19 @@ async def invoice_paid_to_join(relay_id: str, pubkey: str):
|
||||||
return
|
return
|
||||||
|
|
||||||
account.paid_to_join = True
|
account.paid_to_join = True
|
||||||
|
account.sats += amount
|
||||||
await update_account(relay_id, account)
|
await update_account(relay_id, account)
|
||||||
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
logger.warning(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:
|
try:
|
||||||
account = await get_account(relay_id, pubkey)
|
account = await get_account(relay_id, pubkey)
|
||||||
if not account:
|
if not account:
|
||||||
await create_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
|
return
|
||||||
|
|
||||||
|
|
@ -68,6 +69,7 @@ async def invoice_paid_for_storage(relay_id: str, pubkey: str, storage_to_buy: i
|
||||||
return
|
return
|
||||||
|
|
||||||
account.storage = storage_to_buy
|
account.storage = storage_to_buy
|
||||||
|
account.sats += amount
|
||||||
await update_account(relay_id, account)
|
await update_account(relay_id, account)
|
||||||
|
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
|
|
|
||||||
65
views_api.py
65
views_api.py
|
|
@ -18,16 +18,20 @@ from lnbits.helpers import urlsafe_short_hash
|
||||||
from . import nostrrelay_ext
|
from . import nostrrelay_ext
|
||||||
from .client_manager import NostrClientConnection, NostrClientManager
|
from .client_manager import NostrClientConnection, NostrClientManager
|
||||||
from .crud import (
|
from .crud import (
|
||||||
|
create_account,
|
||||||
create_relay,
|
create_relay,
|
||||||
delete_all_events,
|
delete_all_events,
|
||||||
delete_relay,
|
delete_relay,
|
||||||
|
get_account,
|
||||||
|
get_accounts,
|
||||||
get_relay,
|
get_relay,
|
||||||
get_relay_by_id,
|
get_relay_by_id,
|
||||||
get_relays,
|
get_relays,
|
||||||
|
update_account,
|
||||||
update_relay,
|
update_relay,
|
||||||
)
|
)
|
||||||
from .helpers import extract_domain, normalize_public_key
|
from .helpers import extract_domain, normalize_public_key
|
||||||
from .models import BuyOrder, NostrRelay
|
from .models import BuyOrder, NostrAccount, NostrPartialAccount, NostrRelay
|
||||||
|
|
||||||
client_manager = NostrClientManager()
|
client_manager = NostrClientManager()
|
||||||
|
|
||||||
|
|
@ -141,6 +145,64 @@ async def api_get_relay(
|
||||||
return 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}")
|
@nostrrelay_ext.delete("/api/v1/relay/{relay_id}")
|
||||||
async def api_delete_relay(
|
async def api_delete_relay(
|
||||||
relay_id: str, wallet: WalletTypeInfo = Depends(require_admin_key)
|
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,
|
"storage_to_buy": storage_to_buy,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
print("### payment_request", payment_request)
|
|
||||||
return {"invoice": payment_request}
|
return {"invoice": payment_request}
|
||||||
except ValueError as ex:
|
except ValueError as ex:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue