mirror of
https://github.com/hanzoskill/npm-proxy.git
synced 2026-10-30 21:03:23 +00:00
125 lines
4.2 KiB
Python
125 lines
4.2 KiB
Python
#!/usr/bin/env python3
|
|
import json
|
|
import os
|
|
import sys
|
|
import urllib.request
|
|
import urllib.error
|
|
import time
|
|
|
|
# Environment variables
|
|
NPM_URL = os.environ.get("NPM_URL", "").rstrip("/")
|
|
NPM_EMAIL = os.environ.get("NPM_EMAIL", "")
|
|
NPM_PASSWORD = os.environ.get("NPM_PASSWORD", "")
|
|
|
|
TOKEN_FILE = "/root/.npm-token.json"
|
|
|
|
def get_token():
|
|
"""Retrieve or refresh the API token."""
|
|
if os.path.exists(TOKEN_FILE):
|
|
with open(TOKEN_FILE, "r") as f:
|
|
data = json.load(f)
|
|
# Check if token is still valid (using a 1-hour buffer)
|
|
if data.get("expires_at", 0) > time.time() + 3600:
|
|
return data["token"]
|
|
|
|
# Login to get new token
|
|
url = f"{NPM_URL}/api/tokens"
|
|
payload = {"identity": NPM_EMAIL, "secret": NPM_PASSWORD}
|
|
req = urllib.request.Request(url, data=json.dumps(payload).encode(), headers={"Content-Type": "application/json"})
|
|
|
|
try:
|
|
with urllib.request.urlopen(req) as res:
|
|
result = json.loads(res.read().decode())
|
|
token = result["token"]
|
|
# Expiration is usually ISO string "2026-01-24T18:15:57.122Z"
|
|
from datetime import datetime
|
|
expires_str = result["expires"].replace("Z", "+00:00")
|
|
expires_at = datetime.fromisoformat(expires_str).timestamp()
|
|
|
|
with open(TOKEN_FILE, "w") as f:
|
|
json.dump({"token": token, "expires_at": expires_at}, f)
|
|
return token
|
|
except Exception as e:
|
|
print(f"Error authenticating with NPM: {e}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
def api_call(endpoint, method="GET", payload=None):
|
|
token = get_token()
|
|
url = f"{NPM_URL}/api/{endpoint}"
|
|
headers = {
|
|
"Authorization": f"Bearer {token}",
|
|
"Content-Type": "application/json"
|
|
}
|
|
|
|
data = json.dumps(payload).encode() if payload else None
|
|
req = urllib.request.Request(url, data=data, headers=headers, method=method)
|
|
|
|
try:
|
|
with urllib.request.urlopen(req) as res:
|
|
return json.loads(res.read().decode())
|
|
except urllib.error.HTTPError as e:
|
|
print(f"NPM API Error ({e.code}): {e.read().decode()}", file=sys.stderr)
|
|
sys.exit(1)
|
|
except Exception as e:
|
|
print(f"Error calling NPM API: {e}", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
def cmd_hosts():
|
|
hosts = api_call("nginx/proxy-hosts")
|
|
print(f"{'ID':<4} {'Domain':<30} {'Forward To':<30} {'SSL':<5} {'Status':<10}")
|
|
print("-" * 85)
|
|
for h in hosts:
|
|
domain = h["domain_names"][0] if h["domain_names"] else "N/A"
|
|
forward = f"{h['forward_host']}:{h['forward_port']}"
|
|
ssl = "✅" if h["certificate_id"] else "❌"
|
|
status = "🟢 ON" if h["enabled"] else "🔴 OFF"
|
|
print(f"{h['id']:<4} {domain[:29]:<30} {forward[:29]:<30} {ssl:<5} {status:<10}")
|
|
|
|
def cmd_host(host_id):
|
|
host = api_call(f"nginx/proxy-hosts/{host_id}")
|
|
print(json.dumps(host, indent=2))
|
|
|
|
def cmd_toggle(host_id, enable=True):
|
|
action = "enable" if enable else "disable"
|
|
res = api_call(f"nginx/proxy-hosts/{host_id}/{action}", method="POST")
|
|
print(f"Host {host_id} {action}d.")
|
|
|
|
def cmd_delete(host_id):
|
|
api_call(f"nginx/proxy-hosts/{host_id}", method="DELETE")
|
|
print(f"Host {host_id} deleted.")
|
|
|
|
def cmd_certs():
|
|
certs = api_call("nginx/certificates")
|
|
print(f"{'ID':<4} {'Nice Name':<30} {'Expires':<20}")
|
|
print("-" * 55)
|
|
for c in certs:
|
|
print(f"{c['id']:<4} {c['nice_name'][:29]:<30} {c['expires_on'][:19]:<20}")
|
|
|
|
def main():
|
|
if not NPM_URL or not NPM_EMAIL or not NPM_PASSWORD:
|
|
print("Error: NPM_URL, NPM_EMAIL, and NPM_PASSWORD must be set in env.", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
if len(sys.argv) < 2:
|
|
print("Usage: npm_client.py <hosts|host|enable|disable|delete|certs> [args...]")
|
|
sys.exit(0)
|
|
|
|
cmd = sys.argv[1]
|
|
if cmd == "hosts":
|
|
cmd_hosts()
|
|
elif cmd == "host":
|
|
cmd_host(sys.argv[2])
|
|
elif cmd == "enable":
|
|
cmd_toggle(sys.argv[2], True)
|
|
elif cmd == "disable":
|
|
cmd_toggle(sys.argv[2], False)
|
|
elif cmd == "delete":
|
|
cmd_delete(sys.argv[2])
|
|
elif cmd == "certs":
|
|
cmd_certs()
|
|
else:
|
|
print(f"Unknown command: {cmd}")
|
|
|
|
if __name__ == "__main__":
|
|
main()
|