mirror of
https://github.com/netbirdio/netbird.git
synced 2026-09-01 12:31:42 +02:00
Merge main into ui-refactor; port MDM support to the Wails UI
Integrates main's MDM configuration-profile feature and adapts it to the Wails UI (this branch had already replaced the Fyne UI). Conflict resolution: - go.mod/go.sum: take main's deps; howett.net/plist pinned to v1.0.2-... (tidy) - client/proto/daemon.pb.go: regenerated from the merged daemon.proto - client/internal/peer/status.go: union of ipToKey (main) + sessionExpiresAt (HEAD) - client/server/server.go: main's intent/liveness model (connectionGoroutineRunning, clientRunning no longer cleared by the goroutine) + empty-PSK guard - client/ui/client_ui.go, client/ui/profile.go: removed (dead Fyne UI) MDM port (backend + tray): - services/settings.go: expose MDMManagedFields plus a managedFields map keyed by Config field names so the settings form can gate a control without translating mdm.Key* names - tray: gate Profiles / Exit Node menus on DisableProfiles / DisableNetworks via GetFeatures, refreshed on the config_changed system event (replaces the legacy 2s poll); localized MDM policy-applied toast in all shipped locales - client/proto/metadata.go: shared constants for the config_changed / policy_applied event markers PreSharedKey: GetConfig now returns preSharedKeySet (bool) instead of the masked value; the settings form provides its own placeholder and sends a new key only when the user types one.
This commit is contained in:
@@ -26,7 +26,10 @@ type SettingsContextValue = {
|
||||
guiVersion: string;
|
||||
setField: <K extends keyof Config>(k: K, v: Config[K]) => void;
|
||||
saveField: <K extends keyof Config>(k: K, v: Config[K]) => Promise<void>;
|
||||
saveFields: (partial: Partial<Config>) => Promise<void>;
|
||||
// opts.preSharedKey carries a new PSK to write. Config no longer exposes the
|
||||
// PSK value (only preSharedKeySet), so it rides alongside the Config fields
|
||||
// here and is sent only when non-empty.
|
||||
saveFields: (partial: Partial<Config>, opts?: { preSharedKey?: string }) => Promise<void>;
|
||||
saveNow: () => Promise<void>;
|
||||
};
|
||||
|
||||
@@ -104,13 +107,14 @@ const useSettingsState = () => {
|
||||
);
|
||||
|
||||
const save = useCallback(
|
||||
async (profileName: string, next: Config) => {
|
||||
// Sending the "**********" PSK mask back corrupts the stored PSK (wgtypes.ParseKey fails next connect).
|
||||
const { preSharedKey, ...rest } = next;
|
||||
async (profileName: string, next: Config, preSharedKey?: string) => {
|
||||
try {
|
||||
await SettingsSvc.SetConfig({
|
||||
...rest,
|
||||
...(preSharedKey === "**********" ? {} : { preSharedKey }),
|
||||
...next,
|
||||
// The daemon never returns the PSK value (only preSharedKeySet),
|
||||
// so send one only when the user actually typed a new key; an
|
||||
// empty field means "leave unchanged", never "clear".
|
||||
...(preSharedKey ? { preSharedKey } : {}),
|
||||
profileName,
|
||||
username,
|
||||
});
|
||||
@@ -163,7 +167,7 @@ const useSettingsState = () => {
|
||||
);
|
||||
|
||||
const saveFields = useCallback(
|
||||
async (partial: Partial<Config>) => {
|
||||
async (partial: Partial<Config>, opts?: { preSharedKey?: string }) => {
|
||||
if (!loaded) return;
|
||||
if (saveTimer.current) {
|
||||
clearTimeout(saveTimer.current);
|
||||
@@ -171,7 +175,7 @@ const useSettingsState = () => {
|
||||
}
|
||||
const next = { ...loaded.data, ...partial };
|
||||
setLoaded({ profileName: loaded.profileName, data: next });
|
||||
await save(loaded.profileName, next);
|
||||
await save(loaded.profileName, next, opts?.preSharedKey);
|
||||
},
|
||||
[loaded, save],
|
||||
);
|
||||
|
||||
@@ -20,8 +20,6 @@ const PORT_MAX = 65535;
|
||||
// Mirrors client/iface/iface.go MinMTU / MaxMTU.
|
||||
const MTU_MIN = 576;
|
||||
const MTU_MAX = 8192;
|
||||
// GetConfig returns existing PSKs as this mask; revealing it would only show the asterisks.
|
||||
const PSK_MASK = "**********";
|
||||
|
||||
export function SettingsAdvanced() {
|
||||
const { t } = useTranslation();
|
||||
@@ -31,8 +29,11 @@ export function SettingsAdvanced() {
|
||||
interfaceName: config.interfaceName,
|
||||
wireguardPort: config.wireguardPort,
|
||||
mtu: config.mtu,
|
||||
preSharedKey: config.preSharedKey,
|
||||
});
|
||||
// PSK is write-only from the UI: the daemon returns only preSharedKeySet,
|
||||
// never the value. Empty means "leave unchanged"; a typed value is sent on
|
||||
// save. Reset on every config reload (e.g. after a successful save).
|
||||
const [psk, setPsk] = useState("");
|
||||
const [saving, setSaving] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -40,9 +41,9 @@ export function SettingsAdvanced() {
|
||||
interfaceName: config.interfaceName,
|
||||
wireguardPort: config.wireguardPort,
|
||||
mtu: config.mtu,
|
||||
preSharedKey: config.preSharedKey,
|
||||
});
|
||||
}, [config.interfaceName, config.wireguardPort, config.mtu, config.preSharedKey]);
|
||||
setPsk("");
|
||||
}, [config.interfaceName, config.wireguardPort, config.mtu, config.preSharedKeySet]);
|
||||
|
||||
const errors = useMemo(() => {
|
||||
const out: { interfaceName?: string; wireguardPort?: string; mtu?: string } = {};
|
||||
@@ -70,13 +71,13 @@ export function SettingsAdvanced() {
|
||||
values.interfaceName !== config.interfaceName ||
|
||||
values.wireguardPort !== config.wireguardPort ||
|
||||
values.mtu !== config.mtu ||
|
||||
values.preSharedKey !== config.preSharedKey;
|
||||
psk !== "";
|
||||
|
||||
const handleSave = async () => {
|
||||
if (!hasChanges || saving || hasErrors) return;
|
||||
setSaving(true);
|
||||
try {
|
||||
await saveFields(values);
|
||||
await saveFields(values, psk ? { preSharedKey: psk } : undefined);
|
||||
} finally {
|
||||
setSaving(false);
|
||||
}
|
||||
@@ -127,10 +128,14 @@ export function SettingsAdvanced() {
|
||||
<HelpText>{t("settings.advanced.psk.help")}</HelpText>
|
||||
<Input
|
||||
type={"password"}
|
||||
showPasswordToggle={values.preSharedKey !== PSK_MASK}
|
||||
placeholder={"kQv0qF3oQpJYdgD5mC9hL7sB2xZ8nT4eU6wY1aR3jK0="}
|
||||
value={values.preSharedKey}
|
||||
onChange={(e) => setValues((v) => ({ ...v, preSharedKey: e.target.value }))}
|
||||
showPasswordToggle={psk !== ""}
|
||||
placeholder={
|
||||
config.preSharedKeySet
|
||||
? t("settings.advanced.psk.configured")
|
||||
: "kQv0qF3oQpJYdgD5mC9hL7sB2xZ8nT4eU6wY1aR3jK0="
|
||||
}
|
||||
value={psk}
|
||||
onChange={(e) => setPsk(e.target.value)}
|
||||
/>
|
||||
</div>
|
||||
</SectionGroup>
|
||||
|
||||
Reference in New Issue
Block a user