Browse Source

added checks to the cloudflare if the domain can be created; code refactoring - moved calls to cloudflare to seperate file

master
Kristjan 4 years ago
parent
commit
f45aadaafe
  1. 44
      lnbits/extensions/subdomains/cloudflare.py
  2. 26
      lnbits/extensions/subdomains/tasks.py
  3. 26
      lnbits/extensions/subdomains/views_api.py

44
lnbits/extensions/subdomains/cloudflare.py

@ -0,0 +1,44 @@
from lnbits.extensions.subdomains.models import Domains
import httpx, json
async def cloudflare_create_subdomain(domain: Domains, subdomain: str, record_type: str, ip: str):
# Call to cloudflare sort of a dry-run - if success delete the domain and wait for payment
### SEND REQUEST TO CLOUDFLARE
url = "https://api.cloudflare.com/client/v4/zones/" + domain.cf_zone_id + "/dns_records"
header = {"Authorization": "Bearer " + domain.cf_token, "Content-Type": "application/json"}
aRecord = subdomain + "." + domain.domain
cf_response = ""
async with httpx.AsyncClient() as client:
try:
r = await client.post(
url,
headers=header,
json={
"type": record_type,
"name": aRecord,
"content": ip,
"ttl": 0,
"proxed": False,
},
timeout=40,
)
cf_response = json.loads(r.text)
except AssertionError:
cf_response = "Error occured"
return cf_response
async def cloudflare_deletesubdomain(domain: Domains, domain_id: str):
url = "https://api.cloudflare.com/client/v4/zones/" + domain.cf_zone_id + "/dns_records"
header = {"Authorization": "Bearer " + domain.cf_token, "Content-Type": "application/json"}
async with httpx.AsyncClient() as client:
try:
r = await client.delete(
url + "/" + domain_id,
headers=header,
timeout=40,
)
cf_response = r.text
except AssertionError:
cf_response = "Error occured"

26
lnbits/extensions/subdomains/tasks.py

@ -1,7 +1,6 @@
from http import HTTPStatus from http import HTTPStatus
from quart.json import jsonify from quart.json import jsonify
import trio # type: ignore import trio # type: ignore
import json
import httpx import httpx
from .crud import get_domain, set_subdomain_paid from .crud import get_domain, set_subdomain_paid
@ -9,6 +8,7 @@ from lnbits.core.crud import get_user, get_wallet
from lnbits.core import db as core_db from lnbits.core import db as core_db
from lnbits.core.models import Payment from lnbits.core.models import Payment
from lnbits.tasks import register_invoice_listener from lnbits.tasks import register_invoice_listener
from .cloudflare import cloudflare_create_subdomain
async def register_listeners(): async def register_listeners():
@ -31,28 +31,10 @@ async def on_invoice_paid(payment: Payment) -> None:
subdomain = await set_subdomain_paid(payment_hash=payment.payment_hash) subdomain = await set_subdomain_paid(payment_hash=payment.payment_hash)
domain = await get_domain(subdomain.domain) domain = await get_domain(subdomain.domain)
### SEND REQUEST TO CLOUDFLARE ### Create subdomain
url = "https://api.cloudflare.com/client/v4/zones/" + domain.cf_zone_id + "/dns_records" cf_response = cloudflare_create_subdomain(
header = {"Authorization": "Bearer " + domain.cf_token, "Content-Type": "application/json"} domain=domain, subdomain=subdomain.subdomain, record_type=subdomain.record_type, ip=subdomain.ip
aRecord = subdomain.subdomain + "." + subdomain.domain_name
cf_response = ""
async with httpx.AsyncClient() as client:
try:
r = await client.post(
url,
headers=header,
json={
"type": subdomain.record_type,
"name": aRecord,
"content": subdomain.ip,
"ttl": 0,
"proxed": False,
},
timeout=40,
) )
cf_response = r.text
except AssertionError:
cf_response = "Error occured"
### Use webhook to notify about cloudflare registration ### Use webhook to notify about cloudflare registration
if domain.webhook: if domain.webhook:

26
lnbits/extensions/subdomains/views_api.py

