import re import subprocess 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 import sanitize bp = Blueprint('action_apply_interface', __name__) _VIEW = '/view/view_general' 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'} except Exception: return set() @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', '')) try: idx = int(idx_raw) if idx not in (0, 1): raise ValueError except (ValueError, TypeError): flash('Invalid request.', 'error') return redirect(_VIEW) if not interface: flash('Interface name is required.', '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) 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 save_core(core) flash(apply_msg(), 'success') return redirect(_VIEW)