[pve-devel] [PATCH manager] sdn: add model based validation to dhcp ranges

Stefan Sterz s.sterz at proxmox.com
Thu Nov 23 17:09:37 CET 2023


this patch re-works the validation the in the subnit edit panel to
also validate whether the ip address version in a range match each
other.

Signed-off-by: Stefan Sterz <s.sterz at proxmox.com>
---
not super proud of this, but couldn't really find another way to
properly validate accross two columns and also have the panel still work
as intended.

 www/manager6/sdn/SubnetEdit.js | 85 ++++++++++++++++++++++++++++++----
 1 file changed, 76 insertions(+), 9 deletions(-)

diff --git a/www/manager6/sdn/SubnetEdit.js b/www/manager6/sdn/SubnetEdit.js
index 8fc3f52b..cba80d8f 100644
--- a/www/manager6/sdn/SubnetEdit.js
+++ b/www/manager6/sdn/SubnetEdit.js
@@ -59,6 +59,49 @@ Ext.define('PVE.sdn.SubnetInputPanel', {
     ],
 });

+Ext.define('PVE.sdn.model.DhcpRange', {
+    extend: 'Ext.data.Model',
+    fields: [
+        { name: 'startAddress' },
+        { name: 'endAddress' },
+	{
+	    name: 'rangeErrors',
+	    depends: ['startAddress', 'endAddress'],
+	    calculate: (data) => {
+		let errors = [];
+		let sV4 = Proxmox.Utils.IP4_match.test(data.startAddress);
+		let sV6 = Proxmox.Utils.IP6_match.test(data.startAddress);
+		let eV4 = Proxmox.Utils.IP4_match.test(data.endAddress);
+		let eV6 = Proxmox.Utils.IP6_match.test(data.endAddress);
+
+		if (!((sV4 && eV4) || (sV6 && eV6))) {
+		    errors.push("IP address versions do not match.");
+		}
+
+		return errors;
+	    },
+	},
+	{
+	    name: 'rangeErrorsClass',
+	    depends: ['rangeErrors'],
+	    calculate: (data) => {
+		if (data.rangeErrors.length !== 0) {
+		    return ['x-form-trigger-wrap-default', 'x-form-trigger-wrap-invalid'];
+		}
+
+		return [];
+	    }
+	}
+    ],
+
+    validators: {
+        startAddress: (value, record) =>
+	    Ext.form.VTypes.IP64Address(value) || gettext("Not a valid IP address."),
+	endAddress: (value, record) =>
+	    Ext.form.VTypes.IP64Address(value) || gettext("Not a valid IP address."),
+    },
+});
+
 Ext.define('PVE.sdn.SubnetDhcpRangePanel', {
     extend: 'Ext.form.FieldContainer',
     mixins: ['Ext.form.field.Field'],
@@ -86,8 +129,8 @@ Ext.define('PVE.sdn.SubnetDhcpRangePanel', {
 		// needs a deep copy otherwise we run in to ExtJS reference
 		// shenaningans
 		value.push({
-		    'start-address': item.data['start-address'],
-		    'end-address': item.data['end-address'],
+		    'start-address': item.data.startAddress,
+		    'end-address': item.data.endAddress,
 		});
 	    });

@@ -121,8 +164,10 @@ Ext.define('PVE.sdn.SubnetDhcpRangePanel', {
 	    // needs a deep copy otherwise we run in to ExtJS reference
 	    // shenaningans
 	    data.push({
-		'start-address': item['start-address'],
-		'end-address': item['end-address'],
+		startAddress: item['start-address'],
+		endAddress: item['end-address'],
+		rangeErrors: [],
+		rangeErrorsClass: [],
 	    });
 	});

@@ -133,6 +178,18 @@ Ext.define('PVE.sdn.SubnetDhcpRangePanel', {
 	let me = this;
         let errors = [];

+	let grid = me.lookup('grid');
+
+	grid.getStore().data.each((row, index) => {
+	    if (!row.isValid()) {
+		errors.push(gettext("An entry in the DHCP Range is not a valid IP address!"));
+	    }
+
+	    if (row.data.rangeErrors.length !== 0) {
+		row.data.rangeErrors.forEach((error) => errors.push(error));
+	    }
+	});
+
 	return errors;
     },

@@ -182,27 +239,37 @@ Ext.define('PVE.sdn.SubnetDhcpRangePanel', {
 	    reference: 'grid',
 	    scrollable: true,
 	    store: {
-		fields: ['start-address', 'end-address'],
+		model: 'PVE.sdn.model.DhcpRange',
+	    },
+	    itemConfig: {
+		viewModel: true,
 	    },
+	    modelValidation: true,
 	    columns: [
 		{
 		    text: gettext('Start Address'),
 		    xtype: 'widgetcolumn',
-		    dataIndex: 'start-address',
 		    flex: 1,
 		    widget: {
 			xtype: 'textfield',
-			vtype: 'IP64Address',
+			bind: {
+			    value: '{record.startAddress}',
+			    error: '{record.rangeErrors}',
+			    userCls: '{record.rangeErrorsClass}',
+			},
 		    },
 		},
 		{
 		    text: gettext('End Address'),
 		    xtype: 'widgetcolumn',
-		    dataIndex: 'end-address',
 		    flex: 1,
 		    widget: {
 			xtype: 'textfield',
-			vtype: 'IP64Address',
+			bind: {
+			    value: '{record.endAddress}',
+			    error: '{record.rangeErrors}',
+			    userCls: '{record.rangeErrorsClass}',
+			},
 		    },
 		},
 		{
--
2.39.2






More information about the pve-devel mailing list