Add order history, live proxy test, SQLite rate limiter (cross-worker + real client IP)

This commit is contained in:
drjones
2026-09-19 19:26:41 -07:00
parent bac4a695f6
commit 808afbe3f4
3 changed files with 86 additions and 1 deletions

45
app.py
View File

@@ -18,6 +18,25 @@ CFG = db.CFG
app = Flask(__name__)
app.secret_key = CFG["secret_key"]
# simple SQLite-backed rate limiter (shared across gunicorn workers)
def _client_ip():
xff = request.headers.get("X-Forwarded-For", "")
return xff.split(",")[0].strip() if xff else (request.remote_addr or "?")
def _rate_ok(ip, limit=10, window=60):
now = time.time()
d = db.get_db()
d.execute("DELETE FROM rate_limits WHERE ts < ?", (now - window,))
count = d.execute("SELECT COUNT(*) c FROM rate_limits WHERE ip=?", (ip,)).fetchone()["c"]
if count >= limit:
d.close()
return False
d.execute("INSERT INTO rate_limits (ip, ts) VALUES (?,?)", (ip, now))
d.commit()
d.close()
return True
BTCPAY = CFG["btcpay"]
PROXY = CFG["proxy_public"]
SITE_HOST = CFG.get("site_host", "clean-proxys.thetempleofdoom.com")
@@ -229,11 +248,33 @@ def dashboard():
d = db.get_db()
used = d.execute("SELECT COALESCE(SUM(bytes),0) s FROM usage_log WHERE user_id=?", (u["id"],)).fetchone()["s"]
deds = [dict(r) for r in d.execute("SELECT * FROM dedicated_ips WHERE user_id=? ORDER BY id DESC", (u["id"],)).fetchall()]
orders = [dict(r) for r in d.execute(
"SELECT o.*, p.name plan_name, p.gb plan_gb FROM orders o LEFT JOIN plans p ON o.plan_id=p.id "
"WHERE o.user_id=? ORDER BY o.id DESC LIMIT 20", (u["id"],)).fetchall()]
sessions = [dict(r) for r in d.execute(
"SELECT * FROM usage_log WHERE user_id=? ORDER BY id DESC LIMIT 10", (u["id"],)).fetchall()]
d.close()
socks = f"socks5://{u['username']}:{u['proxy_password_plain']}@{PROXY['host']}:{PROXY['socks_port']}"
http = f"http://{u['username']}:{u['proxy_password_plain']}@{PROXY['host']}:{PROXY['http_port']}"
return render_template("dashboard.html", user=u, used_gb=used / 1e9,
socks=socks, http=http, dedicated=deds)
socks=socks, http=http, dedicated=deds, orders=orders, sessions=sessions)
@app.route("/dashboard/test")
@login_required
def dashboard_test():
"""Live proxy check: egress through the customer's own creds via the gateway."""
u = current_user()
proxy = f"socks5h://{u['username']}:{u['proxy_password_plain']}@127.0.0.1:{PROXY['socks_port']}"
try:
import subprocess
r = subprocess.run(["curl", "-s", "--max-time", "20", "-x", proxy,
"http://ip-api.com/json?fields=query,country,city,isp,status"],
capture_output=True, text=True, timeout=25)
return app.response_class(r.stdout or '{"status":"fail","message":"no response"}',
mimetype="application/json")
except Exception as e:
return jsonify({"status": "fail", "message": str(e)}), 502
@app.route("/dashboard/location", methods=["POST"])
@@ -490,6 +531,8 @@ def api_plans():
@app.route("/api/v1/proxy", methods=["POST"])
def api_proxy():
"""Agent-facing one-call purchase: create account + invoice, return creds + checkout URL."""
if not _rate_ok(_client_ip(), limit=10, window=60):
return jsonify({"error": "rate limited"}), 429
data = request.get_json(silent=True) or {}
username = (data.get("username") or "").strip()
password = data.get("password") or ""