1
0
mirror of https://gitlab.nic.cz/turris/reforis/foris-js.git synced 2024-06-25 19:43:59 +00:00
foris-js/src/common/WiFiSettings/WiFiForm.js
Aleksandr Gumroian aeddd9ce74
Add a switch to disable Management Frame Protection (802.11w)
In the case of WPA3 encryption Management Frame Protection is enabled
by default in OpenWrt.

But in some cases, it causes trouble with particular devices that
fails to connect to WiFi Access Point - see:
https://forum.turris.cz/t/turris-omnia-wifi-health/15704/15
2022-12-01 16:19:38 +01:00

307 lines
11 KiB
JavaScript

/*
* Copyright (C) 2019-2021 CZ.NIC z.s.p.o. (http://www.nic.cz/)
*
* This is free software, licensed under the GNU General Public License v3.
* See /LICENSE for more information.
*/
import React from "react";
import PropTypes from "prop-types";
import { Switch } from "../../bootstrap/Switch";
import { PasswordInput } from "../../bootstrap/PasswordInput";
import { RadioSet } from "../../bootstrap/RadioSet";
import { Select } from "../../bootstrap/Select";
import { TextInput } from "../../bootstrap/TextInput";
import WiFiQRCode from "./WiFiQRCode";
import WifiGuestForm from "./WiFiGuestForm";
import { HELP_TEXTS, HTMODES, HWMODES, ENCRYPTIONMODES } from "./constants";
WiFiForm.propTypes = {
formData: PropTypes.shape({ devices: PropTypes.arrayOf(PropTypes.object) })
.isRequired,
formErrors: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
setFormValue: PropTypes.func.isRequired,
hasGuestNetwork: PropTypes.bool,
};
WiFiForm.defaultProps = {
formData: { devices: [] },
setFormValue: () => {},
hasGuestNetwork: true,
};
export default function WiFiForm({
formData,
formErrors,
setFormValue,
hasGuestNetwork,
disabled,
}) {
return formData.devices.map((device, index) => (
<DeviceForm
key={device.id}
formData={device}
deviceIndex={index}
formErrors={(formErrors || [])[index]}
setFormValue={setFormValue}
hasGuestNetwork={hasGuestNetwork}
disabled={disabled}
divider={index + 1 !== formData.devices.length}
/>
));
}
DeviceForm.propTypes = {
formData: PropTypes.shape({
id: PropTypes.number.isRequired,
enabled: PropTypes.bool.isRequired,
SSID: PropTypes.string.isRequired,
password: PropTypes.string.isRequired,
hidden: PropTypes.bool.isRequired,
hwmode: PropTypes.string.isRequired,
htmode: PropTypes.string.isRequired,
channel: PropTypes.string.isRequired,
guest_wifi: PropTypes.object.isRequired,
encryption: PropTypes.string.isRequired,
available_bands: PropTypes.array.isRequired,
ieee80211w_disabled: PropTypes.bool.isRequired,
}),
formErrors: PropTypes.object.isRequired,
setFormValue: PropTypes.func.isRequired,
hasGuestNetwork: PropTypes.bool,
deviceIndex: PropTypes.number,
divider: PropTypes.bool,
};
DeviceForm.defaultProps = {
formErrors: {},
hasGuestNetwork: true,
};
function DeviceForm({
formData,
formErrors,
setFormValue,
hasGuestNetwork,
deviceIndex,
divider,
...props
}) {
const deviceID = formData.id;
const bnds = formData.available_bands;
return (
<>
<Switch
label={<h2>{_(`Wi-Fi ${deviceID + 1}`)}</h2>}
checked={formData.enabled}
onChange={setFormValue((value) => ({
devices: {
[deviceIndex]: { enabled: { $set: value } },
},
}))}
switchHeading
{...props}
/>
{formData.enabled && (
<>
<TextInput
label="SSID"
value={formData.SSID}
error={formErrors.SSID || null}
helpText={HELP_TEXTS.ssid}
required
onChange={setFormValue((value) => ({
devices: {
[deviceIndex]: {
SSID: { $set: value },
},
},
}))}
{...props}
>
<div className="input-group-append">
<WiFiQRCode
SSID={formData.SSID}
password={formData.password}
/>
</div>
</TextInput>
<PasswordInput
withEye
label={_("Password")}
value={formData.password}
error={formErrors.password}
helpText={HELP_TEXTS.password}
required
onChange={setFormValue((value) => ({
devices: {
[deviceIndex]: { password: { $set: value } },
},
}))}
{...props}
/>
<Switch
label={_("Hide SSID")}
helpText={HELP_TEXTS.hidden}
checked={formData.hidden}
onChange={setFormValue((value) => ({
devices: {
[deviceIndex]: { hidden: { $set: value } },
},
}))}
{...props}
/>
<RadioSet
name={`hwmode-${deviceID}`}
label="GHz"
choices={getHwmodeChoices(formData)}
value={formData.hwmode}
helpText={HELP_TEXTS.hwmode}
inline
onChange={setFormValue((value) => {
// Get the last item in an array of available HT modes
const [best2] = bnds[0].available_htmodes.slice(-1);
const [best5] = bnds[1].available_htmodes.slice(-1);
return {
devices: {
[deviceIndex]: {
hwmode: { $set: value },
channel: { $set: "0" },
htmode: {
$set:
// Set HT mode depending on checked frequency
value === "11a" ? best5 : best2,
},
},
},
};
})}
{...props}
/>
<Select
label={_("802.11n/ac/ax mode")}
choices={getHtmodeChoices(formData)}
value={formData.htmode}
helpText={HELP_TEXTS.htmode}
onChange={setFormValue((value) => ({
devices: {
[deviceIndex]: { htmode: { $set: value } },
},
}))}
{...props}
/>
<Select
label={_("Channel")}
choices={getChannelChoices(formData)}
value={formData.channel}
onChange={setFormValue((value) => ({
devices: {
[deviceIndex]: { channel: { $set: value } },
},
}))}
{...props}
/>
<Select
label={_("Encryption")}
choices={getEncryptionChoices(formData)}
helpText={HELP_TEXTS.wpa3}
value={formData.encryption}
onChange={setFormValue((value) => ({
devices: {
[deviceIndex]: { encryption: { $set: value } },
},
}))}
{...props}
/>
{(formData.encryption === "WPA3" ||
formData.encryption === "WPA2/3") && (
<Switch
label={_("Disable Management Frame Protection")}
helpText={_(
"In case you have trouble connecting to WiFi Access Point, try disabling Management Frame Protection."
)}
checked={formData.ieee80211w_disabled}
onChange={setFormValue((value) => ({
devices: {
[deviceIndex]: {
ieee80211w_disabled: { $set: value },
},
},
}))}
{...props}
/>
)}
{hasGuestNetwork && (
<WifiGuestForm
formData={{
id: deviceIndex,
...formData.guest_wifi,
}}
formErrors={formErrors.guest_wifi || {}}
setFormValue={setFormValue}
{...props}
/>
)}
</>
)}
{divider && <hr />}
</>
);
}
function getChannelChoices(device) {
const channelChoices = {
0: _("auto"),
};
device.available_bands.forEach((availableBand) => {
if (availableBand.hwmode !== device.hwmode) return;
availableBand.available_channels.forEach((availableChannel) => {
channelChoices[availableChannel.number.toString()] = `
${availableChannel.number}
(${availableChannel.frequency} MHz ${
availableChannel.radar ? " ,DFS" : ""
})
`;
});
});
return channelChoices;
}
function getHtmodeChoices(device) {
const htmodeChoices = {};
device.available_bands.forEach((availableBand) => {
if (availableBand.hwmode !== device.hwmode) return;
availableBand.available_htmodes.forEach((availableHtmod) => {
htmodeChoices[availableHtmod] = HTMODES[availableHtmod];
});
});
return htmodeChoices;
}
function getHwmodeChoices(device) {
return device.available_bands.map((availableBand) => ({
label: HWMODES[availableBand.hwmode],
value: availableBand.hwmode,
}));
}
function getEncryptionChoices(device) {
if (device.encryption === "custom") {
ENCRYPTIONMODES.custom = _("Custom");
}
return ENCRYPTIONMODES;
}