feat: Move acme to blueprint and cleanup json responses
All checks were successful
Build Docker / BuildImage (push) Successful in 57s

This commit is contained in:
2025-10-11 18:08:00 +11:00
parent 74362de02a
commit 399ac5f0da
3 changed files with 51 additions and 51 deletions

36
blueprints/acme.py Normal file
View File

@@ -0,0 +1,36 @@
from flask import Blueprint, request
import os
from cloudflare import Cloudflare
from tools import json_response
acme_bp = Blueprint('acme', __name__)
@acme_bp.route("/hnsdoh-acme", methods=["POST"])
def acme_post():
# Get the TXT record from the request
if not request.is_json or not request.json:
return json_response(request, "415 Unsupported Media Type", 415)
if "txt" not in request.json or "auth" not in request.json:
return json_response(request, "400 Bad Request", 400)
txt = request.json["txt"]
auth = request.json["auth"]
if auth != os.getenv("CF_AUTH"):
return json_response(request, "401 Unauthorized", 401)
cf = Cloudflare(api_token=os.getenv("CF_TOKEN"))
zone = cf.zones.list(name="hnsdoh.com").to_dict()
zone_id = zone["result"][0]["id"] # type: ignore
existing_records = cf.dns.records.list(
zone_id=zone_id, type="TXT", name="_acme-challenge.hnsdoh.com" # type: ignore
).to_dict()
record_id = existing_records["result"][0]["id"] # type: ignore
cf.dns.records.delete(dns_record_id=record_id, zone_id=zone_id)
cf.dns.records.create(
zone_id=zone_id,
type="TXT",
name="_acme-challenge",
content=txt,
)
return json_response(request, "Success", 200)

View File

@@ -13,7 +13,6 @@ from flask_cors import CORS
import os import os
import dotenv import dotenv
import requests import requests
from cloudflare import Cloudflare
import datetime import datetime
import qrcode import qrcode
from qrcode.constants import ERROR_CORRECT_L, ERROR_CORRECT_H from qrcode.constants import ERROR_CORRECT_L, ERROR_CORRECT_H
@@ -24,6 +23,7 @@ from blueprints.blog import blog_bp
from blueprints.wellknown import wk_bp from blueprints.wellknown import wk_bp
from blueprints.api import api_bp, getGitCommit from blueprints.api import api_bp, getGitCommit
from blueprints.podcast import podcast_bp from blueprints.podcast import podcast_bp
from blueprints.acme import acme_bp
from tools import isCurl, isCrawler, getAddress, getFilePath, error_response, getClientIP from tools import isCurl, isCrawler, getAddress, getFilePath, error_response, getClientIP
app = Flask(__name__) app = Flask(__name__)
@@ -35,6 +35,7 @@ app.register_blueprint(blog_bp, url_prefix='/blog')
app.register_blueprint(wk_bp, url_prefix='/.well-known') app.register_blueprint(wk_bp, url_prefix='/.well-known')
app.register_blueprint(api_bp, url_prefix='/api/v1') app.register_blueprint(api_bp, url_prefix='/api/v1')
app.register_blueprint(podcast_bp) app.register_blueprint(podcast_bp)
app.register_blueprint(acme_bp)
dotenv.load_dotenv() dotenv.load_dotenv()
@@ -712,47 +713,6 @@ def resume_pdf_get():
return error_response(request, message="Resume not found") return error_response(request, message="Resume not found")
# endregion # endregion
# region ACME route
@app.route("/hnsdoh-acme", methods=["POST"])
def acme_post():
print(f"ACME request from {getClientIP(request)}")
# Get the TXT record from the request
if not request.json:
print("No JSON data provided for ACME")
return jsonify({"status": "error", "error": "No JSON data provided"})
if "txt" not in request.json or "auth" not in request.json:
print("Missing required data for ACME")
return jsonify({"status": "error", "error": "Missing required data"})
txt = request.json["txt"]
auth = request.json["auth"]
if auth != os.getenv("CF_AUTH"):
print("Invalid auth for ACME")
return jsonify({"status": "error", "error": "Invalid auth"})
cf = Cloudflare(api_token=os.getenv("CF_TOKEN"))
zone = cf.zones.list(name="hnsdoh.com").to_dict()
zone_id = zone["result"][0]["id"] # type: ignore
existing_records = cf.dns.records.list(
zone_id=zone_id, type="TXT", name="_acme-challenge.hnsdoh.com" # type: ignore
).to_dict()
record_id = existing_records["result"][0]["id"] # type: ignore
cf.dns.records.delete(dns_record_id=record_id, zone_id=zone_id)
cf.dns.records.create(
zone_id=zone_id,
type="TXT",
name="_acme-challenge",
content=txt,
)
print(f"ACME request successful: {txt}")
return jsonify({"status": "success"})
# endregion
# region Error Catching # region Error Catching
# Catch all for GET requests # Catch all for GET requests

View File

@@ -58,15 +58,19 @@ def getFilePath(name, path):
if name in files: if name in files:
return os.path.join(root, name) return os.path.join(root, name)
def error_response(request: Request, message: str = "404 Not Found", code: int = 404): def json_response(request: Request, message: str = "404 Not Found", code: int = 404):
if isCurl(request): return jsonify(
return jsonify( {
{ "status": code,
"status": code, "message": message,
"message": message, "ip": getClientIP(request),
"ip": getClientIP(request), }
} ), code
), code
def error_response(request: Request, message: str = "404 Not Found", code: int = 404, force_json: bool = False):
if force_json or isCurl(request):
return json_response(request, message, code)
# Check if <error code>.html exists in templates # Check if <error code>.html exists in templates
if os.path.isfile(f"templates/{code}.html"): if os.path.isfile(f"templates/{code}.html"):