Development
This commit is contained in:
parent
96f6e32c8f
commit
5575b06b64
7 changed files with 126 additions and 63 deletions
|
|
@ -1,6 +1,5 @@
|
|||
from pathlib import Path
|
||||
import copy
|
||||
import ipaddress
|
||||
|
||||
from flask import Blueprint, request, redirect, flash
|
||||
from auth import require_level
|
||||
|
|
@ -47,25 +46,6 @@ def _parse_ip():
|
|||
return ip
|
||||
|
||||
|
||||
def _check_ip_conflicts(ip, vlan):
|
||||
if ip == 'dynamic':
|
||||
return None
|
||||
dhcp = vlan.get('dhcp_information', {})
|
||||
pool_start = dhcp.get('dynamic_pool_start')
|
||||
pool_end = dhcp.get('dynamic_pool_end')
|
||||
if pool_start and pool_end:
|
||||
try:
|
||||
if (ipaddress.IPv4Address(pool_start) <= ipaddress.IPv4Address(ip)
|
||||
<= ipaddress.IPv4Address(pool_end)):
|
||||
return f'{ip} falls within the dynamic pool range ({pool_start}-{pool_end}).'
|
||||
except Exception:
|
||||
pass
|
||||
identity_ips = {s['ip'] for s in vlan.get('server_identities', []) if s.get('ip')}
|
||||
if ip in identity_ips:
|
||||
return f'{ip} is already assigned as a server identity IP.'
|
||||
return None
|
||||
|
||||
|
||||
@bp.route('/action/dhcp/addreservation_add', methods=['POST'])
|
||||
@require_level('administrator')
|
||||
def addreservation_add():
|
||||
|
|
@ -94,7 +74,7 @@ def addreservation_add():
|
|||
flash(f'The configuration has not been saved because VLAN "{vlan_name}" was not found.', 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
||||
conflict = _check_ip_conflicts(ip, vlan)
|
||||
conflict = validate.check_reservation_ip_conflicts(ip, vlan)
|
||||
if conflict:
|
||||
flash(f'The configuration has not been saved because {conflict}', 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
|
@ -181,7 +161,7 @@ def reservations_edit():
|
|||
flash('Entry not found.', 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
||||
conflict = _check_ip_conflicts(ip, vlans[vi])
|
||||
conflict = validate.check_reservation_ip_conflicts(ip, vlans[vi])
|
||||
if conflict:
|
||||
flash(f'The configuration has not been saved because {conflict}', 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
|
|
|||
|
|
@ -172,7 +172,11 @@
|
|||
"name": "hostname",
|
||||
"input_type": "text",
|
||||
"validate": "VALIDATION_NETWORK_NAME",
|
||||
"placeholder": "e.g. nas"
|
||||
"optional": true,
|
||||
"placeholder": "e.g. nas",
|
||||
"attrs": {
|
||||
"data-res-hosts-by-vlan": "%RESERVATION_HOSTNAMES_BY_VLAN_JSON%"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
|
|
@ -187,8 +191,13 @@
|
|||
"label": "IP Address",
|
||||
"name": "ip",
|
||||
"input_type": "text",
|
||||
"validate": "VALIDATION_IPV4_FORMAT",
|
||||
"optional": true,
|
||||
"placeholder": "e.g. 192.168.10.50",
|
||||
"hint": "Leave blank to authorize device on this VLAN dynamically."
|
||||
"hint": "Leave blank to authorize device on this VLAN dynamically.",
|
||||
"attrs": {
|
||||
"data-res-ips-by-vlan": "%RESERVATION_IPS_BY_VLAN_JSON%"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "field",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
from pathlib import Path
|
||||
import copy
|
||||
import ipaddress
|
||||
|
||||
from flask import Blueprint, request, redirect, flash
|
||||
from auth import require_level
|
||||
|
|
@ -12,28 +11,6 @@ _PAGE = Path(__file__).parent.name
|
|||
|
||||
bp = Blueprint(_PAGE, __name__)
|
||||
|
||||
def _vlan_networks(cfg):
|
||||
nets = []
|
||||
for v in cfg.get('vlans', []):
|
||||
subnet = v.get('subnet', '')
|
||||
mask = v.get('subnet_mask', '')
|
||||
if subnet and mask:
|
||||
try:
|
||||
nets.append(ipaddress.IPv4Network(f'{subnet}/{mask}', strict=False))
|
||||
except ValueError:
|
||||
pass
|
||||
return nets
|
||||
|
||||
|
||||
def _ip_in_vlan(ip_str, cfg):
|
||||
try:
|
||||
addr = ipaddress.IPv4Address(ip_str)
|
||||
except ValueError:
|
||||
return False
|
||||
nets = _vlan_networks(cfg)
|
||||
return not nets or any(addr in net for net in nets)
|
||||
|
||||
|
||||
def _row_index():
|
||||
try:
|
||||
return int(request.form.get('row_index', ''))
|
||||
|
|
@ -62,8 +39,9 @@ def addoverride_add():
|
|||
return redirect(f'/{_PAGE}')
|
||||
|
||||
cfg = load_config()
|
||||
if not _ip_in_vlan(ip, cfg):
|
||||
flash('IP address does not fall within any configured VLAN subnet.', 'error')
|
||||
err = validate.check_host_override_ip_in_vlans(ip, cfg)
|
||||
if err:
|
||||
flash(err, 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
||||
entry = {'description': description, 'host': host, 'ip': ip, 'enabled': True}
|
||||
|
|
@ -130,8 +108,9 @@ def table_edit():
|
|||
return redirect(f'/{_PAGE}')
|
||||
|
||||
cfg = load_config()
|
||||
if not _ip_in_vlan(ip, cfg):
|
||||
flash('IP address does not fall within any configured VLAN subnet.', 'error')
|
||||
err = validate.check_host_override_ip_in_vlans(ip, cfg)
|
||||
if err:
|
||||
flash(err, 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
||||
items = cfg.get('host_overrides', [])
|
||||
|
|
|
|||
|
|
@ -172,10 +172,11 @@ def wireguard_apply():
|
|||
flash('No WireGuard VLAN found in configuration.', 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
||||
for v in cfg.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(f'/{_PAGE}')
|
||||
err = validate.check_vpn_listen_port_unique(cfg.get('vlans', []), listen_port,
|
||||
exclude_vlan_name=vpn_vlan.get('name'))
|
||||
if err:
|
||||
flash(err, 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
||||
before_info = copy.deepcopy(vpn_vlan.get('vpn_information', {}))
|
||||
info = vpn_vlan.setdefault('vpn_information', {})
|
||||
|
|
@ -242,8 +243,9 @@ def addpeer_add():
|
|||
pass
|
||||
|
||||
peers = vpn_vlan.setdefault('peers', [])
|
||||
if any(p.get('name') == peer_name for p in peers):
|
||||
flash(f'A peer named "{peer_name}" already exists.', 'error')
|
||||
err = validate.check_peer_name_unique(peers, peer_name)
|
||||
if err:
|
||||
flash(err, 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
for v in cfg.get('vlans', []):
|
||||
if not v.get('is_vpn'):
|
||||
|
|
@ -297,8 +299,9 @@ def peers_edit():
|
|||
return redirect(f'/{_PAGE}')
|
||||
|
||||
peers = vlan.get('peers', [])
|
||||
if any(j != peer_idx and p.get('name') == peer_name for j, p in enumerate(peers)):
|
||||
flash(f'A peer named "{peer_name}" already exists.', 'error')
|
||||
err = validate.check_peer_name_unique(peers, peer_name, exclude_idx=peer_idx)
|
||||
if err:
|
||||
flash(err, 'error')
|
||||
return redirect(f'/{_PAGE}')
|
||||
|
||||
before = copy.deepcopy({k: peers[peer_idx].get(k) for k in ('name', 'split_tunnel', 'enabled')})
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue