UI improvements and input validations

This commit is contained in:
Matthew Grotke 2026-05-20 04:06:50 -04:00
parent b8c4914a52
commit 270856b391
22 changed files with 1548 additions and 302 deletions

View file

@ -1,9 +1,8 @@
import re
import subprocess
import os
from flask import Blueprint, request, redirect, flash
from auth import require_level
from config_utils import load_core, save_core, verify_core_hash, apply_msg
from config_utils import load_core, save_core, verify_core_hash, queued_msg
import sanitize
bp = Blueprint('action_apply_interface', __name__)
@ -11,11 +10,17 @@ bp = Blueprint('action_apply_interface', __name__)
_VIEW = '/view/view_general'
_EXCLUDE_PREFIXES = ('lo', 'wg', 'docker', 'br-', 'veth',
'tun', 'tap', 'ppp', 'virbr',
'podman', 'vnet', 'macvtap', 'fc-')
def _get_system_interfaces():
try:
r = subprocess.run(['ip', 'link', 'show'], capture_output=True, text=True, timeout=5)
names = re.findall(r'^\d+:\s+(\S+):', r.stdout, re.MULTILINE)
return {n.split('@')[0] for n in names} - {'lo'}
return {
n for n in os.listdir('/sys/class/net')
if not n.startswith(_EXCLUDE_PREFIXES)
and os.path.exists(f'/sys/class/net/{n}/device')
}
except Exception:
return set()
@ -23,41 +28,32 @@ def _get_system_interfaces():
@bp.route('/action/apply_interface', methods=['POST'])
@require_level('administrator')
def apply_interface():
idx_raw = request.form.get('row_index', '').strip()
interface = sanitize.interface_name(request.form.get('interface', ''))
wan = sanitize.interface_name(request.form.get('wan_interface', ''))
lan = sanitize.interface_name(request.form.get('lan_interface', ''))
try:
idx = int(idx_raw)
if idx not in (0, 1):
raise ValueError
except (ValueError, TypeError):
flash('Invalid request.', 'error')
if not wan or not lan:
flash('Both WAN and LAN interfaces are required.', 'error')
return redirect(_VIEW)
if not interface:
flash('Interface name is required.', 'error')
if wan == lan:
flash('WAN and LAN interfaces must be different.', 'error')
return redirect(_VIEW)
if not verify_core_hash(request.form.get('config_hash', '')):
flash('Configuration was modified by another session. Please refresh and try again.', 'error')
return redirect(_VIEW)
available = _get_system_interfaces()
for iface in (wan, lan):
if available and iface not in available:
flash(f"Interface '{iface}' does not exist on this system.", 'error')
return redirect(_VIEW)
core = load_core()
gen = core.setdefault('general', {})
other_key = 'lan_interface' if idx == 0 else 'wan_interface'
if interface == gen.get(other_key, ''):
flash('WAN and LAN interfaces must be different.', 'error')
return redirect(_VIEW)
available = _get_system_interfaces()
if available and interface not in available:
flash(f"Interface '{interface}' does not exist on this system.", 'error')
return redirect(_VIEW)
key = 'wan_interface' if idx == 0 else 'lan_interface'
gen[key] = interface
gen['wan_interface'] = wan
gen['lan_interface'] = lan
save_core(core)
flash(apply_msg(), 'success')
flash(queued_msg('core apply'), 'success')
return redirect(_VIEW)