@ -2,7 +2,9 @@ import re
from quart import g, jsonify, request from quart import g, jsonify, request
from http import HTTPStatus from http import HTTPStatus
from lnbits.core import crud from lnbits.core import crud
import json
import httpx
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 create_invoice, check_invoice_status
from lnbits.decorators import api_check_wallet_key, api_validate_post_request from lnbits.decorators import api_check_wallet_key, api_validate_post_request
@ -21,6 +23,7 @@ from .crud import (
delete_domain, delete_domain,
get_subdomainBySubdomain, get_subdomainBySubdomain,
) )
from .cloudflare import cloudflare_create_subdomain, cloudflare_deletesubdomain
# domainS # domainS
@ -113,32 +116,45 @@ async def api_subdomains():
async def api_subdomain_make_subdomain(domain_id): async def api_subdomain_make_subdomain(domain_id):
domain = await get_domain(domain_id) domain = await get_domain(domain_id)
# If the request is coming for the non-existant domain
if not domain: if not domain:
return jsonify({"message": "LNsubdomain does not exist."}), HTTPStatus.NOT_FOUND return jsonify({"message": "LNsubdomain does not exist."}), HTTPStatus.NOT_FOUND
# regex if IP is address
if not isvalidIPAddress(g.data["ip"]): if not isvalidIPAddress(g.data["ip"]):
return jsonify({"message": g.data["ip"] + " Not a valid IP address"}), HTTPStatus.BAD_REQUEST return jsonify({"message": g.data["ip"] + " Not a valid IP address"}), HTTPStatus.BAD_REQUEST
# regex for checking if domain is valid
if not isValidDomain(g.data["subdomain"] + "." + domain.domain): if not isValidDomain(g.data["subdomain"] + "." + domain.domain):
return ( return (
jsonify({"message": g.data["subdomain"] + "." + domain.domain + " bad domain name"}), jsonify({"message": g.data["subdomain"] + "." + domain.domain + " bad domain name"}),
HTTPStatus.BAD_REQUEST, HTTPStatus.BAD_REQUEST,
) )
## If domain already exist in our database reject it
if await get_subdomainBySubdomain(g.data["subdomain"]) is not None: if await get_subdomainBySubdomain(g.data["subdomain"]) is not None:
return ( return (
jsonify({"message": g.data["subdomain"] + "." + domain.domain + " domain already taken"}), jsonify({"message": g.data["subdomain"] + "." + domain.domain + " domain already taken"}),
HTTPStatus.BAD_REQUEST, HTTPStatus.BAD_REQUEST,
) )
## If record_type is not one of the allowed ones reject the request
if g.data["record_type"] not in domain.allowed_record_types: if g.data["record_type"] not in domain.allowed_record_types:
return jsonify({"message": g.data["record_type"] + "Not a valid record"}), HTTPStatus.BAD_REQUEST return jsonify({"message": g.data["record_type"] + "Not a valid record"}), HTTPStatus.BAD_REQUEST
## Dry run cloudflare... (create and if create is sucessful delete it)
cf_response = await cloudflare_create_subdomain(
domain=domain, subdomain=g.data["subdomain"], record_type=g.data["record_type"], ip=g.data["ip"]
)
if cf_response["success"] == True:
cloudflare_deletesubdomain(domain=domain, domain_id=cf_response["result"]["id"])
else:
return (
jsonify({"message": "Problem with cloudflare: " + cf_response["errors"][0]["message"]}),
HTTPStatus.BAD_REQUEST,
)
subdomain = g.data["subdomain"] ## ALL OK - create an invoice and return it to the user
duration = g.data["duration"]
sats = g.data["sats"] sats = g.data["sats"]
payment_hash, payment_request = await create_invoice( payment_hash, payment_request = await create_invoice(
wallet_id=domain.wallet, wallet_id=domain.wallet,
amount=sats, amount=sats,
memo=f"subdomain {subdomain}.{domain.domain} for {sats} sats for {duration} days", memo=f"subdomain {g.data['subdomain']}.{domain.domain} for {sats} sats for {g.data['duration']} days",
extra={"tag": "lnsubdomain"}, extra={"tag": "lnsubdomain"},
) )

Loading…
Cancel
Save