{"repo": "anjomro/headscale-webui", "files": {"renderer.py": {"7ab508f071fe9040ea9133020601197ffb8e4d5d": {"t": 1785595757.0604842, "n": 25065, "h": "9b4a89290f8434d9", "c": "import headscale, helper, json, logging, sys, pytz, os, time, yaml\nfrom flask import Markup, render_template, Flask\nfrom datetime import datetime, timedelta, date\nfrom dateutil import parser\n\n# Threading to speed things up\nfrom concurrent.futures import wait, ALL_COMPLETED\nfrom flask_executor import Executor\n\napp = Flask(__name__)\nexecutor = Executor(app)\n\nlog = logging.getLogger('server.renderer')\n\ndef render_overview():\n url = headscale.get_url()\n api_key = headscale.get_api_key()\n\n timezone = pytz.timezone(os.environ[\"TZ\"] if os.environ[\"TZ\"] else \"UTC\")\n local_time = timezone.localize(datetime.now())\n \n # Overview page will just read static information from the config file and display it\n # Open the config.yaml and parse it.\n config_file = open(\"/etc/headscale/config.yaml\", \"r\")\n config_yaml = yaml.safe_load(config_file)\n\n # Get and display the following information:\n # Overview of the server's machines, users, preauth keys, API key expiration, server version\n \n # Get all machines:\n machines_count = 0\n machines = headscale.get_machines(url, api_key)\n for machine in machines[\"machines\"]:\n machines_count += 1\n\n # Get all routes:\n routes = headscale.get_routes(url,api_key)\n total_routes = len(routes[\"routes\"])\n enabled_routes = 0\n for route in routes[\"routes\"]:\n if route[\"enabled\"] and route['advertised']: \n enabled_routes += 1\n\n # Get a count of all enabled exit routes\n exits_count = 0\n exits_enabled_count = 0\n for route in routes[\"routes\"]:\n if route['advertised']:\n if route[\"prefix\"] == \"0.0.0.0/0\" or route[\"prefix\"] == \"::/0\":\n exits_count +=1\n if route[\"enabled\"]:\n exits_enabled_count += 1\n\n # Get User and PreAuth Key counts\n user_count = 0\n usable_keys_count = 0\n users = headscale.get_users(url, api_key)\n for user in users[\"users\"]:\n user_count +=1\n preauth_keys = headscale.get_preauth_keys(url, api_key, user[\"name\"])\n for key in preauth_keys[\"preAuthKeys\"]:\n expiration_parse = parser.parse(key[\"expiration\"])\n key_expired = True if expiration_parse < local_time else False\n if key[\"reusable\"] and not key_expired: usable_keys_count += 1\n if not key[\"reusable\"] and not key[\"used\"] and not key_expired: usable_keys_count += 1\n\n overview_content = \"\"\"\n
\n
| Machines Added | \"\"\"+ str(machines_count) +\"\"\" |
| Users | \"\"\"+ str(user_count) +\"\"\" |
| Usable PreAuth Keys | \"\"\"+ str(usable_keys_count) +\"\"\" |
| Enabled/Total Routes | \"\"\"+ str(enabled_routes) +\"\"\"/\"\"\"+str(total_routes)+\"\"\" |
| Enabled/Total Exits | \"\"\"+ str(exits_enabled_count) +\"\"\"/\"\"\"+str(exits_count)+\"\"\" |
\n
| IP Prefixes | \"\"\"+str(config_yaml[\"ip_prefixes\"]) +\"\"\" |
| Server URL | \"\"\"+str(config_yaml[\"server_url\"]) +\"\"\" |
| Updates Disabled? | \"\"\"+str(config_yaml[\"disable_check_updates\"]) +\"\"\" |
| Ephemeral Node Timeout | \"\"\"+str(config_yaml[\"ephemeral_node_inactivity_timeout\"]) +\"\"\" |
| Node Update Check Interval | \"\"\"+str(config_yaml[\"node_update_check_interval\"]) +\"\"\" |
\n
| Issuer | \"\"\"+str(config_yaml[\"oidc\"][\"issuer\"]) +\"\"\" |
| Client ID | \"\"\"+str(config_yaml[\"oidc\"][\"client_id\"]) +\"\"\" |
| Scope | \"\"\"+str(config_yaml[\"oidc\"][\"scope\"]) +\"\"\" |
| Allowed Domains | \"\"\"+str(config_yaml[\"oidc\"][\"allowed_domains\"]) +\"\"\" |
| Strip Email Domain | \"\"\"+str(config_yaml[\"oidc\"][\"strip_email_domain\"])+\"\"\" |
\n
| Enabled | \"\"\"+str(config_yaml[\"derp\"][\"server\"][\"enabled\"]) +\"\"\" |
| Region ID | \"\"\"+str(config_yaml[\"derp\"][\"server\"][\"region_id\"]) +\"\"\" |
| Region Code | \"\"\"+str(config_yaml[\"derp\"][\"server\"][\"region_code\"]) +\"\"\" |
| Region Name | \"\"\"+str(config_yaml[\"derp\"][\"server\"][\"region_name\"]) +\"\"\" |
| STUN Address | \"\"\"+str(config_yaml[\"derp\"][\"server\"][\"stun_listen_addr\"]) +\"\"\" |
\n
| Nameservers | \"\"\"+str(config_yaml[\"dns_config\"][\"nameservers\"])+\"\"\" |
| MagicDNS | \"\"\"+str(config_yaml[\"dns_config\"][\"magic_dns\"]) +\"\"\" |
| Domains | \"\"\"+str(config_yaml[\"dns_config\"][\"domains\"]) +\"\"\" |
| Base Domain | \"\"\"+str(config_yaml[\"dns_config\"][\"base_domain\"])+\"\"\" |
\n \"\"\"+route['prefix']+\"\"\"\n
\n \"\"\"\n routes = routes+\"\n# \"\"\"+advertised_route+\"\"\"\n#
\n# \"\"\"\n# routes = routes+\"No keys defined for this user
\"\n if len(preauth_keys[\"preAuthKeys\"]) > 0:\n preauth_keys_collection += \"\"\"\n| ID | \nKey | \n|||||
| \"\"\"+str(key[\"id\"])+\"\"\" | \n\"\"\"+str(key[\"key\"])+\"\"\" | \n