paywall converted but create invoice creates BAD REQUEST

This commit is contained in:
Tiago vasconcelos
2021-10-27 12:02:27 +01:00
parent 1653c45f12
commit 1021d3c81c
8 changed files with 113 additions and 110 deletions

View File

@@ -1,12 +1,18 @@
from quart import Blueprint from fastapi import APIRouter
from lnbits.db import Database from lnbits.db import Database
from lnbits.helpers import template_renderer
db = Database("ext_paywall") db = Database("ext_paywall")
paywall_ext: Blueprint = Blueprint( paywall_ext: APIRouter = APIRouter(
"paywall", __name__, static_folder="static", template_folder="templates" prefix="/paywall",
tags=["Paywall"]
) )
def paywall_renderer():
return template_renderer(["lnbits/extensions/paywall/templates"])
from .views_api import * # noqa
from .views import * # noqa from .views import * # noqa
from .views_api import * # noqa

View File

@@ -3,17 +3,12 @@ from typing import List, Optional, Union
from lnbits.helpers import urlsafe_short_hash from lnbits.helpers import urlsafe_short_hash
from . import db from . import db
from .models import Paywall from .models import CreatePaywall, Paywall
async def create_paywall( async def create_paywall(
*,
wallet_id: str, wallet_id: str,
url: str, data: CreatePaywall
memo: str,
description: Optional[str] = None,
amount: int = 0,
remembers: bool = True,
) -> Paywall: ) -> Paywall:
paywall_id = urlsafe_short_hash() paywall_id = urlsafe_short_hash()
await db.execute( await db.execute(
@@ -21,7 +16,7 @@ async def create_paywall(
INSERT INTO paywall.paywalls (id, wallet, url, memo, description, amount, remembers) INSERT INTO paywall.paywalls (id, wallet, url, memo, description, amount, remembers)
VALUES (?, ?, ?, ?, ?, ?, ?) VALUES (?, ?, ?, ?, ?, ?, ?)
""", """,
(paywall_id, wallet_id, url, memo, description, amount, int(remembers)), (paywall_id, wallet_id, data.url, data.memo, data.description, data.amount, int(data.remembers)),
) )
paywall = await get_paywall(paywall_id) paywall = await get_paywall(paywall_id)
@@ -33,7 +28,6 @@ async def get_paywall(paywall_id: str) -> Optional[Paywall]:
row = await db.fetchone( row = await db.fetchone(
"SELECT * FROM paywall.paywalls WHERE id = ?", (paywall_id,) "SELECT * FROM paywall.paywalls WHERE id = ?", (paywall_id,)
) )
return Paywall.from_row(row) if row else None return Paywall.from_row(row) if row else None

View File

@@ -1,15 +1,30 @@
import json import json
from sqlite3 import Row from sqlite3 import Row
from typing import NamedTuple, Optional from typing import Optional
from fastapi import Query
from pydantic import BaseModel
class Paywall(NamedTuple): class CreatePaywall(BaseModel):
url: str = Query(...)
memo: str = Query(...)
description: str = Query(None)
amount: int = Query(..., ge=0)
remembers: bool = Query(...)
class CreatePaywallInvoice(BaseModel):
amount: int = Query(..., ge=1)
class CheckPaywallInvoice(BaseModel):
payment_hash: str = Query(...)
class Paywall(BaseModel):
id: str id: str
wallet: str wallet: str
url: str url: str
memo: str memo: str
description: str description: Optional[str]
amount: int amount: int
time: int time: int
remembers: bool remembers: bool

View File

@@ -18,7 +18,7 @@
<h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5> <h5 class="text-caption q-mt-sm q-mb-none">Curl example</h5>
<code <code
>curl -X GET {{ request.url_root }}api/v1/paywalls -H "X-Api-Key: {{ >curl -X GET {{ request.url_root }}api/v1/paywalls -H "X-Api-Key: {{
g.user.wallets[0].inkey }}" user.wallets[0].inkey }}"
</code> </code>
</q-card-section> </q-card-section>
</q-card> </q-card>
@@ -52,7 +52,7 @@
&lt;string&gt;, "memo": &lt;string&gt;, "description": &lt;string&gt;, &lt;string&gt;, "memo": &lt;string&gt;, "description": &lt;string&gt;,
"amount": &lt;integer&gt;, "remembers": &lt;boolean&gt;}' -H "amount": &lt;integer&gt;, "remembers": &lt;boolean&gt;}' -H
"Content-type: application/json" -H "X-Api-Key: {{ "Content-type: application/json" -H "X-Api-Key: {{
g.user.wallets[0].adminkey }}" user.wallets[0].adminkey }}"
</code> </code>
</q-card-section> </q-card-section>
</q-card> </q-card>
@@ -139,7 +139,7 @@
<code <code
>curl -X DELETE {{ request.url_root >curl -X DELETE {{ request.url_root
}}api/v1/paywalls/&lt;paywall_id&gt; -H "X-Api-Key: {{ }}api/v1/paywalls/&lt;paywall_id&gt; -H "X-Api-Key: {{
g.user.wallets[0].adminkey }}" user.wallets[0].adminkey }}"
</code> </code>
</q-card-section> </q-card-section>
</q-card> </q-card>

View File

@@ -102,11 +102,11 @@
}, },
createInvoice: function () { createInvoice: function () {
var self = this var self = this
console.log(this.amount)
axios axios
.post( .post(
'/paywall/api/v1/paywalls/{{ paywall.id }}/invoice', '/paywall/api/v1/paywalls/{{ paywall.id }}/invoice',
{amount: this.amount} {amount: self.amount}
) )
.then(function (response) { .then(function (response) {
self.paymentReq = response.data.payment_request.toUpperCase() self.paymentReq = response.data.payment_request.toUpperCase()

View File

@@ -237,7 +237,7 @@
LNbits.api LNbits.api
.request( .request(
'GET', 'GET',
'/paywall/api/v1/paywalls?all_wallets', '/paywall/api/v1/paywalls?all_wallets=true',
this.g.user.wallets[0].inkey this.g.user.wallets[0].inkey
) )
.then(function (response) { .then(function (response) {

View File

@@ -1,22 +1,26 @@
from quart import g, abort, render_template
from http import HTTPStatus from http import HTTPStatus
from lnbits.decorators import check_user_exists, validate_uuids from fastapi import Depends
from starlette.exceptions import HTTPException
from starlette.requests import Request
from . import paywall_ext from lnbits.core.models import User
from lnbits.decorators import check_user_exists
from . import paywall_ext, paywall_renderer
from .crud import get_paywall from .crud import get_paywall
@paywall_ext.route("/") @paywall_ext.get("/")
@validate_uuids(["usr"], required=True) async def index(request: Request, user: User = Depends(check_user_exists)):
@check_user_exists() return paywall_renderer().TemplateResponse("paywall/index.html", {"request": request, "user": user.dict()})
async def index():
return await render_template("paywall/index.html", user=g.user)
@paywall_ext.route("/<paywall_id>") @paywall_ext.get("/{paywall_id}")
async def display(paywall_id): async def display(request: Request, paywall_id):
paywall = await get_paywall(paywall_id) or abort( paywall = await get_paywall(paywall_id)
HTTPStatus.NOT_FOUND, "Paywall does not exist." if not paywall:
) raise HTTPException(
return await render_template("paywall/display.html", paywall=paywall) status_code=HTTPStatus.NOT_FOUND, detail="Paywall does not exist."
)
return paywall_renderer().TemplateResponse("paywall/display.html", {"request": request, "paywall": paywall})

View File

@@ -1,81 +1,68 @@
from quart import g, jsonify, request
from http import HTTPStatus from http import HTTPStatus
from fastapi import Depends, Query
from starlette.exceptions import HTTPException
from lnbits.core.crud import get_user, get_wallet from lnbits.core.crud import get_user, get_wallet
from lnbits.core.services import create_invoice, check_invoice_status from lnbits.core.services import check_invoice_status, create_invoice
from lnbits.decorators import api_check_wallet_key, api_validate_post_request from lnbits.decorators import WalletTypeInfo, get_key_type
from . import paywall_ext from . import paywall_ext
from .crud import create_paywall, get_paywall, get_paywalls, delete_paywall from .crud import create_paywall, delete_paywall, get_paywall, get_paywalls
from .models import CheckPaywallInvoice, CreatePaywall, CreatePaywallInvoice
@paywall_ext.route("/api/v1/paywalls", methods=["GET"]) @paywall_ext.get("/api/v1/paywalls")
@api_check_wallet_key("invoice") async def api_paywalls(wallet: WalletTypeInfo = Depends(get_key_type), all_wallets: bool = Query(False)):
async def api_paywalls(): wallet_ids = [wallet.wallet.id]
wallet_ids = [g.wallet.id]
if "all_wallets" in request.args: if all_wallets:
wallet_ids = (await get_user(g.wallet.user)).wallet_ids wallet_ids = (await get_user(wallet.wallet.user)).wallet_ids
return ( return [paywall.dict() for paywall in await get_paywalls(wallet_ids)]
jsonify([paywall._asdict() for paywall in await get_paywalls(wallet_ids)]),
HTTPStatus.OK,
)
@paywall_ext.route("/api/v1/paywalls", methods=["POST"]) @paywall_ext.post("/api/v1/paywalls")
@api_check_wallet_key("invoice") async def api_paywall_create(data: CreatePaywall, wallet: WalletTypeInfo = Depends(get_key_type)):
@api_validate_post_request( paywall = await create_paywall(wallet_id=wallet.wallet.id, data=data)
schema={ return paywall.dict()
"url": {"type": "string", "empty": False, "required": True},
"memo": {"type": "string", "empty": False, "required": True},
"description": {
"type": "string",
"empty": True,
"nullable": True,
"required": False,
},
"amount": {"type": "integer", "min": 0, "required": True},
"remembers": {"type": "boolean", "required": True},
}
)
async def api_paywall_create():
paywall = await create_paywall(wallet_id=g.wallet.id, **g.data)
return jsonify(paywall._asdict()), HTTPStatus.CREATED
@paywall_ext.route("/api/v1/paywalls/<paywall_id>", methods=["DELETE"]) @paywall_ext.delete("/api/v1/paywalls/{paywall_id}")
@api_check_wallet_key("invoice") async def api_paywall_delete(paywall_id, wallet: WalletTypeInfo = Depends(get_key_type)):
async def api_paywall_delete(paywall_id):
paywall = await get_paywall(paywall_id) paywall = await get_paywall(paywall_id)
if not paywall: if not paywall:
return jsonify({"message": "Paywall does not exist."}), HTTPStatus.NOT_FOUND raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Paywall does not exist."
)
if paywall.wallet != g.wallet.id: if paywall.wallet != wallet.wallet.id:
return jsonify({"message": "Not your paywall."}), HTTPStatus.FORBIDDEN raise HTTPException(
status_code=HTTPStatus.FORBIDDEN,
detail="Not your paywall."
)
await delete_paywall(paywall_id) await delete_paywall(paywall_id)
raise HTTPException(status_code=HTTPStatus.NO_CONTENT)
return "", HTTPStatus.NO_CONTENT
@paywall_ext.route("/api/v1/paywalls/<paywall_id>/invoice", methods=["POST"]) @paywall_ext.post("/api/v1/paywalls/{paywall_id}/invoice")
@api_validate_post_request( async def api_paywall_create_invoice(paywall_id, data: CreatePaywallInvoice, wallet: WalletTypeInfo = Depends(get_key_type)):
schema={"amount": {"type": "integer", "min": 1, "required": True}}
)
async def api_paywall_create_invoice(paywall_id):
paywall = await get_paywall(paywall_id) paywall = await get_paywall(paywall_id)
print("PAYW", paywall)
if g.data["amount"] < paywall.amount: print("DATA", data)
return (
jsonify({"message": f"Minimum amount is {paywall.amount} sat."}), if data.amount < paywall.amount:
HTTPStatus.BAD_REQUEST, raise HTTPException(
) status_code=HTTPStatus.BAD_REQUEST,
detail=f"Minimum amount is {paywall.amount} sat."
)
try: try:
amount = ( amount = (
g.data["amount"] if g.data["amount"] > paywall.amount else paywall.amount data.amount if data.amount > paywall.amount else paywall.amount
) )
payment_hash, payment_request = await create_invoice( payment_hash, payment_request = await create_invoice(
wallet_id=paywall.wallet, wallet_id=paywall.wallet,
@@ -84,38 +71,35 @@ async def api_paywall_create_invoice(paywall_id):
extra={"tag": "paywall"}, extra={"tag": "paywall"},
) )
except Exception as e: except Exception as e:
return jsonify({"message": str(e)}), HTTPStatus.INTERNAL_SERVER_ERROR raise HTTPException(
status_code=HTTPStatus.INTERNAL_SERVER_ERROR,
detail=str(e)
)
return ( return {"payment_hash": payment_hash, "payment_request": payment_request}
jsonify({"payment_hash": payment_hash, "payment_request": payment_request}),
HTTPStatus.CREATED,
)
@paywall_ext.route("/api/v1/paywalls/<paywall_id>/check_invoice", methods=["POST"]) @paywall_ext.post("/api/v1/paywalls/{paywall_id}/check_invoice")
@api_validate_post_request( async def api_paywal_check_invoice(data: CheckPaywallInvoice, paywall_id):
schema={"payment_hash": {"type": "string", "empty": False, "required": True}}
)
async def api_paywal_check_invoice(paywall_id):
paywall = await get_paywall(paywall_id) paywall = await get_paywall(paywall_id)
payment_hash = data.payment_hash
if not paywall: if not paywall:
return jsonify({"message": "Paywall does not exist."}), HTTPStatus.NOT_FOUND raise HTTPException(
status_code=HTTPStatus.NOT_FOUND,
detail="Paywall does not exist."
)
try: try:
status = await check_invoice_status(paywall.wallet, g.data["payment_hash"]) status = await check_invoice_status(paywall.wallet, payment_hash)
is_paid = not status.pending is_paid = not status.pending
except Exception: except Exception:
return jsonify({"paid": False}), HTTPStatus.OK return {"paid": False}
if is_paid: if is_paid:
wallet = await get_wallet(paywall.wallet) wallet = await get_wallet(paywall.wallet)
payment = await wallet.get_payment(g.data["payment_hash"]) payment = await wallet.get_payment(payment_hash)
await payment.set_pending(False) await payment.set_pending(False)
return ( return {"paid": True, "url": paywall.url, "remembers": paywall.remembers}
jsonify({"paid": True, "url": paywall.url, "remembers": paywall.remembers}),
HTTPStatus.OK,
)
return jsonify({"paid": False}), HTTPStatus.OK return {"paid": False}