fix(striker-ui): correct subnet conflict checks in NetworkInitForm

main
Tsu-ba-me 2 years ago
parent 6d54fca666
commit 0fa3cb3be7
  1. 144
      striker-ui/components/NetworkInitForm.tsx

@ -143,16 +143,14 @@ const REQUIRED_NETWORKS: NetworkInput[] = [
]; ];
const MAX_INTERFACES_PER_NETWORK = 2; const MAX_INTERFACES_PER_NETWORK = 2;
const IT_APPEND_KEYS = {
conflictNetworkName: 'conflictNetworkName',
};
const IT_IDS = { const IT_IDS = {
dnsCSV: 'domainNameServerCSV', dnsCSV: 'domainNameServerCSV',
gateway: 'gateway', gateway: 'gateway',
networkInterfaces: (prefix: string) => `${prefix}Interface`, networkInterfaces: (prefix: string) => `${prefix}Interface`,
networkIPAddress: (prefix: string) => `${prefix}IPAddress`, networkIPAddress: (prefix: string) => `${prefix}IPAddress`,
networkName: (prefix: string) => `${prefix}Name`, networkName: (prefix: string) => `${prefix}Name`,
networkSubnet: (prefix: string) => `${prefix}SubnetMask`, networkSubnetMask: (prefix: string) => `${prefix}SubnetMask`,
networkSubnetConflict: (prefix: string) => `${prefix}NetworkSubnetConflict`,
}; };
const NETWORK_INTERFACE_TEMPLATE = Array.from( const NETWORK_INTERFACE_TEMPLATE = Array.from(
@ -160,6 +158,8 @@ const NETWORK_INTERFACE_TEMPLATE = Array.from(
(unused, index) => index + 1, (unused, index) => index + 1,
); );
const createInputTestPrefix = (uuid: string) => `network${uuid}`;
const createNetworkInterfaceTableColumns = ( const createNetworkInterfaceTableColumns = (
handleDragMouseDown: ( handleDragMouseDown: (
row: NetworkInterfaceOverviewMetadata, row: NetworkInterfaceOverviewMetadata,
@ -296,8 +296,8 @@ const NetworkForm: FC<{
const { inputUUID, interfaces, ipAddress, subnetMask, type } = networkInput; const { inputUUID, interfaces, ipAddress, subnetMask, type } = networkInput;
const inputTestPrefix = useMemo( const inputTestPrefix = useMemo(
() => `network${networkIndex}`, () => createInputTestPrefix(inputUUID),
[networkIndex], [inputUUID],
); );
const interfacesInputTestId = useMemo( const interfacesInputTestId = useMemo(
() => IT_IDS.networkInterfaces(inputTestPrefix), () => IT_IDS.networkInterfaces(inputTestPrefix),
@ -308,7 +308,7 @@ const NetworkForm: FC<{
[inputTestPrefix], [inputTestPrefix],
); );
const subnetMaskInputTestId = useMemo( const subnetMaskInputTestId = useMemo(
() => IT_IDS.networkSubnet(inputTestPrefix), () => IT_IDS.networkSubnetMask(inputTestPrefix),
[inputTestPrefix], [inputTestPrefix],
); );
const isNetworkOptional = useMemo( const isNetworkOptional = useMemo(
@ -565,8 +565,10 @@ const NetworkInitForm = forwardRef<
onNoConflict, onNoConflict,
skipUUID, skipUUID,
}: { }: {
onConflict?: (input: Partial<NetworkInput>, index: number) => void; onConflict?: (
onNoConflict?: (index: number) => void; otherInput: Pick<NetworkInput, 'inputUUID' | 'name'>,
) => void;
onNoConflict?: (otherInput: Pick<NetworkInput, 'inputUUID'>) => void;
skipUUID?: string; skipUUID?: string;
}, },
) => { ) => {
@ -578,10 +580,7 @@ const NetworkInitForm = forwardRef<
} catch (netmaskError) {} } catch (netmaskError) {}
return networkInputs.every( return networkInputs.every(
( ({ inputUUID, ipAddressInputRef, name, subnetMaskInputRef }) => {
{ inputUUID, ipAddressInputRef, name, subnetMaskInputRef },
networkIndex,
) => {
if (inputUUID === skipUUID) { if (inputUUID === skipUUID) {
return true; return true;
} }
@ -589,32 +588,23 @@ const NetworkInitForm = forwardRef<
const otherIP = ipAddressInputRef?.current.getValue?.call(null); const otherIP = ipAddressInputRef?.current.getValue?.call(null);
const otherMask = subnetMaskInputRef?.current.getValue?.call(null); const otherMask = subnetMaskInputRef?.current.getValue?.call(null);
// console.log(
// `local=${otherIP}/${otherMask},current=${changedIP}/${changedMask}`,
// );
let isConflict = false; let isConflict = false;
try { try {
const otherSubnet = new Netmask(`${otherIP}/${otherMask}`); const otherSubnet = new Netmask(`${otherIP}/${otherMask}`);
isConflict = otherSubnet.contains(changedIP); isConflict =
otherSubnet.contains(changedIP) ||
(changedSubnet !== undefined &&
changedSubnet.contains(String(otherIP)));
// eslint-disable-next-line no-empty // eslint-disable-next-line no-empty
} catch (netmaskError) {} } catch (netmaskError) {}
// console.log(`isConflict=${isConflict}`);
if (changedSubnet) {
isConflict = isConflict || changedSubnet.contains(String(otherIP));
}
// console.log(`isReverseConflict=${isConflict}`);
if (isConflict) { if (isConflict) {
onConflict?.call(null, { name }, networkIndex); onConflict?.call(null, { inputUUID, name });
} else { } else {
onNoConflict?.call(null, networkIndex); onNoConflict?.call(null, { inputUUID });
} }
return !isConflict; return !isConflict;
@ -668,18 +658,58 @@ const NetworkInitForm = forwardRef<
}; };
networkInputs.forEach( networkInputs.forEach(
( ({
{ inputUUID, interfaces, ipAddressInputRef, name, subnetMaskInputRef }, inputUUID,
networkIndex, interfaces,
) => { ipAddressInputRef,
const inputTestPrefix = `network${networkIndex}`; name,
subnetMaskInputRef,
}) => {
const inputTestPrefix = createInputTestPrefix(inputUUID);
const inputTestIDIPAddress = IT_IDS.networkIPAddress(inputTestPrefix); const inputTestIDIPAddress = IT_IDS.networkIPAddress(inputTestPrefix);
const inputTestIDSubnetMask = IT_IDS.networkSubnet(inputTestPrefix); const inputTestIDSubnetMask = IT_IDS.networkSubnetMask(inputTestPrefix);
const setNetworkIPAddressInputMessage = (message?: Message) => const setNetworkIPAddressInputMessage = (message?: Message) =>
setMessage(inputTestIDIPAddress, message); setMessage(inputTestIDIPAddress, message);
const setNetworkSubnetMaskInputMessage = (message?: Message) => const setNetworkSubnetMaskInputMessage = (message?: Message) =>
setMessage(inputTestIDSubnetMask, message); setMessage(inputTestIDSubnetMask, message);
const setNetworkSubnetConflict = (
uuid: string,
otherUUID: string,
message?: Message,
) => {
const id = `${IT_IDS.networkSubnetConflict(
inputTestPrefix,
)}-${otherUUID}`;
const reverseID = `${IT_IDS.networkSubnetConflict(
createInputTestPrefix(otherUUID),
)}-${uuid}`;
setMessage(
messageGroupRef.current.exists?.call(null, reverseID)
? reverseID
: id,
message,
);
};
const testNetworkSubnetConflictWithDefaults = ({
ip = ipAddressInputRef?.current.getValue?.call(null),
mask = subnetMaskInputRef?.current.getValue?.call(null),
}: {
ip?: string;
mask?: string;
}) =>
testSubnetConflict(ip, mask, {
onConflict: ({ inputUUID: otherUUID, name: otherName }) => {
setNetworkSubnetConflict(inputUUID, otherUUID, {
children: `"${name}" and "${otherName}" cannot be in the same subnet.`,
});
},
onNoConflict: ({ inputUUID: otherUUID }) => {
setNetworkSubnetConflict(inputUUID, otherUUID);
},
skipUUID: inputUUID,
});
tests[IT_IDS.networkInterfaces(inputTestPrefix)] = { tests[IT_IDS.networkInterfaces(inputTestPrefix)] = {
defaults: { getValue: () => getFilled(interfaces).length }, defaults: { getValue: () => getFilled(interfaces).length },
@ -702,25 +732,8 @@ const NetworkInitForm = forwardRef<
test: ({ value }) => REP_IPV4.test(value as string), test: ({ value }) => REP_IPV4.test(value as string),
}, },
{ {
onFailure: ({ append }) => { test: ({ value }) =>
setNetworkIPAddressInputMessage({ testNetworkSubnetConflictWithDefaults({ ip: value as string }),
children: `"${name}" and "${
append[IT_APPEND_KEYS.conflictNetworkName]
}" cannot be in the same subnet.`,
});
},
test: ({ append, value }) => {
const changedIP = value as string;
const changedMask =
subnetMaskInputRef?.current.getValue?.call(null);
return testSubnetConflict(changedIP, changedMask, {
onConflict: ({ name: networkName }) => {
append[IT_APPEND_KEYS.conflictNetworkName] = networkName;
},
skipUUID: inputUUID,
});
},
}, },
{ test: testNotBlank }, { test: testNotBlank },
], ],
@ -729,7 +742,7 @@ const NetworkInitForm = forwardRef<
defaults: { value: name }, defaults: { value: name },
tests: [{ test: testNotBlank }], tests: [{ test: testNotBlank }],
}; };
tests[IT_IDS.networkSubnet(inputTestPrefix)] = { tests[IT_IDS.networkSubnetMask(inputTestPrefix)] = {
defaults: { defaults: {
getValue: () => subnetMaskInputRef?.current.getValue?.call(null), getValue: () => subnetMaskInputRef?.current.getValue?.call(null),
onSuccess: () => { onSuccess: () => {
@ -746,25 +759,10 @@ const NetworkInitForm = forwardRef<
test: ({ value }) => REP_IPV4.test(value as string), test: ({ value }) => REP_IPV4.test(value as string),
}, },
{ {
onFailure: ({ append }) => { test: ({ value }) =>
setNetworkSubnetMaskInputMessage({ testNetworkSubnetConflictWithDefaults({
children: `IP address in ${name} conflicts with ${ mask: value as string,
append[IT_APPEND_KEYS.conflictNetworkName] }),
}.`,
});
},
test: ({ append, value }) => {
const changedIP =
ipAddressInputRef?.current.getValue?.call(null);
const changedMask = value as string;
return testSubnetConflict(changedIP, changedMask, {
onConflict: ({ name: networkName }) => {
append[IT_APPEND_KEYS.conflictNetworkName] = networkName;
},
skipUUID: inputUUID,
});
},
}, },
{ test: testNotBlank }, { test: testNotBlank },
], ],

Loading…
Cancel
Save