From 70ccfe2c2967677896d4db8d9ee7fb6107d2e9ae Mon Sep 17 00:00:00 2001 From: Matthew Grotke Date: Sun, 7 Jun 2026 00:21:08 -0400 Subject: [PATCH] Development --- .../routlin-dash/app/action_accountlogout.py | 4 +- docker/routlin-dash/app/api_apply_health.py | 19 +++-- docker/routlin-dash/app/factory.py | 71 ++++++++----------- docker/routlin-dash/app/main.py | 48 ++++++------- .../app/pages/accountcreate/action.py | 10 +-- .../app/pages/accountcreate/view.py | 4 +- .../app/pages/accountlogin/action.py | 8 +-- .../app/pages/accountlogin/view.py | 4 +- .../app/pages/accountmanage/action.py | 12 ++-- .../app/pages/accountmanage/view.py | 12 ++-- .../app/pages/accountverifyemail/action.py | 12 ++-- .../app/pages/accountverifyemail/view.py | 4 +- .../routlin-dash/app/pages/actions/action.py | 28 ++++---- docker/routlin-dash/app/pages/actions/view.py | 47 ++++++------ .../app/pages/bannedips/action.py | 38 +++++----- .../routlin-dash/app/pages/bannedips/view.py | 12 ++-- .../app/pages/clientcredentials/action.py | 8 +-- .../app/pages/clientcredentials/view.py | 16 ++--- docker/routlin-dash/app/pages/ddns/action.py | 70 +++++++++--------- docker/routlin-dash/app/pages/ddns/view.py | 30 ++++---- .../routlin-dash/app/pages/dhcpleases/view.py | 30 ++++---- .../app/pages/dhcpreservations/action.py | 38 +++++----- .../app/pages/dhcpreservations/view.py | 12 ++-- .../app/pages/dnsblocking/action.py | 60 ++++++++-------- .../app/pages/dnsblocking/view.py | 24 +++---- .../app/pages/dnsserver/action.py | 24 +++---- .../routlin-dash/app/pages/dnsserver/view.py | 4 +- .../app/pages/hostoverrides/action.py | 38 +++++----- .../app/pages/hostoverrides/view.py | 12 ++-- .../app/pages/intervlan/action.py | 38 +++++----- .../routlin-dash/app/pages/intervlan/view.py | 12 ++-- docker/routlin-dash/app/pages/mdns/action.py | 14 ++-- docker/routlin-dash/app/pages/mdns/view.py | 4 +- .../app/pages/networklayout/action.py | 30 ++++---- .../app/pages/networklayout/view.py | 14 ++-- .../routlin-dash/app/pages/overview/view.py | 26 +++---- .../app/pages/physicalinterfaces/action.py | 24 +++---- .../app/pages/physicalinterfaces/view.py | 4 +- .../app/pages/portforwarding/action.py | 38 +++++----- .../app/pages/portforwarding/view.py | 12 ++-- .../app/pages/portwrangling/action.py | 38 +++++----- .../app/pages/portwrangling/view.py | 12 ++-- .../app/pages/preferences/action.py | 12 ++-- .../app/pages/preferences/view.py | 4 +- .../routlin-dash/app/pages/radius/action.py | 56 +++++++-------- docker/routlin-dash/app/pages/radius/view.py | 8 +-- docker/routlin-dash/app/pages/vpn/action.py | 60 ++++++++-------- docker/routlin-dash/app/pages/vpn/view.py | 22 +++--- 48 files changed, 549 insertions(+), 578 deletions(-) diff --git a/docker/routlin-dash/app/action_accountlogout.py b/docker/routlin-dash/app/action_accountlogout.py index 3a10b35..829f296 100644 --- a/docker/routlin-dash/app/action_accountlogout.py +++ b/docker/routlin-dash/app/action_accountlogout.py @@ -1,11 +1,11 @@ from flask import Blueprint, session, redirect -from auth import require_level +import auth bp = Blueprint('accountlogout', __name__) @bp.route('/action/accountlogout/logout', methods=['POST']) -@require_level('viewer') +@auth.require_level('viewer') def logout(): session.clear() return redirect('/overview') diff --git a/docker/routlin-dash/app/api_apply_health.py b/docker/routlin-dash/app/api_apply_health.py index 3b6f6b7..e118484 100644 --- a/docker/routlin-dash/app/api_apply_health.py +++ b/docker/routlin-dash/app/api_apply_health.py @@ -1,28 +1,25 @@ from flask import Blueprint, request, jsonify -from auth import require_level -from config_utils import ( - _load_done_set, _is_locked, _lock_mtime, - _seconds_until_next_run, _entry_ts_from_queue, -) +import auth +import config_utils bp = Blueprint('api_apply_health', __name__) @bp.route('/api/apply-health') -@require_level('viewer') +@auth.require_level('viewer') def apply_health(): entry_uuid = request.args.get('uuid', '') if not entry_uuid: return jsonify({'status': 'unknown'}) - if entry_uuid in _load_done_set(): + if entry_uuid in config_utils._load_done_set(): return jsonify({'status': 'complete'}) - if _is_locked(): - mtime = _lock_mtime() - entry_ts = _entry_ts_from_queue(entry_uuid) + if config_utils._is_locked(): + mtime = config_utils._lock_mtime() + entry_ts = config_utils._entry_ts_from_queue(entry_uuid) if mtime and entry_ts is not None and entry_ts < mtime: return jsonify({'status': 'running'}) return jsonify({'status': 'pending', 'next_in': None}) - return jsonify({'status': 'pending', 'next_in': _seconds_until_next_run()}) + return jsonify({'status': 'pending', 'next_in': config_utils._seconds_until_next_run()}) diff --git a/docker/routlin-dash/app/factory.py b/docker/routlin-dash/app/factory.py index 12b0b67..ad1a47c 100644 --- a/docker/routlin-dash/app/factory.py +++ b/docker/routlin-dash/app/factory.py @@ -3,24 +3,13 @@ from flask import session from markupsafe import Markup import json, re, sys, html as html_mod, os, subprocess -from config_utils import ( - config_hash, load_config, CONFIGS_DIR, WWW_DIR, APP_DIR, - ACCOUNTS_FILE, HEALTH_FILE, BLOCKLISTS_DIR, - fmt_timestamp, relative_time, fmt_bytes, resolve_iface, - WEB_APP_DISPLAY_NAME, -) -from config_utils import ( - get_pending_entries, get_dashboard_pending, _find_cmd_in_queues, - _apply_changes_immediately, _seconds_until_next_run, _format_timing, - _is_locked, _lock_mtime, _entry_ts_from_queue, -) +import config_utils +import settings -import settings as settings - -PAGES_DIR = os.path.join(APP_DIR, 'pages') -NAVBAR_FILE = os.path.join(APP_DIR, 'navbar.json') -CSS_FILE = os.path.join(WWW_DIR, 'styles.css') -COMMON_JS_FILE = os.path.join(WWW_DIR, 'common.js') +PAGES_DIR = os.path.join(config_utils.APP_DIR, 'pages') +NAVBAR_FILE = os.path.join(config_utils.APP_DIR, 'navbar.json') +CSS_FILE = os.path.join(config_utils.WWW_DIR, 'styles.css') +COMMON_JS_FILE = os.path.join(config_utils.WWW_DIR, 'common.js') def _file_version(path): @@ -55,7 +44,7 @@ VALIDATION_FLAGS = { def _restricted_vlan_subnets(): """Return list of 'subnet/prefix' strings for all restricted VLANs.""" - vlans = load_config().get('vlans', []) + vlans = config_utils.load_config().get('vlans', []) result = [] for v in vlans: if v.get('restricted_vlan') in ('q', 'c') and v.get('subnet') and v.get('subnet_mask') is not None: @@ -73,10 +62,10 @@ def load_json(path): return {} def load_ddns(): - return load_config().get('ddns', {}) + return config_utils.load_config().get('ddns', {}) def load_accounts(): - return load_json(ACCOUNTS_FILE) + return load_json(config_utils.ACCOUNTS_FILE) def run(cmd): try: @@ -94,7 +83,7 @@ def load_css(): def load_icon(name): try: - with open(f'{WWW_DIR}/icons/{name}.svg') as f: + with open(f'{config_utils.WWW_DIR}/icons/{name}.svg') as f: return f.read().strip() except Exception: return '' @@ -1036,7 +1025,7 @@ def build_table(item, tokens, rows, inherited_req=None): columns = item.get('columns', []) empty = e(item.get('empty_message', 'No data.')) row_actions = item.get('row_actions', []) - hash_val = config_hash() + hash_val = config_utils.config_hash() toolbar_html = '' toolbar = item.get('toolbar') @@ -1245,7 +1234,7 @@ def build_item(item, tokens, inherited_req=None): '' '' f'