feat: mage block/allow accounts
This commit is contained in:
parent
2c5dfbbf92
commit
5a984bddcd
5 changed files with 188 additions and 58 deletions
|
|
@ -299,12 +299,6 @@ class NostrClientConnection:
|
||||||
if self._exceeded_max_events_per_second():
|
if self._exceeded_max_events_per_second():
|
||||||
return False, f"Exceeded max events per second limit'!"
|
return False, f"Exceeded max events per second limit'!"
|
||||||
|
|
||||||
if not self.client_config.is_author_allowed(e.pubkey):
|
|
||||||
return (
|
|
||||||
False,
|
|
||||||
f"Public key '{e.pubkey}' is not allowed in relay '{self.relay_id}'!",
|
|
||||||
)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
e.check_signature()
|
e.check_signature()
|
||||||
except ValueError:
|
except ValueError:
|
||||||
|
|
@ -326,7 +320,13 @@ class NostrClientConnection:
|
||||||
if not account:
|
if not account:
|
||||||
account = NostrAccount.null_account()
|
account = NostrAccount.null_account()
|
||||||
|
|
||||||
if not account.paid_to_join and self.client_config.is_paid_relay:
|
if account.blocked:
|
||||||
|
return (
|
||||||
|
False,
|
||||||
|
f"Public key '{pubkey}' is not allowed in relay '{self.relay_id}'!",
|
||||||
|
)
|
||||||
|
|
||||||
|
if not account.can_join and self.client_config.is_paid_relay:
|
||||||
return False, f"This is a paid relay: '{self.relay_id}'"
|
return False, f"This is a paid relay: '{self.relay_id}'"
|
||||||
|
|
||||||
stored_bytes = await get_storage_for_public_key(self.relay_id, pubkey)
|
stored_bytes = await get_storage_for_public_key(self.relay_id, pubkey)
|
||||||
|
|
|
||||||
19
models.py
19
models.py
|
|
@ -83,18 +83,6 @@ class PaymentSpec(BaseModel):
|
||||||
storage_cost_unit = Field("MB", alias="storageCostUnit")
|
storage_cost_unit = Field("MB", alias="storageCostUnit")
|
||||||
|
|
||||||
|
|
||||||
class AuthorSpec(Spec):
|
|
||||||
allowed_public_keys = Field([], alias="allowedPublicKeys")
|
|
||||||
blocked_public_keys = Field([], alias="blockedPublicKeys")
|
|
||||||
|
|
||||||
def is_author_allowed(self, p: str) -> bool:
|
|
||||||
if p in self.blocked_public_keys:
|
|
||||||
return False
|
|
||||||
if len(self.allowed_public_keys) == 0:
|
|
||||||
return True
|
|
||||||
# todo: check payment
|
|
||||||
return p in self.allowed_public_keys
|
|
||||||
|
|
||||||
|
|
||||||
class WalletSpec(Spec):
|
class WalletSpec(Spec):
|
||||||
wallet = Field("")
|
wallet = Field("")
|
||||||
|
|
@ -108,7 +96,7 @@ class RelayPublicSpec(FilterSpec, EventSpec, StorageSpec, PaymentSpec):
|
||||||
self.free_storage_value == 0 and not self.is_paid_relay
|
self.free_storage_value == 0 and not self.is_paid_relay
|
||||||
|
|
||||||
|
|
||||||
class RelaySpec(RelayPublicSpec, AuthorSpec, WalletSpec, AuthSpec):
|
class RelaySpec(RelayPublicSpec, WalletSpec, AuthSpec):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -357,6 +345,11 @@ class NostrAccount(BaseModel):
|
||||||
storage = 0
|
storage = 0
|
||||||
paid_to_join = False
|
paid_to_join = False
|
||||||
|
|
||||||
|
@property
|
||||||
|
def can_join(self):
|
||||||
|
"""If an account is explicitly allowed then it does not need to pay"""
|
||||||
|
return self.paid_to_join or self.allowed
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def null_account(cls) -> "NostrAccount":
|
def null_account(cls) -> "NostrAccount":
|
||||||
return NostrAccount(pubkey="")
|
return NostrAccount(pubkey="")
|
||||||
|
|
|
||||||
|
|
@ -526,33 +526,101 @@
|
||||||
</q-tab-panel>
|
</q-tab-panel>
|
||||||
<q-tab-panel name="accounts">
|
<q-tab-panel name="accounts">
|
||||||
<div v-if="relay">
|
<div v-if="relay">
|
||||||
|
<q-card
|
||||||
|
><q-card-section>
|
||||||
|
<div class="row items-center no-wrap q-mb-md">
|
||||||
|
<div class="col-2 q-pr-lg">Public Key:</div>
|
||||||
|
<div class="col-6 q-pr-lg">
|
||||||
|
<q-input
|
||||||
|
filled
|
||||||
|
dense
|
||||||
|
v-model.trim="accountPubkey"
|
||||||
|
type="text"
|
||||||
|
></q-input>
|
||||||
|
</div>
|
||||||
|
<div class="col-2 q-pr-md">
|
||||||
|
<q-btn
|
||||||
|
unelevated
|
||||||
|
color="green"
|
||||||
|
class="float-right"
|
||||||
|
@click="allowPublicKey(accountPubkey, true)"
|
||||||
|
>Allow</q-btn
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="col-2">
|
||||||
|
<q-btn
|
||||||
|
unelevated
|
||||||
|
color="pink"
|
||||||
|
class="float-right"
|
||||||
|
@click="blockPublicKey(accountPubkey, true)"
|
||||||
|
>Block</q-btn
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</q-card-section>
|
||||||
|
</q-card>
|
||||||
|
<q-separator></q-separator>
|
||||||
<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-3 q-pr-lg">Filter:</div>
|
||||||
<div class="col-6 q-pr-lg">
|
<div class="col-9 q-pr-lg">
|
||||||
<q-input
|
<q-toggle
|
||||||
filled
|
size="sm"
|
||||||
|
color="secodary"
|
||||||
|
class="q-mr-lg"
|
||||||
|
v-model="showAllowedAccounts"
|
||||||
|
@input="getAccounts()"
|
||||||
|
>Show Allowed Account</q-toggle
|
||||||
|
>
|
||||||
|
<q-toggle
|
||||||
|
size="sm"
|
||||||
|
color="secodary"
|
||||||
|
class="q-mr-lg"
|
||||||
|
v-model="showBlockedAccounts"
|
||||||
|
@input="getAccounts()"
|
||||||
|
>
|
||||||
|
Show Blocked Accounts</q-toggle
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<q-separator></q-separator>
|
||||||
|
<div class="row items-center no-wrap q-mb-md">
|
||||||
|
<div class="col-12 q-pr-lg">
|
||||||
|
<q-table
|
||||||
|
flat
|
||||||
dense
|
dense
|
||||||
v-model.trim="accountPubkey"
|
:data="accounts"
|
||||||
type="text"
|
row-key="pubkey"
|
||||||
></q-input>
|
:columns="accountsTable.columns"
|
||||||
</div>
|
:pagination.sync="accountsTable.pagination"
|
||||||
<div class="col-2 q-pr-md">
|
:filter="accountsFilter"
|
||||||
<q-btn
|
|
||||||
unelevated
|
|
||||||
color="green"
|
|
||||||
class="float-right"
|
|
||||||
@click="allowPublicKey(true)"
|
|
||||||
>Allow</q-btn
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div class="col-2">
|
|
||||||
<q-btn
|
|
||||||
unelevated
|
|
||||||
color="pink"
|
|
||||||
class="float-right"
|
|
||||||
@click="blockPublicKey(true)"
|
|
||||||
>Block</q-btn
|
|
||||||
>
|
>
|
||||||
|
<template v-slot:body="props">
|
||||||
|
<q-tr :props="props">
|
||||||
|
<q-td key="pubkey" :props="props">
|
||||||
|
{{props.row.pubkey}}
|
||||||
|
</q-td>
|
||||||
|
<q-td key="allowed" :props="props">
|
||||||
|
<q-toggle
|
||||||
|
size="sm"
|
||||||
|
color="secodary"
|
||||||
|
v-model="props.row.allowed"
|
||||||
|
@input="togglePublicKey(props.row, 'allow')"
|
||||||
|
></q-toggle>
|
||||||
|
</q-td>
|
||||||
|
<q-td key="blocked" :props="props">
|
||||||
|
<q-toggle
|
||||||
|
size="sm"
|
||||||
|
color="secodary"
|
||||||
|
v-model="props.row.blocked"
|
||||||
|
@input="togglePublicKey(props.row, 'block')"
|
||||||
|
></q-toggle>
|
||||||
|
</q-td>
|
||||||
|
<q-td auto-width> {{props.row.paid_to_join}} </q-td>
|
||||||
|
<q-td auto-width> {{props.row.sats}} </q-td>
|
||||||
|
<q-td auto-width> {{props.row.storage}} </q-td>
|
||||||
|
</q-tr>
|
||||||
|
</template>
|
||||||
|
</q-table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@ async function relayDetails(path) {
|
||||||
return {
|
return {
|
||||||
tab: 'info',
|
tab: 'info',
|
||||||
relay: null,
|
relay: null,
|
||||||
|
accounts: [],
|
||||||
accountPubkey: '',
|
accountPubkey: '',
|
||||||
formDialogItem: {
|
formDialogItem: {
|
||||||
show: false,
|
show: false,
|
||||||
|
|
@ -17,6 +18,52 @@ async function relayDetails(path) {
|
||||||
description: ''
|
description: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
accountsFilter: '',
|
||||||
|
showBlockedAccounts: true,
|
||||||
|
showAllowedAccounts: false,
|
||||||
|
accountsTable: {
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
name: 'pubkey',
|
||||||
|
align: 'left',
|
||||||
|
label: 'Public Key',
|
||||||
|
field: 'pubkey'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'allowed',
|
||||||
|
align: 'left',
|
||||||
|
label: 'Allowed',
|
||||||
|
field: 'allowed'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'blocked',
|
||||||
|
align: 'left',
|
||||||
|
label: 'Blocked',
|
||||||
|
field: 'blocked'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'paid_to_join',
|
||||||
|
align: 'left',
|
||||||
|
label: 'Paid to join',
|
||||||
|
field: 'paid_to_join'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'sats',
|
||||||
|
align: 'left',
|
||||||
|
label: 'Spent Sats',
|
||||||
|
field: 'sats'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'storage',
|
||||||
|
align: 'left',
|
||||||
|
label: 'Storage',
|
||||||
|
field: 'storage'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
pagination: {
|
||||||
|
rowsPerPage: 10
|
||||||
|
}
|
||||||
|
},
|
||||||
skipEventKind: 0,
|
skipEventKind: 0,
|
||||||
forceEventKind: 0
|
forceEventKind: 0
|
||||||
}
|
}
|
||||||
|
|
@ -113,11 +160,39 @@ 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: async function (allowed) {
|
getAccounts: async function () {
|
||||||
await this.updatePublicKey({allowed})
|
try {
|
||||||
|
const {data} = await LNbits.api.request(
|
||||||
|
'GET',
|
||||||
|
`/nostrrelay/api/v1/account?relay_id=${this.relay.id}&allowed=${this.showAllowedAccounts}&blocked=${this.showBlockedAccounts}`,
|
||||||
|
this.inkey
|
||||||
|
)
|
||||||
|
this.accounts = data
|
||||||
|
|
||||||
|
console.log('### this.accounts', this.accounts)
|
||||||
|
} catch (error) {
|
||||||
|
LNbits.utils.notifyApiError(error)
|
||||||
|
}
|
||||||
},
|
},
|
||||||
blockPublicKey: async function (blocked = true) {
|
allowPublicKey: async function (pubkey, allowed) {
|
||||||
await this.updatePublicKey({blocked})
|
await this.updatePublicKey({pubkey, allowed})
|
||||||
|
},
|
||||||
|
blockPublicKey: async function (pubkey, blocked = true) {
|
||||||
|
await this.updatePublicKey({pubkey, blocked})
|
||||||
|
},
|
||||||
|
togglePublicKey: async function (account, action) {
|
||||||
|
if (action === 'allow') {
|
||||||
|
await this.updatePublicKey({
|
||||||
|
pubkey: account.pubkey,
|
||||||
|
allowed: account.allowed
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (action === 'block') {
|
||||||
|
await this.updatePublicKey({
|
||||||
|
pubkey: account.pubkey,
|
||||||
|
blocked: account.blocked
|
||||||
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
updatePublicKey: async function (ops) {
|
updatePublicKey: async function (ops) {
|
||||||
try {
|
try {
|
||||||
|
|
@ -127,7 +202,7 @@ async function relayDetails(path) {
|
||||||
this.adminkey,
|
this.adminkey,
|
||||||
{
|
{
|
||||||
relay_id: this.relay.id,
|
relay_id: this.relay.id,
|
||||||
pubkey: this.accountPubkey,
|
pubkey: ops.pubkey,
|
||||||
allowed: ops.allowed,
|
allowed: ops.allowed,
|
||||||
blocked: ops.blocked
|
blocked: ops.blocked
|
||||||
}
|
}
|
||||||
|
|
@ -138,18 +213,11 @@ async function relayDetails(path) {
|
||||||
timeout: 5000
|
timeout: 5000
|
||||||
})
|
})
|
||||||
this.accountPubkey = ''
|
this.accountPubkey = ''
|
||||||
|
await this.getAccounts()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
LNbits.utils.notifyApiError(error)
|
LNbits.utils.notifyApiError(error)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deleteAllowedPublicKey: function (pubKey) {
|
|
||||||
this.relay.config.allowedPublicKeys =
|
|
||||||
this.relay.config.allowedPublicKeys.filter(p => p !== pubKey)
|
|
||||||
},
|
|
||||||
deleteBlockedPublicKey: function (pubKey) {
|
|
||||||
this.relay.config.blockedPublicKeys =
|
|
||||||
this.relay.config.blockedPublicKeys.filter(p => p !== pubKey)
|
|
||||||
},
|
|
||||||
|
|
||||||
addSkipAuthForEvent: function () {
|
addSkipAuthForEvent: function () {
|
||||||
value = +this.skipEventKind
|
value = +this.skipEventKind
|
||||||
|
|
@ -179,6 +247,7 @@ async function relayDetails(path) {
|
||||||
|
|
||||||
created: async function () {
|
created: async function () {
|
||||||
await this.getRelay()
|
await this.getRelay()
|
||||||
|
await this.getAccounts()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ async def api_create_or_update_account(
|
||||||
|
|
||||||
@nostrrelay_ext.get("/api/v1/account")
|
@nostrrelay_ext.get("/api/v1/account")
|
||||||
async def api_get_accounts(
|
async def api_get_accounts(
|
||||||
relay_id: str, allowed: bool, blocked: bool, wallet: WalletTypeInfo = Depends(require_invoice_key)
|
relay_id: str, allowed = False, blocked = True, wallet: WalletTypeInfo = Depends(require_invoice_key)
|
||||||
) -> List[NostrAccount]:
|
) -> List[NostrAccount]:
|
||||||
try:
|
try:
|
||||||
# make sure the user has access to the relay
|
# make sure the user has access to the relay
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue