mirror of
https://github.com/lnbits/lnbits.git
synced 2025-09-28 12:56:16 +02:00
added checks to the cloudflare if the domain can be created; code refactoring - moved calls to cloudflare to seperate file
This commit is contained in:
44
lnbits/extensions/subdomains/cloudflare.py
Normal file
44
lnbits/extensions/subdomains/cloudflare.py
Normal file
@@ -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"
|
@@ -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:
|
||||||
|
@@ -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"},
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user