linuxrouter/docker/router-dash/app/action_apply_vlans.py

129 lines
3.8 KiB
Python

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_vlans', __name__)
VIEW = '/view/view_vlans'
def _row_index():
try:
return int(request.form.get('row_index', ''))
except (ValueError, TypeError):
return None
def _hash_ok():
if not verify_core_hash(request.form.get('config_hash', '')):
flash('Configuration was modified by another session. Please refresh and try again.', 'error')
return False
return True
@bp.route('/action/add_vlan', methods=['POST'])
@require_level('administrator')
def add_vlan():
vlan_id_raw = request.form.get('vlan_id', '').strip()
name = sanitize.name(request.form.get('name', ''))
interface = sanitize.interface_name(request.form.get('interface', ''))
subnet = sanitize.ip_or_cidr(request.form.get('subnet', ''))
radius_default = 'radius_default' in request.form
mdns_reflection = 'mdns_reflection' in request.form
if not vlan_id_raw or not name or not interface:
flash('VLAN ID, name, and interface are required.', 'error')
return redirect(VIEW)
try:
vlan_id = int(vlan_id_raw)
if not (1 <= vlan_id <= 4094):
raise ValueError
except (ValueError, TypeError):
flash('VLAN ID must be between 1 and 4094.', 'error')
return redirect(VIEW)
if not _hash_ok():
return redirect(VIEW)
core = load_core()
vlans = core.setdefault('vlans', [])
if any(v.get('vlan_id') == vlan_id for v in vlans):
flash(f'VLAN {vlan_id} already exists.', 'error')
return redirect(VIEW)
vlans.append({
'vlan_id': vlan_id,
'name': name,
'interface': interface,
'dhcp': {'subnet': subnet},
'use_blocklists': [],
'radius_default': radius_default,
'mdns_reflection': mdns_reflection,
'reservations': [],
})
save_core(core)
flash(apply_msg(), 'success')
return redirect(VIEW)
@bp.route('/action/edit_vlan', methods=['POST'])
@require_level('administrator')
def edit_vlan():
idx = _row_index()
if idx is None:
flash('Invalid request.', 'error')
return redirect(VIEW)
name = sanitize.name(request.form.get('name', ''))
interface = sanitize.interface_name(request.form.get('interface', ''))
subnet = sanitize.ip_or_cidr(request.form.get('subnet', ''))
radius_default = 'radius_default' in request.form
mdns_reflection = 'mdns_reflection' in request.form
if not name or not interface:
flash('Name and interface are required.', 'error')
return redirect(VIEW)
if not _hash_ok():
return redirect(VIEW)
core = load_core()
vlans = core.get('vlans', [])
if idx < 0 or idx >= len(vlans):
flash('VLAN not found.', 'error')
return redirect(VIEW)
vlans[idx].update({'name': name, 'interface': interface, 'radius_default': radius_default, 'mdns_reflection': mdns_reflection})
vlans[idx].setdefault('dhcp', {})['subnet'] = subnet
save_core(core)
flash(apply_msg(), 'success')
return redirect(VIEW)
@bp.route('/action/delete_vlan', methods=['POST'])
@require_level('administrator')
def delete_vlan():
idx = _row_index()
if idx is None:
flash('Invalid request.', 'error')
return redirect(VIEW)
if not _hash_ok():
return redirect(VIEW)
core = load_core()
vlans = core.get('vlans', [])
if idx < 0 or idx >= len(vlans):
flash('VLAN not found.', 'error')
return redirect(VIEW)
removed = vlans.pop(idx)
save_core(core)
flash(apply_msg(), 'success')
return redirect(VIEW)