Development

This commit is contained in:
Matthew Grotke 2026-05-20 17:10:18 -04:00
parent 270856b391
commit 2bfa5ff29a
18 changed files with 814 additions and 565 deletions

View file

@ -6,7 +6,7 @@ from flask import Blueprint, make_response, redirect, flash, request
from auth import require_level
from config_utils import load_core, save_core, verify_core_hash, queued_msg, CONFIGS_DIR
import sanitize
import validate
import validation as validate
bp = Blueprint('action_apply_vpn', __name__)
@ -140,19 +140,16 @@ def _conf_response(vlan, peer_name, peer_ip, private_key):
@require_level('administrator')
def apply_vpn():
listen_port_raw = request.form.get('vpn_listen_port', '').strip()
server_endpoint = sanitize.domainname(request.form.get('vpn_server_endpoint', ''))
domain = sanitize.domainname(request.form.get('vpn_domain', ''))
server_endpoint = validate.domainname(request.form.get('vpn_server_endpoint', ''))
domain = validate.domainname(request.form.get('vpn_domain', ''))
dns_raw = request.form.get('vpn_dns_server', '').strip()
mtu_raw = request.form.get('vpn_mtu', '').strip()
if not listen_port_raw:
flash('Listen port is required.', 'error')
return redirect(_VIEW)
try:
listen_port = int(listen_port_raw)
if not (1 <= listen_port <= 65535):
raise ValueError
except (ValueError, TypeError):
listen_port = validate.int_range(listen_port_raw, 1, 65535)
if listen_port is None:
flash(f'"{listen_port_raw}" is not a valid port number (1-65535).', 'error')
return redirect(_VIEW)
@ -165,11 +162,8 @@ def apply_vpn():
mtu = None
if mtu_raw:
try:
mtu = int(mtu_raw)
if not (_MTU_MIN <= mtu <= _MTU_MAX):
raise ValueError
except (ValueError, TypeError):
mtu = validate.int_range(mtu_raw, _MTU_MIN, _MTU_MAX)
if mtu is None:
flash(f'"{mtu_raw}" is not a valid MTU (must be {_MTU_MIN}-{_MTU_MAX}).', 'error')
return redirect(_VIEW)
@ -182,6 +176,11 @@ def apply_vpn():
flash('No WireGuard VLAN found in configuration.', 'error')
return redirect(_VIEW)
for v in core.get('vlans', []):
if v.get('is_vpn') and v is not vpn_vlan and v.get('vpn_information', {}).get('listen_port') == listen_port:
flash(f'Listen port {listen_port} is already used by another VPN VLAN.', 'error')
return redirect(_VIEW)
info = vpn_vlan.setdefault('vpn_information', {})
info['listen_port'] = listen_port
info['server_endpoint'] = server_endpoint
@ -197,6 +196,11 @@ def apply_vpn():
else:
overrides.pop('mtu', None)
errors = validate.validate_config(core)
if errors:
for msg in errors:
flash(msg, 'error')
return redirect(_VIEW)
save_core(core)
flash(queued_msg('core apply'), 'success')
return redirect(_VIEW)
@ -258,6 +262,11 @@ def add_vpn_peer():
'split_tunnel': split_tunnel,
'enabled': enabled,
})
errors = validate.validate_config(core)
if errors:
for msg in errors:
flash(msg, 'error')
return redirect(_VIEW)
save_core(core)
return _conf_response(vpn_vlan, peer_name, peer_ip, private_key)
@ -293,6 +302,11 @@ def edit_vpn_peer():
return redirect(_VIEW)
peers[peer_idx].update({'name': peer_name, 'split_tunnel': split_tunnel, 'enabled': enabled})
errors = validate.validate_config(core)
if errors:
for msg in errors:
flash(msg, 'error')
return redirect(_VIEW)
save_core(core)
flash(queued_msg('core apply'), 'success')
return redirect(_VIEW)
@ -316,6 +330,11 @@ def toggle_vpn_peer():
peers = vlan.get('peers', [])
peers[peer_idx]['enabled'] = not peers[peer_idx].get('enabled', True)
errors = validate.validate_config(core)
if errors:
for msg in errors:
flash(msg, 'error')
return redirect(_VIEW)
save_core(core)
flash(queued_msg('core apply'), 'success')
return redirect(_VIEW)
@ -338,6 +357,11 @@ def delete_vpn_peer():
return redirect(_VIEW)
vlan.get('peers', []).pop(peer_idx)
errors = validate.validate_config(core)
if errors:
for msg in errors:
flash(msg, 'error')
return redirect(_VIEW)
save_core(core)
flash(queued_msg('core apply'), 'success')
return redirect(_VIEW)
@ -362,6 +386,11 @@ def regenerate_vpn_peer():
private_key, public_key = _generate_wg_keypair()
peer = vlan['peers'][peer_idx]
peer['public_key'] = public_key
errors = validate.validate_config(core)
if errors:
for msg in errors:
flash(msg, 'error')
return redirect(_VIEW)
save_core(core)
return _conf_response(vlan, peer['name'], peer['ip'], private_key)