This commit is contained in:
benarc 2024-02-01 17:18:55 +00:00
parent 66d44f95fb
commit 2cac36be17
12 changed files with 272 additions and 311 deletions

View file

@ -8,9 +8,7 @@ from lnbits.tasks import catch_everything_and_restart
db = Database("ext_myextension") db = Database("ext_myextension")
myextension_ext: APIRouter = APIRouter( myextension_ext: APIRouter = APIRouter(prefix="/myextension", tags=["MyExtension"])
prefix="/myextension", tags=["MyExtension"]
)
temp_static_files = [ temp_static_files = [
{ {
@ -19,14 +17,17 @@ temp_static_files = [
} }
] ]
def myextension_renderer(): def myextension_renderer():
return template_renderer(["myextension/templates"]) return template_renderer(["myextension/templates"])
from .lnurl import * from .lnurl import *
from .tasks import wait_for_paid_invoices from .tasks import wait_for_paid_invoices
from .views import * from .views import *
from .views_api import * from .views_api import *
def myextension_start(): def myextension_start():
loop = asyncio.get_event_loop() loop = asyncio.get_event_loop()
loop.create_task(catch_everything_and_restart(wait_for_paid_invoices)) loop.create_task(catch_everything_and_restart(wait_for_paid_invoices))

51
crud.py
View file

@ -9,7 +9,10 @@ from fastapi import Request
from lnurl import encode as lnurl_encode from lnurl import encode as lnurl_encode
import shortuuid import shortuuid
async def create_myextension(wallet_id: str, data: CreateMyExtensionData, req: Request) -> MyExtension:
async def create_myextension(
wallet_id: str, data: CreateMyExtensionData, req: Request
) -> MyExtension:
myextension_id = urlsafe_short_hash() myextension_id = urlsafe_short_hash()
await db.execute( await db.execute(
""" """
@ -21,7 +24,7 @@ async def create_myextension(wallet_id: str, data: CreateMyExtensionData, req: R
wallet_id, wallet_id,
data.name, data.name,
data.lnurlpayamount, data.lnurlpayamount,
data.lnurlwithdrawamount data.lnurlwithdrawamount,
), ),
) )
myextension = await get_myextension(myextension_id, req) myextension = await get_myextension(myextension_id, req)
@ -29,25 +32,33 @@ async def create_myextension(wallet_id: str, data: CreateMyExtensionData, req: R
return myextension return myextension
async def get_myextension(myextension_id: str, req: Optional[Request] = None) -> Optional[MyExtension]: async def get_myextension(
myextension_id: str, req: Optional[Request] = None
) -> Optional[MyExtension]:
logger.debug(myextension_id) logger.debug(myextension_id)
row = await db.fetchone("SELECT * FROM myextension.maintable WHERE id = ?", (myextension_id,)) row = await db.fetchone(
"SELECT * FROM myextension.maintable WHERE id = ?", (myextension_id,)
)
if not row: if not row:
return None return None
rowAmended = MyExtension(**row) rowAmended = MyExtension(**row)
if req: if req:
rowAmended.lnurlpay = lnurl_encode( rowAmended.lnurlpay = lnurl_encode(
req.url_for("myextension.api_lnurl_pay", req.url_for("myextension.api_lnurl_pay", myextension_id=row.id)._url
myextension_id=row.id)._url
) )
rowAmended.lnurlwithdraw = lnurl_encode( rowAmended.lnurlwithdraw = lnurl_encode(
req.url_for("myextension.api_lnurl_withdraw", req.url_for(
"myextension.api_lnurl_withdraw",
myextension_id=row.id, myextension_id=row.id,
tickerhash=shortuuid.uuid(name=rowAmended.id + str(rowAmended.ticker)))._url tickerhash=shortuuid.uuid(name=rowAmended.id + str(rowAmended.ticker)),
)._url
) )
return rowAmended return rowAmended
async def get_myextensions(wallet_ids: Union[str, List[str]], req: Optional[Request] = None) -> List[MyExtension]:
async def get_myextensions(
wallet_ids: Union[str, List[str]], req: Optional[Request] = None
) -> List[MyExtension]:
if isinstance(wallet_ids, str): if isinstance(wallet_ids, str):
wallet_ids = [wallet_ids] wallet_ids = [wallet_ids]
@ -59,25 +70,33 @@ async def get_myextensions(wallet_ids: Union[str, List[str]], req: Optional[Requ
if req: if req:
for row in tempRows: for row in tempRows:
row.lnurlpay = lnurl_encode( row.lnurlpay = lnurl_encode(
req.url_for("myextension.api_lnurl_pay", req.url_for("myextension.api_lnurl_pay", myextension_id=row.id)._url
myextension_id=row.id)._url
) )
row.lnurlwithdraw = lnurl_encode( row.lnurlwithdraw = lnurl_encode(
req.url_for("myextension.api_lnurl_withdraw", req.url_for(
"myextension.api_lnurl_withdraw",
myextension_id=row.id, myextension_id=row.id,
tickerhash=shortuuid.uuid(name=row.id + str(row.ticker)))._url tickerhash=shortuuid.uuid(name=row.id + str(row.ticker)),
)._url
) )
return tempRows return tempRows
async def update_myextension(myextension_id: str, req: Optional[Request] = None, **kwargs) -> MyExtension:
async def update_myextension(
myextension_id: str, req: Optional[Request] = None, **kwargs
) -> MyExtension:
q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()]) q = ", ".join([f"{field[0]} = ?" for field in kwargs.items()])
logger.debug(kwargs.items()) logger.debug(kwargs.items())
await db.execute( await db.execute(
f"UPDATE myextension.maintable SET {q} WHERE id = ?", (*kwargs.values(), myextension_id) f"UPDATE myextension.maintable SET {q} WHERE id = ?",
(*kwargs.values(), myextension_id),
) )
myextension = await get_myextension(myextension_id, req) myextension = await get_myextension(myextension_id, req)
assert myextension, "Newly updated myextension couldn't be retrieved" assert myextension, "Newly updated myextension couldn't be retrieved"
return myextension return myextension
async def delete_myextension(myextension_id: str) -> None: async def delete_myextension(myextension_id: str) -> None:
await db.execute("DELETE FROM myextension.maintable WHERE id = ?", (myextension_id,)) await db.execute(
"DELETE FROM myextension.maintable WHERE id = ?", (myextension_id,)
)

View file

@ -19,6 +19,7 @@ import shortuuid
################################################# #################################################
################################################# #################################################
@myextension_ext.get( @myextension_ext.get(
"/api/v1/lnurl/pay/{myextension_id}", "/api/v1/lnurl/pay/{myextension_id}",
status_code=HTTPStatus.OK, status_code=HTTPStatus.OK,
@ -32,13 +33,18 @@ async def api_lnurl_pay(
if not myextension: if not myextension:
return {"status": "ERROR", "reason": "No myextension found"} return {"status": "ERROR", "reason": "No myextension found"}
return { return {
"callback": str(request.url_for("myextension.api_lnurl_pay_callback", myextension_id=myextension_id)), "callback": str(
request.url_for(
"myextension.api_lnurl_pay_callback", myextension_id=myextension_id
)
),
"maxSendable": myextension.lnurlpayamount * 1000, "maxSendable": myextension.lnurlpayamount * 1000,
"minSendable": myextension.lnurlpayamount * 1000, "minSendable": myextension.lnurlpayamount * 1000,
"metadata":"[[\"text/plain\", \"" + myextension.name + "\"]]", "metadata": '[["text/plain", "' + myextension.name + '"]]',
"tag": "payRequest" "tag": "payRequest",
} }
@myextension_ext.get( @myextension_ext.get(
"/api/v1/lnurl/pay/cb/{myextension_id}", "/api/v1/lnurl/pay/cb/{myextension_id}",
status_code=HTTPStatus.OK, status_code=HTTPStatus.OK,
@ -58,7 +64,7 @@ async def api_lnurl_pay_cb(
wallet_id=myextension.wallet, wallet_id=myextension.wallet,
amount=int(amount / 1000), amount=int(amount / 1000),
memo=myextension.name, memo=myextension.name,
unhashed_description=f"[[\"text/plain\", \"{myextension.name}\"]]".encode(), unhashed_description=f'[["text/plain", "{myextension.name}"]]'.encode(),
extra={ extra={
"tag": "MyExtension", "tag": "MyExtension",
"myextensionId": myextension_id, "myextensionId": myextension_id,
@ -68,12 +74,10 @@ async def api_lnurl_pay_cb(
return { return {
"pr": payment_request, "pr": payment_request,
"routes": [], "routes": [],
"successAction": { "successAction": {"tag": "message", "message": f"Paid {myextension.name}"},
"tag": "message",
"message": f"Paid {myextension.name}"
}
} }
################################################# #################################################
######## A very simple LNURLwithdraw ############ ######## A very simple LNURLwithdraw ############
# https://github.com/lnurl/luds/blob/luds/03.md # # https://github.com/lnurl/luds/blob/luds/03.md #
@ -100,13 +104,18 @@ async def api_lnurl_withdraw(
return { return {
"tag": "withdrawRequest", "tag": "withdrawRequest",
"callback": str(request.url_for("myextension.api_lnurl_withdraw_callback", myextension_id=myextension_id)), "callback": str(
request.url_for(
"myextension.api_lnurl_withdraw_callback", myextension_id=myextension_id
)
),
"k1": k1, "k1": k1,
"defaultDescription": myextension.name, "defaultDescription": myextension.name,
"maxWithdrawable": myextension.lnurlwithdrawamount * 1000, "maxWithdrawable": myextension.lnurlwithdrawamount * 1000,
"minWithdrawable": myextension.lnurlwithdrawamount * 1000 "minWithdrawable": myextension.lnurlwithdrawamount * 1000,
} }
@myextension_ext.get( @myextension_ext.get(
"/api/v1/lnurl/withdraw/cb/{myextension_id}", "/api/v1/lnurl/withdraw/cb/{myextension_id}",
status_code=HTTPStatus.OK, status_code=HTTPStatus.OK,
@ -130,7 +139,9 @@ async def api_lnurl_withdraw_cb(
if k1Check != k1: if k1Check != k1:
return {"status": "ERROR", "reason": "Wrong k1 check provided"} return {"status": "ERROR", "reason": "Wrong k1 check provided"}
await update_myextension(myextension_id=myextension_id, ticker=myextension.ticker + 1) await update_myextension(
myextension_id=myextension_id, ticker=myextension.ticker + 1
)
logger.debug(myextension.wallet) logger.debug(myextension.wallet)
logger.debug(pr) logger.debug(pr)
logger.debug(int(myextension.lnurlwithdrawamount * 1000)) logger.debug(int(myextension.lnurlwithdrawamount * 1000))
@ -138,6 +149,10 @@ async def api_lnurl_withdraw_cb(
wallet_id=myextension.wallet, wallet_id=myextension.wallet,
payment_request=pr, payment_request=pr,
max_sat=int(myextension.lnurlwithdrawamount * 1000), max_sat=int(myextension.lnurlwithdrawamount * 1000),
extra={"tag": "MyExtension", "myextensionId": myextension_id, "lnurlwithdraw": True} extra={
"tag": "MyExtension",
"myextensionId": myextension_id,
"lnurlwithdraw": True,
},
) )
return {"status": "OK"} return {"status": "OK"}

View file

@ -1,5 +1,6 @@
# The migration file is like a blockchain, never edit only add! # The migration file is like a blockchain, never edit only add!
async def m001_initial(db): async def m001_initial(db):
""" """
Initial templates table. Initial templates table.
@ -19,8 +20,10 @@ async def m001_initial(db):
""" """
) )
# Here we add another field to the database # Here we add another field to the database
async def m002_addtip_wallet(db): async def m002_addtip_wallet(db):
""" """
Add total to templates table Add total to templates table

View file

@ -9,6 +9,7 @@ from fastapi import Request
from lnbits.lnurl import encode as lnurl_encode from lnbits.lnurl import encode as lnurl_encode
from urllib.parse import urlparse from urllib.parse import urlparse
class CreateMyExtensionData(BaseModel): class CreateMyExtensionData(BaseModel):
wallet: Optional[str] wallet: Optional[str]
name: Optional[str] name: Optional[str]
@ -17,6 +18,7 @@ class CreateMyExtensionData(BaseModel):
lnurlwithdrawamount: Optional[int] lnurlwithdrawamount: Optional[int]
ticker: Optional[int] ticker: Optional[int]
class MyExtension(BaseModel): class MyExtension(BaseModel):
id: str id: str
wallet: Optional[str] wallet: Optional[str]

View file

@ -29,6 +29,7 @@ async def wait_for_paid_invoices():
# do somethhing when an invoice related top this extension is paid # do somethhing when an invoice related top this extension is paid
async def on_invoice_paid(payment: Payment) -> None: async def on_invoice_paid(payment: Payment) -> None:
logger.debug("payment received for myextension extension") logger.debug("payment received for myextension extension")
if payment.extra.get("tag") != "MyExtension": if payment.extra.get("tag") != "MyExtension":
@ -42,9 +43,7 @@ async def on_invoice_paid(payment: Payment) -> None:
total = myextension.total - payment.amount total = myextension.total - payment.amount
else: else:
total = myextension.total + payment.amount total = myextension.total + payment.amount
data_to_update = { data_to_update = {"total": total}
"total": total
}
await update_myextension(myextension_id=myextension_id, **data_to_update) await update_myextension(myextension_id=myextension_id, **data_to_update)
@ -55,7 +54,7 @@ async def on_invoice_paid(payment: Payment) -> None:
"name": myextension.name, "name": myextension.name,
"amount": payment.amount, "amount": payment.amount,
"fee": payment.fee, "fee": payment.fee,
"checking_id": payment.checking_id "checking_id": payment.checking_id,
} }
await websocketUpdater(myextension_id, str(some_payment_data)) await websocketUpdater(myextension_id, str(some_payment_data))

View file

@ -1,8 +1,3 @@
<q-expansion-item <q-expansion-item group="extras" icon="swap_vertical_circle" label="API info" :content-inset-level="0.5">
group="extras"
icon="swap_vertical_circle"
label="API info"
:content-inset-level="0.5"
>
<q-btn flat label="Swagger API" type="a" href="../docs#/MyExtension"></q-btn> <q-btn flat label="Swagger API" type="a" href="../docs#/MyExtension"></q-btn>
</q-expansion-item> </q-expansion-item>

View file

@ -4,24 +4,10 @@
<p> <p>
Some more info about my excellent extension. Some more info about my excellent extension.
</p> </p>
<small <small>Created by
>Created by <a class="text-secondary" href="https://github.com/benarc" target="_blank">Ben Arc</a>.</small>
<a <small>Repo
class="text-secondary" <a class="text-secondary" href="https://github.com/lnbits/myextension" target="_blank">MyExtension</a>.</small>
href="https://github.com/benarc"
target="_blank"
>Ben Arc</a
>.</small
>
<small
>Repo
<a
class="text-secondary"
href="https://github.com/lnbits/myextension"
target="_blank"
>MyExtension</a
>.</small
>
</q-card-section> </q-card-section>
</q-card> </q-card>
</q-expansion-item> </q-expansion-item>

View file

@ -4,9 +4,7 @@
<div class="col-12 col-md-8 col-lg-7 q-gutter-y-md"> <div class="col-12 col-md-8 col-lg-7 q-gutter-y-md">
<q-card> <q-card>
<q-card-section> <q-card-section>
<q-btn unelevated color="primary" @click="formDialog.show = true" <q-btn unelevated color="primary" @click="formDialog.show = true">New MyExtension</q-btn>
>New MyExtension</q-btn
>
</q-card-section> </q-card-section>
</q-card> </q-card>
@ -20,14 +18,8 @@
<q-btn flat color="grey" @click="exportCSV">Export to CSV</q-btn> <q-btn flat color="grey" @click="exportCSV">Export to CSV</q-btn>
</div> </div>
</div> </div>
<q-table <q-table dense flat :data="temps" row-key="id" :columns="tempsTable.columns"
dense :pagination.sync="tempsTable.pagination">
flat
:data="temps"
row-key="id"
:columns="tempsTable.columns"
:pagination.sync="tempsTable.pagination"
>
<myextension v-slot:header="props"> <myextension v-slot:header="props">
<q-tr :props="props"> <q-tr :props="props">
<q-th v-for="col in props.cols" :key="col.name" :props="props"> <q-th v-for="col in props.cols" :key="col.name" :props="props">
@ -38,59 +30,26 @@
<template v-slot:body="props"> <template v-slot:body="props">
<q-tr :props="props"> <q-tr :props="props">
<q-td <q-td v-for="col in props.cols" :key="col.name" :props="props">
v-for="col in props.cols"
:key="col.name"
:props="props"
>
<div v-if="col.field == 'total'">${ col.value / 1000} sats</div> <div v-if="col.field == 'total'">${ col.value / 1000} sats</div>
<div v-else>${ col.value }</div> <div v-else>${ col.value }</div>
</q-td> </q-td>
<q-td auto-width> <q-td auto-width>
<q-btn <q-btn unelevated dense size="sm" icon="qr_code" :color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
unelevated class="q-mr-sm" @click="openUrlDialog(props.row.id)"></q-btn></q-td>
dense
size="sm"
icon="qr_code"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
class="q-mr-sm"
@click="openUrlDialog(props.row.id)"
></q-btn></q-td>
<q-td auto-width> <q-td auto-width>
<q-btn <q-btn unelevated dense size="sm" icon="launch" :color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
unelevated type="a" :href="props.row.myextension" target="_blank"><q-tooltip>Open public
dense page</q-tooltip></q-btn></q-td>
size="sm"
icon="launch"
:color="($q.dark.isActive) ? 'grey-7' : 'grey-5'"
type="a"
:href="props.row.myextension"
target="_blank"
><q-tooltip>Open public page</q-tooltip></q-btn
></q-td>
<q-td> <q-td>
<q-btn <q-btn flat dense size="xs" @click="updateMyExtensionForm(props.row.id)" icon="edit" color="light-blue">
flat
dense
size="xs"
@click="updateMyExtensionForm(props.row.id)"
icon="edit"
color="light-blue"
>
<q-tooltip> Edit copilot </q-tooltip> <q-tooltip> Edit copilot </q-tooltip>
</q-btn> </q-btn>
</q-td> </q-td>
<q-td> <q-td>
<q-btn <q-btn flat dense size="xs" @click="deleteMyExtension(props.row.id)" icon="cancel" color="pink">
flat
dense
size="xs"
@click="deleteMyExtension(props.row.id)"
icon="cancel"
color="pink"
>
<q-tooltip> Delete copilot </q-tooltip> <q-tooltip> Delete copilot </q-tooltip>
</q-btn> </q-btn>
</q-td> </q-td>
@ -107,7 +66,8 @@
<q-card> <q-card>
<q-card-section> <q-card-section>
<h6 class="text-subtitle1 q-my-none">{{SITE_TITLE}} MyExtension extension</h6> <h6 class="text-subtitle1 q-my-none">{{SITE_TITLE}} MyExtension extension</h6>
<p>Simple extension you can use as a base for your own extension. <br/> Includes very simple LNURL-pay and LNURL-withdraw example.</p> <p>Simple extension you can use as a base for your own extension. <br /> Includes very simple LNURL-pay and
LNURL-withdraw example.</p>
</q-card-section> </q-card-section>
<q-card-section class="q-pa-none"> <q-card-section class="q-pa-none">
<q-separator></q-separator> <q-separator></q-separator>
@ -123,54 +83,20 @@
<q-dialog v-model="formDialog.show" position="top" @hide="closeFormDialog"> <q-dialog v-model="formDialog.show" position="top" @hide="closeFormDialog">
<q-card class="q-pa-lg q-pt-xl" style="width: 500px"> <q-card class="q-pa-lg q-pt-xl" style="width: 500px">
<q-form @submit="sendMyExtensionData" class="q-gutter-md"> <q-form @submit="sendMyExtensionData" class="q-gutter-md">
<q-input <q-input filled dense v-model.trim="formDialog.data.name" label="Name"
filled placeholder="Name for your record"></q-input>
dense <q-select filled dense emit-value v-model="formDialog.data.wallet" :options="g.user.walletOptions"
v-model.trim="formDialog.data.name" label="Wallet *"></q-select>
label="Name" <q-input filled dense type="number" v-model.trim="formDialog.data.lnurlwithdrawamount"
placeholder="Name for your record" label="LNURL-withdraw amount"></q-input>
></q-input> <q-input filled dense type="number" v-model.trim="formDialog.data.lnurlpayamount"
<q-select label="LNURL-pay amount"></q-input>
filled
dense
emit-value
v-model="formDialog.data.wallet"
:options="g.user.walletOptions"
label="Wallet *"
></q-select>
<q-input
filled
dense
type="number"
v-model.trim="formDialog.data.lnurlwithdrawamount"
label="LNURL-withdraw amount"
></q-input>
<q-input
filled
dense
type="number"
v-model.trim="formDialog.data.lnurlpayamount"
label="LNURL-pay amount"
></q-input>
<div class="row q-mt-lg"> <div class="row q-mt-lg">
<q-btn <q-btn v-if="formDialog.data.id" unelevated color="primary" type="submit">Update MyExtension</q-btn>
v-if="formDialog.data.id" <q-btn v-else unelevated color="primary"
unelevated
color="primary"
type="submit"
>Update MyExtension</q-btn
>
<q-btn
v-else
unelevated
color="primary"
:disable="formDialog.data.name == null || formDialog.data.wallet == null || formDialog.data.lnurlwithdrawamount == null || formDialog.data.lnurlpayamount == null" :disable="formDialog.data.name == null || formDialog.data.wallet == null || formDialog.data.lnurlwithdrawamount == null || formDialog.data.lnurlpayamount == null"
type="submit" type="submit">Create MyExtension</q-btn>
>Create MyExtension</q-btn <q-btn v-close-popup flat color="grey" class="q-ml-auto">Cancel</q-btn>
>
<q-btn v-close-popup flat color="grey" class="q-ml-auto"
>Cancel</q-btn
>
</div> </div>
</q-form> </q-form>
</q-card> </q-card>
@ -181,9 +107,7 @@
<q-responsive :ratio="1" class="q-mx-xl q-mb-md"> <q-responsive :ratio="1" class="q-mx-xl q-mb-md">
<lnbits-qrcode <lnbits-qrcode :value="qrValue"></lnbits-qrcode>
:value="qrValue"
></lnbits-qrcode>
</q-responsive> </q-responsive>
<center><q-btn label="copy" @click="copyText(qrValue)"></q-btn> <center><q-btn label="copy" @click="copyText(qrValue)"></q-btn>
</center> </center>
@ -202,7 +126,8 @@
<div class="col q-pl-md"> <div class="col q-pl-md">
<q-input filled bottom-slots dense v-model="invoiceAmount"> <q-input filled bottom-slots dense v-model="invoiceAmount">
<template v-slot:append> <template v-slot:append>
<q-btn round @click="createInvoice(urlDialog.data.wallet, urlDialog.data.id)" color="primary" flat icon="add_circle" /> <q-btn round @click="createInvoice(urlDialog.data.wallet, urlDialog.data.id)" color="primary" flat
icon="add_circle" />
</template> </template>
<template v-slot:hint> <template v-slot:hint>
Create an invoice Create an invoice

View file

@ -6,18 +6,12 @@
<div class="text-center"> <div class="text-center">
<a class="text-secondary" href="lightning:{{ lnurl }}"> <a class="text-secondary" href="lightning:{{ lnurl }}">
<q-responsive :ratio="1" class="q-mx-md"> <q-responsive :ratio="1" class="q-mx-md">
<qrcode <qrcode :value="qrValue" :options="{width: 800}" class="rounded-borders"></qrcode>
:value="qrValue"
:options="{width: 800}"
class="rounded-borders"
></qrcode>
</q-responsive> </q-responsive>
</a> </a>
</div> </div>
<div class="row q-mt-lg q-gutter-sm"> <div class="row q-mt-lg q-gutter-sm">
<q-btn outline color="grey" @click="copyText(qrValue)" <q-btn outline color="grey" @click="copyText(qrValue)">Copy LNURL </q-btn>
>Copy LNURL </q-btn
>
</div> </div>
</q-card-section> </q-card-section>

View file

@ -22,6 +22,7 @@ temps = Jinja2Templates(directory="temps")
# Backend admin page # Backend admin page
@myextension_ext.get("/", response_class=HTMLResponse) @myextension_ext.get("/", response_class=HTMLResponse)
async def index(request: Request, user: User = Depends(check_user_exists)): async def index(request: Request, user: User = Depends(check_user_exists)):
return myextension_renderer().TemplateResponse( return myextension_renderer().TemplateResponse(
@ -31,6 +32,7 @@ async def index(request: Request, user: User = Depends(check_user_exists)):
# Frontend shareable page # Frontend shareable page
@myextension_ext.get("/{myextension_id}") @myextension_ext.get("/{myextension_id}")
async def myextension(request: Request, myextension_id): async def myextension(request: Request, myextension_id):
myextension = await get_myextension(myextension_id, request) myextension = await get_myextension(myextension_id, request)
@ -52,6 +54,7 @@ async def myextension(request: Request, myextension_id):
# Manifest for public page, customise or remove manifest completely # Manifest for public page, customise or remove manifest completely
@myextension_ext.get("/manifest/{myextension_id}.webmanifest") @myextension_ext.get("/manifest/{myextension_id}.webmanifest")
async def manifest(myextension_id: str): async def manifest(myextension_id: str):
myextension = await get_myextension(myextension_id) myextension = await get_myextension(myextension_id)

View file

@ -25,7 +25,7 @@ from .crud import (
update_myextension, update_myextension,
delete_myextension, delete_myextension,
get_myextension, get_myextension,
get_myextensions get_myextensions,
) )
from .models import CreateMyExtensionData from .models import CreateMyExtensionData
@ -36,25 +36,29 @@ from .models import CreateMyExtensionData
## Get all the records belonging to the user ## Get all the records belonging to the user
@myextension_ext.get("/api/v1/temps", status_code=HTTPStatus.OK) @myextension_ext.get("/api/v1/temps", status_code=HTTPStatus.OK)
async def api_myextensions( async def api_myextensions(
req: Request, all_wallets: req: Request,
bool = Query(False), all_wallets: bool = Query(False),
wallet: WalletTypeInfo = Depends(get_key_type) wallet: WalletTypeInfo = Depends(get_key_type),
): ):
wallet_ids = [wallet.wallet.id] wallet_ids = [wallet.wallet.id]
if all_wallets: if all_wallets:
user = await get_user(wallet.wallet.user) user = await get_user(wallet.wallet.user)
wallet_ids = user.wallet_ids if user else [] wallet_ids = user.wallet_ids if user else []
return [myextension.dict() for myextension in await get_myextensions(wallet_ids, req)] return [
myextension.dict() for myextension in await get_myextensions(wallet_ids, req)
]
## Get a single record ## Get a single record
@myextension_ext.get("/api/v1/temps/{myextension_id}", status_code=HTTPStatus.OK) @myextension_ext.get("/api/v1/temps/{myextension_id}", status_code=HTTPStatus.OK)
async def api_myextension( async def api_myextension(
req: Request, req: Request, myextension_id: str, WalletTypeInfo=Depends(get_key_type)
myextension_id: str, ):
WalletTypeInfo = Depends(get_key_type)):
myextension = await get_myextension(myextension_id, req) myextension = await get_myextension(myextension_id, req)
if not myextension: if not myextension:
raise HTTPException( raise HTTPException(
@ -62,8 +66,10 @@ async def api_myextension(
) )
return myextension.dict() return myextension.dict()
## update a record ## update a record
@myextension_ext.put("/api/v1/temps/{myextension_id}") @myextension_ext.put("/api/v1/temps/{myextension_id}")
async def api_myextension_update( async def api_myextension_update(
req: Request, req: Request,
@ -79,25 +85,33 @@ async def api_myextension_update(
assert myextension, "MyExtension couldn't be retrieved" assert myextension, "MyExtension couldn't be retrieved"
if wallet.wallet.id != myextension.wallet: if wallet.wallet.id != myextension.wallet:
raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail="Not your MyExtension.") raise HTTPException(
myextension = await update_myextension(myextension_id=myextension_id, **data.dict(), req=req) status_code=HTTPStatus.FORBIDDEN, detail="Not your MyExtension."
)
myextension = await update_myextension(
myextension_id=myextension_id, **data.dict(), req=req
)
return myextension.dict() return myextension.dict()
## Create a new record ## Create a new record
@myextension_ext.post("/api/v1/temps", status_code=HTTPStatus.CREATED) @myextension_ext.post("/api/v1/temps", status_code=HTTPStatus.CREATED)
async def api_myextension_create( async def api_myextension_create(
req: Request, req: Request,
data: CreateMyExtensionData, data: CreateMyExtensionData,
wallet: WalletTypeInfo = Depends(get_key_type) wallet: WalletTypeInfo = Depends(get_key_type),
): ):
myextension = await create_myextension(wallet_id=wallet.wallet.id, data=data, req=req) myextension = await create_myextension(
wallet_id=wallet.wallet.id, data=data, req=req
)
return myextension.dict() return myextension.dict()
## Delete a record ## Delete a record
@myextension_ext.delete("/api/v1/temps/{myextension_id}") @myextension_ext.delete("/api/v1/temps/{myextension_id}")
async def api_myextension_delete( async def api_myextension_delete(
myextension_id: str, wallet: WalletTypeInfo = Depends(require_admin_key) myextension_id: str, wallet: WalletTypeInfo = Depends(require_admin_key)
@ -110,7 +124,9 @@ async def api_myextension_delete(
) )
if myextension.wallet != wallet.wallet.id: if myextension.wallet != wallet.wallet.id:
raise HTTPException(status_code=HTTPStatus.FORBIDDEN, detail="Not your MyExtension.") raise HTTPException(
status_code=HTTPStatus.FORBIDDEN, detail="Not your MyExtension."
)
await delete_myextension(myextension_id) await delete_myextension(myextension_id)
return "", HTTPStatus.NO_CONTENT return "", HTTPStatus.NO_CONTENT
@ -120,7 +136,10 @@ async def api_myextension_delete(
## This endpoint creates a payment ## This endpoint creates a payment
@myextension_ext.post("/api/v1/temps/payment/{myextension_id}", status_code=HTTPStatus.CREATED)
@myextension_ext.post(
"/api/v1/temps/payment/{myextension_id}", status_code=HTTPStatus.CREATED
)
async def api_tpos_create_invoice( async def api_tpos_create_invoice(
myextension_id: str, amount: int = Query(..., ge=1), memo: str = "" myextension_id: str, amount: int = Query(..., ge=1), memo: str = ""
) -> dict: ) -> dict: