From 2eb44674d0bb66bdf333a021b07c91281e630d16 Mon Sep 17 00:00:00 2001 From: Kristjan Date: Mon, 28 Dec 2020 22:40:46 +0100 Subject: [PATCH] added public facing api --- lnbits/extensions/subdomains/views_api.py | 183 ++++++++++++++++++---- 1 file changed, 152 insertions(+), 31 deletions(-) diff --git a/lnbits/extensions/subdomains/views_api.py b/lnbits/extensions/subdomains/views_api.py index dc9263c..7f2ffb7 100644 --- a/lnbits/extensions/subdomains/views_api.py +++ b/lnbits/extensions/subdomains/views_api.py @@ -1,41 +1,162 @@ -# views_api.py is for you API endpoints that could be hit by another service +import re +from quart import g, jsonify, request +from http import HTTPStatus -# add your dependencies here +from lnbits.core.crud import get_user, get_wallet +from lnbits.core.services import create_invoice, check_invoice_status +from lnbits.decorators import api_check_wallet_key, api_validate_post_request -# import json -# import httpx -# (use httpx just like requests, except instead of response.ok there's only the -# response.is_error that is its inverse) +from . import lnsubdomain_ext +from .crud import ( + create_subdomain, + set_subdomain_paid, + get_subdomain, + get_subdomains, + delete_subdomain, + create_domain, + update_domain, + get_domain, + get_domains, + delete_domain, +) -from quart import jsonify -from http import HTTPStatus -from . import subdomains_ext +# domainS + + +@lnsubdomain_ext.route("/api/v1/domains", methods=["GET"]) +@api_check_wallet_key("invoice") +async def api_domains(): + wallet_ids = [g.wallet.id] + + if "all_wallets" in request.args: + wallet_ids = (await get_user(g.wallet.user)).wallet_ids + + return jsonify([domain._asdict() for domain in await get_domains(wallet_ids)]), HTTPStatus.OK + + +@lnsubdomain_ext.route("/api/v1/domains", methods=["POST"]) +@lnsubdomain_ext.route("/api/v1/domains/", methods=["PUT"]) +@api_check_wallet_key("invoice") +@api_validate_post_request( + schema={ + "wallet": {"type": "string", "empty": False, "required": True}, + "domain": {"type": "string", "empty": False, "required": True}, + "cfToken": {"type": "string", "empty": False, "required": True}, + "cfZoneId": {"type": "string", "empty": False, "required": True}, + "webhook": {"type": "string", "empty": False, "required": False}, + "description": {"type": "string", "min": 0, "required": True}, + "cost": {"type": "integer", "min": 0, "required": True}, + } +) +async def api_domain_create(domain_id=None): + if domain_id: + domain = await get_domain(domain_id) + + if not domain: + return jsonify({"message": "domain does not exist."}), HTTPStatus.NOT_FOUND + + if domain.wallet != g.wallet.id: + return jsonify({"message": "Not your domain."}), HTTPStatus.FORBIDDEN + + domain = await update_domain(domain_id, **g.data) + else: + domain = await create_domain(**g.data) + return jsonify(domain._asdict()), HTTPStatus.CREATED + + +@lnsubdomain_ext.route("/api/v1/domains/", methods=["DELETE"]) +@api_check_wallet_key("invoice") +async def api_domain_delete(domain_id): + domain = await get_domain(domain_id) + + if not domain: + return jsonify({"message": "domain does not exist."}), HTTPStatus.NOT_FOUND + + if domain.wallet != g.wallet.id: + return jsonify({"message": "Not your domain."}), HTTPStatus.FORBIDDEN + + await delete_domain(domain_id) + + return "", HTTPStatus.NO_CONTENT -# add your endpoints here +#########subdomains########## -@subdomains_ext.route("/api/v1/tools", methods=["GET"]) +@lnsubdomain_ext.route("/api/v1/subdomains", methods=["GET"]) +@api_check_wallet_key("invoice") async def api_subdomains(): - """Try to add descriptions for others.""" - tools = [ - { - "name": "Quart", - "url": "https://pgjones.gitlab.io/quart/", - "language": "Python", - }, - { - "name": "Vue.js", - "url": "https://vuejs.org/", - "language": "JavaScript", - }, - { - "name": "Quasar Framework", - "url": "https://quasar.dev/", - "language": "JavaScript", - }, - ] - - return jsonify(tools), HTTPStatus.OK + wallet_ids = [g.wallet.id] + + if "all_wallets" in request.args: + wallet_ids = (await get_user(g.wallet.user)).wallet_ids + + return jsonify([domain._asdict() for domain in await get_subdomains(wallet_ids)]), HTTPStatus.OK + + +@lnsubdomain_ext.route("/api/v1/subdomains/", methods=["POST"]) +@api_validate_post_request( + schema={ + "domain": {"type": "string", "empty": False, "required": True}, + "subdomain": {"type": "string", "empty": False, "required": True}, + "email": {"type": "string", "empty": True, "required": True}, + "ip": {"type": "string", "empty": False, "required": True}, + "sats": {"type": "integer", "min": 0, "required": True}, + } +) +async def api_subdomain_make_subdomain(domain_id): + domain = await get_domain(domain_id) + if not domain: + return jsonify({"message": "LNsubdomain does not exist."}), HTTPStatus.NOT_FOUND + + subdomain = len(re.split(r"\s+", g.data["subdomain"])) + sats = g.data["sats"] + payment_hash, payment_request = await create_invoice( + wallet_id=domain.wallet, + amount=sats, + memo=f"subdomain with {subdomain} words on {domain_id}", + extra={"tag": "lnsubdomain"}, + ) + + subdomain = await create_subdomain(payment_hash=payment_hash, wallet=domain.wallet, **g.data) + + if not subdomain: + return jsonify({"message": "LNsubdomain could not be fetched."}), HTTPStatus.NOT_FOUND + + return jsonify({"payment_hash": payment_hash, "payment_request": payment_request}), HTTPStatus.OK + + +@lnsubdomain_ext.route("/api/v1/subdomains/", methods=["GET"]) +async def api_subdomain_send_subdomain(payment_hash): + subdomain = await get_subdomain(payment_hash) + try: + status = await check_invoice_status(subdomain.wallet, payment_hash) + is_paid = not status.pending + except Exception: + return jsonify({"paid": False}), HTTPStatus.OK + + if is_paid: + wallet = await get_wallet(subdomain.wallet) + payment = await wallet.get_payment(payment_hash) + await payment.set_pending(False) + subdomain = await set_subdomain_paid(payment_hash=payment_hash) + return jsonify({"paid": True}), HTTPStatus.OK + + return jsonify({"paid": False}), HTTPStatus.OK + + +@lnsubdomain_ext.route("/api/v1/subdomains/", methods=["DELETE"]) +@api_check_wallet_key("invoice") +async def api_subdomain_delete(subdomain_id): + subdomain = await get_subdomain(subdomain_id) + + if not subdomain: + return jsonify({"message": "Paywall does not exist."}), HTTPStatus.NOT_FOUND + + if subdomain.wallet != g.wallet.id: + return jsonify({"message": "Not your subdomain."}), HTTPStatus.FORBIDDEN + + await delete_subdomain(subdomain_id) + return "", HTTPStatus.NO_CONTENT