From b866d1584c9989f0ad8b4ccc319e189aead66a6e Mon Sep 17 00:00:00 2001 From: Maycon Santos Date: Tue, 20 Oct 2026 14:07:00 +0200 Subject: [PATCH] [client] Drop the non-functional admin URL (#8267) * [client] Drop the non-functional admin URL #4218 deprecated --admin-url, but #3980 merged right after it and restored the flag and its wiring. The value has been stored and echoed back ever since, without anything reading it. Stop sending it from the CLI, ignore it in the daemon and drop it from the profile config, the UI settings service and the debug bundle. The proto fields stay for older clients, and the mobile getters and setters keep their signatures as deprecated stubs. * [client] Drop adminUrl from the Wails API reference --- client/android/preferences.go | 22 +++----- client/android/preferences_test.go | 5 +- client/cmd/root.go | 3 +- client/cmd/up.go | 1 - client/internal/debug/debug.go | 7 --- client/internal/debug/debug_test.go | 10 +--- client/internal/profilemanager/config.go | 50 ++----------------- client/internal/profilemanager/config_test.go | 6 --- .../config_would_change_test.go | 50 ++++++++----------- client/ios/NetBirdSDK/preferences.go | 22 +++----- client/ios/NetBirdSDK/preferences_test.go | 5 +- client/server/server.go | 5 -- client/server/setconfig_test.go | 10 ++-- client/ui/frontend/WAILS-API.md | 6 +-- client/ui/services/settings.go | 4 -- 15 files changed, 60 insertions(+), 146 deletions(-) diff --git a/client/android/preferences.go b/client/android/preferences.go index 3623de23f..af37682c5 100644 --- a/client/android/preferences.go +++ b/client/android/preferences.go @@ -58,23 +58,17 @@ func (p *Preferences) SetManagementURL(url string) { p.configInput.ManagementURL = url } -// GetAdminURL reads URL from config file +// GetAdminURL returns the default admin panel URL. +// +// Deprecated: the admin URL is no longer stored or used by the client. func (p *Preferences) GetAdminURL() (string, error) { - if p.configInput.AdminURL != "" { - return p.configInput.AdminURL, nil - } - - cfg, err := profilemanager.ReadConfigOrDefault(p.configInput.ConfigPath) - if err != nil { - return "", err - } - return cfg.AdminURL.String(), err + return profilemanager.DefaultAdminURL, nil } -// SetAdminURL stores the given URL and waits for commit -func (p *Preferences) SetAdminURL(url string) { - p.configInput.AdminURL = url -} +// SetAdminURL is a no-op kept for API compatibility. +// +// Deprecated: the admin URL is no longer stored or used by the client. +func (p *Preferences) SetAdminURL(_ string) {} // HasPreSharedKey reports whether a pre-shared key is staged, persisted, or // enforced by MDM; the key itself is never handed to the native layer. diff --git a/client/android/preferences_test.go b/client/android/preferences_test.go index d9f5b1918..98670afe0 100644 --- a/client/android/preferences_test.go +++ b/client/android/preferences_test.go @@ -43,13 +43,14 @@ func TestPreferences_ReadUncommitedValues(t *testing.T) { cfgFile := filepath.Join(t.TempDir(), "netbird.json") p := NewPreferences(cfgFile) + // The admin URL is deprecated: setting it is a no-op. p.SetAdminURL(exampleString) resp, err := p.GetAdminURL() if err != nil { t.Fatalf("failed to read admin url: %s", err) } - if resp != exampleString { + if resp != profilemanager.DefaultAdminURL { t.Errorf("unexpected admin url: %s", resp) } @@ -95,7 +96,7 @@ func TestPreferences_Commit(t *testing.T) { t.Fatalf("failed to read admin url: %s", err) } - if resp != exampleURL { + if resp != profilemanager.DefaultAdminURL { t.Errorf("unexpected admin url: %s", resp) } diff --git a/client/cmd/root.go b/client/cmd/root.go index 51179f77c..f976ca895 100644 --- a/client/cmd/root.go +++ b/client/cmd/root.go @@ -157,7 +157,8 @@ func init() { rootCmd.PersistentFlags().StringVar(&daemonAddr, "daemon-addr", defaultDaemonAddr, "Daemon service address to serve CLI requests [unix|tcp|npipe]://[path|host:port|name]") rootCmd.PersistentFlags().StringVarP(&managementURL, "management-url", "m", "", fmt.Sprintf("Management Service URL [http|https]://[host]:[port] (default \"%s\")", profilemanager.DefaultManagementURL)) - rootCmd.PersistentFlags().StringVar(&adminURL, "admin-url", "", fmt.Sprintf("Admin Panel URL [http|https]://[host]:[port] (default \"%s\")", profilemanager.DefaultAdminURL)) + rootCmd.PersistentFlags().StringVar(&adminURL, "admin-url", "", "(DEPRECATED) Admin Panel URL - This flag is no longer functional") + _ = rootCmd.PersistentFlags().MarkDeprecated("admin-url", "the admin-url flag is no longer functional and will be removed in a future version") rootCmd.PersistentFlags().StringVarP(&logLevel, "log-level", "l", "info", "sets NetBird log level") rootCmd.PersistentFlags().StringSliceVar(&logFiles, "log-file", []string{defaultLogFile}, "sets NetBird log paths written to simultaneously. If `console` is specified the log will be output to stdout. If `syslog` is specified the log will be sent to syslog daemon. You can pass the flag multiple times or separate entries by `,` character") rootCmd.PersistentFlags().StringVarP(&setupKey, "setup-key", "k", "", "Setup key obtained from the Management Service Dashboard (used to register peer)") diff --git a/client/cmd/up.go b/client/cmd/up.go index e336ba257..1b5a4a6cd 100644 --- a/client/cmd/up.go +++ b/client/cmd/up.go @@ -493,7 +493,6 @@ func setupSetConfigReq(customDNSAddressConverted []byte, cmd *cobra.Command, pro req.Username = username req.ManagementUrl = managementURL - req.AdminURL = adminURL req.NatExternalIPs = natExternalIPs req.CustomDNSAddress = customDNSAddressConverted req.ExtraIFaceBlacklist = extraIFaceBlackList diff --git a/client/internal/debug/debug.go b/client/internal/debug/debug.go index 95419b0e9..5e8badfc5 100644 --- a/client/internal/debug/debug.go +++ b/client/internal/debug/debug.go @@ -174,7 +174,6 @@ The IP addresses in the interfaces file are anonymized using the same process as Configuration The config.txt file contains anonymized configuration information of the NetBird client. Sensitive information such as private keys and SSH keys are excluded. The following fields are anonymized: - ManagementURL -- AdminURL - NATExternalIPs - CustomDNSAddress @@ -602,9 +601,6 @@ func (g *BundleGenerator) addConfig() error { if g.internalConfig.ManagementURL != nil { configContent.WriteString(fmt.Sprintf("ManagementURL: %s\n", g.anonymizer.AnonymizeURI(g.internalConfig.ManagementURL.String()))) } - if g.internalConfig.AdminURL != nil { - configContent.WriteString(fmt.Sprintf("AdminURL: %s\n", g.anonymizer.AnonymizeURI(g.internalConfig.AdminURL.String()))) - } configContent.WriteString(fmt.Sprintf("NATExternalIPs: %v\n", anonymizeNATExternalIPs(g.internalConfig.NATExternalIPs, g.anonymizer))) if g.internalConfig.CustomDNSAddress != "" { configContent.WriteString(fmt.Sprintf("CustomDNSAddress: %s\n", g.anonymizer.AnonymizeString(g.internalConfig.CustomDNSAddress))) @@ -613,9 +609,6 @@ func (g *BundleGenerator) addConfig() error { if g.internalConfig.ManagementURL != nil { configContent.WriteString(fmt.Sprintf("ManagementURL: %s\n", g.internalConfig.ManagementURL.String())) } - if g.internalConfig.AdminURL != nil { - configContent.WriteString(fmt.Sprintf("AdminURL: %s\n", g.internalConfig.AdminURL.String())) - } configContent.WriteString(fmt.Sprintf("NATExternalIPs: %v\n", g.internalConfig.NATExternalIPs)) if g.internalConfig.CustomDNSAddress != "" { configContent.WriteString(fmt.Sprintf("CustomDNSAddress: %s\n", g.internalConfig.CustomDNSAddress)) diff --git a/client/internal/debug/debug_test.go b/client/internal/debug/debug_test.go index a9cda5a46..93886c5e7 100644 --- a/client/internal/debug/debug_test.go +++ b/client/internal/debug/debug_test.go @@ -856,14 +856,12 @@ func TestAddConfig_AllFieldsCovered(t *testing.T) { } mURL, _ := url.Parse("https://api.example.com:443") - aURL, _ := url.Parse("https://admin.example.com:443") bTrue := true iVal := 42 cfg := &profilemanager.Config{ PrivateKey: "priv", PreSharedKey: "psk", ManagementURL: mURL, - AdminURL: aURL, WgIface: "wt0", WgPort: 51820, NetworkMonitor: &bTrue, @@ -947,7 +945,7 @@ func TestAddConfig_AllFieldsCovered(t *testing.T) { } // renderAddConfigSpecific renders the fields handled by the anonymize/non-anonymize -// branches in addConfig (ManagementURL, AdminURL, NATExternalIPs, CustomDNSAddress). +// branches in addConfig (ManagementURL, NATExternalIPs, CustomDNSAddress). // addCommonConfigFields covers the rest. Keeping this in the test mirrors the // production shape without needing to write an actual zip. func renderAddConfigSpecific(g *BundleGenerator) string { @@ -956,9 +954,6 @@ func renderAddConfigSpecific(g *BundleGenerator) string { if g.internalConfig.ManagementURL != nil { sb.WriteString("ManagementURL: " + g.anonymizer.AnonymizeURI(g.internalConfig.ManagementURL.String()) + "\n") } - if g.internalConfig.AdminURL != nil { - sb.WriteString("AdminURL: " + g.anonymizer.AnonymizeURI(g.internalConfig.AdminURL.String()) + "\n") - } sb.WriteString("NATExternalIPs: x\n") if g.internalConfig.CustomDNSAddress != "" { sb.WriteString("CustomDNSAddress: " + g.anonymizer.AnonymizeString(g.internalConfig.CustomDNSAddress) + "\n") @@ -967,9 +962,6 @@ func renderAddConfigSpecific(g *BundleGenerator) string { if g.internalConfig.ManagementURL != nil { sb.WriteString("ManagementURL: " + g.internalConfig.ManagementURL.String() + "\n") } - if g.internalConfig.AdminURL != nil { - sb.WriteString("AdminURL: " + g.internalConfig.AdminURL.String() + "\n") - } sb.WriteString("NATExternalIPs: x\n") if g.internalConfig.CustomDNSAddress != "" { sb.WriteString("CustomDNSAddress: " + g.internalConfig.CustomDNSAddress + "\n") diff --git a/client/internal/profilemanager/config.go b/client/internal/profilemanager/config.go index 3d378a9e6..6c797a184 100644 --- a/client/internal/profilemanager/config.go +++ b/client/internal/profilemanager/config.go @@ -36,7 +36,8 @@ const ( DefaultManagementURL = "https://api.netbird.io:443" // oldDefaultManagementURL points to the NetBird's old cloud management endpoint oldDefaultManagementURL = "https://api.wiretrustee.com:443" - // DefaultAdminURL points to NetBird's cloud management console + // DefaultAdminURL points to NetBird's cloud management console. It is only + // reported by the deprecated mobile admin URL getters. DefaultAdminURL = "https://app.netbird.io:443" ) @@ -60,7 +61,6 @@ var DefaultInterfaceBlacklist = []string{ // ConfigInput carries configuration changes to the client type ConfigInput struct { ManagementURL string - AdminURL string ConfigPath string StateFilePath string PreSharedKey *string @@ -114,7 +114,6 @@ type Config struct { PrivateKey string PreSharedKey string ManagementURL *url.URL - AdminURL *url.URL WgIface string WgPort int NetworkMonitor *bool @@ -508,29 +507,6 @@ func (config *Config) apply(input ConfigInput) (updated bool, err error) { } } - if config.AdminURL == nil { - log.Infof("using default Admin URL %s", DefaultAdminURL) - config.AdminURL, err = parseURL("Admin URL", DefaultAdminURL) - if err != nil { - return false, err - } - } - // The admin panel is opened, not dialed, so unlike the Management URL its - // path is part of what identifies it: a panel served under /netbird is not - // the one served at the root. - if input.AdminURL != "" { - newURL, err := parseURL("Admin Panel URL", input.AdminURL) - if err != nil { - return updated, err - } - if !SameServiceURLIncludingPath(newURL, config.AdminURL) { - log.Infof("new Admin Panel URL provided, updated to %#v (old value %#v)", - newURL.String(), config.AdminURL.String()) - config.AdminURL = newURL - updated = true - } - } - if input.WireguardPort != nil && *input.WireguardPort != config.WgPort { log.Infof("updating Wireguard port %d (old value %d)", *input.WireguardPort, config.WgPort) @@ -1027,8 +1003,7 @@ func ParseServiceURL(serviceName, serviceURL string) (*url.URL, error) { // matches only another nil one. // // The path plays no part: a management URL is dialed, and only its host and -// port are. util.SameServiceURL is this comparison plus the path, which is -// what SameServiceURLIncludingPath needs and delegates to. +// port are. util.SameServiceURL is this comparison plus the path. func SameServiceURL(a, b *url.URL) bool { if a == nil || b == nil { return a == b @@ -1039,25 +1014,6 @@ func SameServiceURL(a, b *url.URL) bool { util.ServiceURLPort(a) == util.ServiceURLPort(b) } -// SameServiceURLIncludingPath is SameServiceURL plus everything a URL carries -// past its endpoint: path, query, fragment and userinfo. -// -// Use it for a URL that gets opened rather than dialed. The admin panel can -// live under a path, so two URLs with the same endpoint and different paths are -// two different panels — where for a URL the client dials over gRPC only the -// endpoint is ever used. Equivalent spellings still compare equal: a missing -// path and "/" are the same root, and so is a trailing slash on any path. -func SameServiceURLIncludingPath(a, b *url.URL) bool { - if a == nil || b == nil { - return a == b - } - - return util.SameServiceURL(a, b) && - a.RawQuery == b.RawQuery && - a.Fragment == b.Fragment && - a.User.String() == b.User.String() -} - func parseURL(serviceName, serviceURL string) (*url.URL, error) { parsedMgmtURL, err := url.ParseRequestURI(serviceURL) if err != nil { diff --git a/client/internal/profilemanager/config_test.go b/client/internal/profilemanager/config_test.go index a461aa71f..192fc8ec8 100644 --- a/client/internal/profilemanager/config_test.go +++ b/client/internal/profilemanager/config_test.go @@ -36,17 +36,14 @@ func TestGetConfig(t *testing.T) { } assert.Equal(t, config.ManagementURL.String(), DefaultManagementURL) - assert.Equal(t, config.AdminURL.String(), DefaultAdminURL) managementURL := "https://test.management.url:33071" - adminURL := "https://app.admin.url:443" path := filepath.Join(t.TempDir(), "config.json") preSharedKey := "preSharedKey" // case 2: new config has to be generated config, err = UpdateOrCreateConfig(ConfigInput{ ManagementURL: managementURL, - AdminURL: adminURL, ConfigPath: path, PreSharedKey: &preSharedKey, }) @@ -64,7 +61,6 @@ func TestGetConfig(t *testing.T) { // case 3: existing config -> fetch it config, err = UpdateOrCreateConfig(ConfigInput{ ManagementURL: managementURL, - AdminURL: adminURL, ConfigPath: path, PreSharedKey: &preSharedKey, }) @@ -79,7 +75,6 @@ func TestGetConfig(t *testing.T) { newManagementURL := "https://test.newManagement.url:33071" config, err = UpdateOrCreateConfig(ConfigInput{ ManagementURL: newManagementURL, - AdminURL: adminURL, ConfigPath: path, PreSharedKey: &preSharedKey, }) @@ -164,7 +159,6 @@ func TestNewProfileDefaults(t *testing.T) { require.NoError(t, err, "should create new config") assert.Equal(t, DefaultManagementURL, config.ManagementURL.String(), "ManagementURL should have default") - assert.Equal(t, DefaultAdminURL, config.AdminURL.String(), "AdminURL should have default") assert.NotEmpty(t, config.PrivateKey, "PrivateKey should be generated") assert.NotEmpty(t, config.SSHKey, "SSHKey should be generated") assert.Equal(t, iface.WgInterfaceDefault, config.WgIface, "WgIface should have default") diff --git a/client/internal/profilemanager/config_would_change_test.go b/client/internal/profilemanager/config_would_change_test.go index 6b140030f..3efa2fb05 100644 --- a/client/internal/profilemanager/config_would_change_test.go +++ b/client/internal/profilemanager/config_would_change_test.go @@ -334,40 +334,34 @@ func TestCreateInMemoryConfigCarriesAnIdentity(t *testing.T) { require.NotEmpty(t, cfg.SSHKey) } -// The admin panel is opened, not dialed, so its path identifies it. Comparing -// it as a bare endpoint left a custom panel URL unable to change. -func TestAdminURLPathIsPartOfTheIdentity(t *testing.T) { - path := filepath.Join(t.TempDir(), "panel.json") - _, err := UpdateOrCreateConfig(ConfigInput{ - ConfigPath: path, - AdminURL: "https://app.example.com/netbird", - }) +// Profiles written before the admin URL was dropped still carry an AdminURL key. +// It must not break loading, and the next write must drop it. +func TestLegacyAdminURLIsIgnored(t *testing.T) { + path := filepath.Join(t.TempDir(), "legacy.json") + _, err := UpdateOrCreateConfig(ConfigInput{ConfigPath: path}) require.NoError(t, err) - cfg, err := GetExistingConfig(path) + raw, err := os.ReadFile(path) require.NoError(t, err) - require.Equal(t, "https://app.example.com:443/netbird", cfg.AdminURL.String()) - - // Equivalent spellings of the same panel are still not a change. - for _, same := range []string{ - "https://app.example.com/netbird", - "https://app.example.com:443/netbird", - "https://app.example.com/netbird/", - "https://APP.example.com/netbird", - } { - changed, err := cfg.WouldChange(ConfigInput{AdminURL: same}) - require.NoError(t, err) - require.False(t, changed, "%q is the stored panel written differently", same) - } - - // A different path is a different panel, and it must be persisted. - changed, err := cfg.WouldChange(ConfigInput{AdminURL: "https://app.example.com/other"}) + var stored map[string]json.RawMessage + require.NoError(t, json.Unmarshal(raw, &stored)) + stored["AdminURL"] = json.RawMessage(`{"Scheme":"https","Host":"panel.example.com:443","Path":"/netbird"}`) + rewritten, err := json.Marshal(stored) require.NoError(t, err) - require.True(t, changed, "a different panel path is a change") + require.NoError(t, os.WriteFile(path, rewritten, 0600)) - updated, err := UpdateConfig(ConfigInput{ConfigPath: path, AdminURL: "https://app.example.com/other"}) + _, err = GetExistingConfig(path) + require.NoError(t, err, "a legacy AdminURL key must not prevent loading the profile") + + port := 51999 + _, err = UpdateConfig(ConfigInput{ConfigPath: path, WireguardPort: &port}) require.NoError(t, err) - require.Equal(t, "https://app.example.com:443/other", updated.AdminURL.String(), "the new panel path was not persisted") + + raw, err = os.ReadFile(path) + require.NoError(t, err) + stored = nil + require.NoError(t, json.Unmarshal(raw, &stored)) + require.NotContains(t, stored, "AdminURL", "the legacy AdminURL key should be dropped on write") } // unsetOnDisk rewrites the stored config so the named fields carry a JSON null, diff --git a/client/ios/NetBirdSDK/preferences.go b/client/ios/NetBirdSDK/preferences.go index 642f9e160..4209a5654 100644 --- a/client/ios/NetBirdSDK/preferences.go +++ b/client/ios/NetBirdSDK/preferences.go @@ -61,23 +61,17 @@ func (p *Preferences) SetManagementURL(url string) { p.configInput.ManagementURL = url } -// GetAdminURL read url from config file +// GetAdminURL returns the default admin panel URL. +// +// Deprecated: the admin URL is no longer stored or used by the client. func (p *Preferences) GetAdminURL() (string, error) { - if p.configInput.AdminURL != "" { - return p.configInput.AdminURL, nil - } - - cfg, err := profilemanager.ReadConfigOrDefault(p.configInput.ConfigPath) - if err != nil { - return "", err - } - return cfg.AdminURL.String(), err + return profilemanager.DefaultAdminURL, nil } -// SetAdminURL store the given url and wait for commit -func (p *Preferences) SetAdminURL(url string) { - p.configInput.AdminURL = url -} +// SetAdminURL is a no-op kept for API compatibility. +// +// Deprecated: the admin URL is no longer stored or used by the client. +func (p *Preferences) SetAdminURL(_ string) {} // HasPreSharedKey reports whether a pre-shared key is staged, persisted, or // enforced by MDM; the key itself is never handed to the native layer. diff --git a/client/ios/NetBirdSDK/preferences_test.go b/client/ios/NetBirdSDK/preferences_test.go index 2382e123c..2deb996b2 100644 --- a/client/ios/NetBirdSDK/preferences_test.go +++ b/client/ios/NetBirdSDK/preferences_test.go @@ -47,13 +47,14 @@ func TestPreferences_ReadUncommitedValues(t *testing.T) { stateFile := filepath.Join(t.TempDir(), "state.json") p := NewPreferences(cfgFile, stateFile) + // The admin URL is deprecated: setting it is a no-op. p.SetAdminURL(exampleString) resp, err := p.GetAdminURL() if err != nil { t.Fatalf("failed to read admin url: %s", err) } - if resp != exampleString { + if resp != profilemanager.DefaultAdminURL { t.Errorf("unexpected admin url: %s", resp) } @@ -100,7 +101,7 @@ func TestPreferences_Commit(t *testing.T) { t.Fatalf("failed to read admin url: %s", err) } - if resp != exampleURL { + if resp != profilemanager.DefaultAdminURL { t.Errorf("unexpected admin url: %s", resp) } diff --git a/client/server/server.go b/client/server/server.go index 4ce2a5c82..94469c683 100644 --- a/client/server/server.go +++ b/client/server/server.go @@ -593,9 +593,6 @@ func (s *Server) setConfigInputFromRequest(msg *proto.SetConfigRequest) (profile if msg.ManagementUrl != "" { config.ManagementURL = msg.ManagementUrl } - if msg.AdminURL != "" { - config.AdminURL = msg.AdminURL - } if msg.InterfaceName != nil { config.InterfaceName = msg.InterfaceName } @@ -2409,7 +2406,6 @@ func (s *Server) GetConfig(ctx context.Context, req *proto.GetConfigRequest) (*p // overlay (Loader lives outside profilemanager). cfg.ApplyMDMPolicy(s.mdmLoader.Load()) managementURL := cfg.ManagementURL - adminURL := cfg.AdminURL var preSharedKey = cfg.PreSharedKey if preSharedKey != "" { @@ -2465,7 +2461,6 @@ func (s *Server) GetConfig(ctx context.Context, req *proto.GetConfigRequest) (*p return &proto.GetConfigResponse{ ManagementUrl: managementURL.String(), PreSharedKey: preSharedKey, - AdminURL: adminURL.String(), InterfaceName: cfg.WgIface, WireguardPort: int64(cfg.WgPort), Mtu: int64(cfg.MTU), diff --git a/client/server/setconfig_test.go b/client/server/setconfig_test.go index d7f7b2bd5..454bfe423 100644 --- a/client/server/setconfig_test.go +++ b/client/server/setconfig_test.go @@ -1,6 +1,7 @@ package server import ( + "os" "os/user" "path/filepath" "reflect" @@ -129,7 +130,10 @@ func TestSetConfig_AllFieldsSaved(t *testing.T) { require.NoError(t, err) require.Equal(t, "https://new-api.netbird.io:443", cfg.ManagementURL.String()) - require.Equal(t, "https://new-admin.netbird.io:443", cfg.AdminURL.String()) + // Older clients still send the deprecated admin URL; it must be ignored. + raw, err := os.ReadFile(cfgPath) + require.NoError(t, err) + require.NotContains(t, string(raw), "new-admin.netbird.io", "deprecated AdminURL must not be persisted") require.Equal(t, rosenpassEnabled, cfg.RosenpassEnabled) require.Equal(t, rosenpassPermissive, cfg.RosenpassPermissive) require.NotNil(t, cfg.ServerSSHAllowed) @@ -182,11 +186,11 @@ func verifyAllFieldsCovered(t *testing.T, req *proto.SetConfigRequest) { "CleanNATExternalIPs": true, // control flag for clearing "CleanDNSLabels": true, // control flag for clearing "LazyConnectionEnabled": true, // deprecated: proto field retained for compat, no longer applied + "AdminURL": true, // deprecated: proto field retained for compat, no longer applied } expectedFields := map[string]bool{ "ManagementUrl": true, - "AdminURL": true, "RosenpassEnabled": true, "RosenpassPermissive": true, "ServerSSHAllowed": true, @@ -249,7 +253,6 @@ func TestCLIFlags_MappedToSetConfig(t *testing.T) { // This map must be updated when adding new config-related CLI flags. flagToField := map[string]string{ "management-url": "ManagementUrl", - "admin-url": "AdminURL", "enable-rosenpass": "RosenpassEnabled", "rosenpass-permissive": "RosenpassPermissive", "allow-server-ssh": "ServerSSHAllowed", @@ -286,6 +289,7 @@ func TestCLIFlags_MappedToSetConfig(t *testing.T) { fieldsWithoutCLIFlags := map[string]bool{ "DisableNotifications": true, // Only settable via UI "LazyConnectionEnabled": true, // deprecated: no longer settable (managed by server + NB_LAZY_CONN) + "AdminURL": true, // deprecated: the admin-url flag is no longer functional } // Get all SetConfigRequest fields to verify our map is complete. diff --git a/client/ui/frontend/WAILS-API.md b/client/ui/frontend/WAILS-API.md index 6cc1dd79c..ad0866b65 100644 --- a/client/ui/frontend/WAILS-API.md +++ b/client/ui/frontend/WAILS-API.md @@ -110,7 +110,7 @@ Settings.SetConfig(p: SetConfigParams): Promise // partial update Settings.GetFeatures(): Promise // operator-disabled UI sections ``` -`SetConfig` is a partial update: only fields you set are pushed to the daemon. `profileName` + `username` are always required; the typed fields in `SetConfigParams` are optional (`field?: T | null`). `managementUrl` and `adminUrl` are always-string for historical reasons. +`SetConfig` is a partial update: only fields you set are pushed to the daemon. `profileName` + `username` are always required; the typed fields in `SetConfigParams` are optional (`field?: T | null`). `managementUrl` is always-string for historical reasons. **PSK mask quirk:** `GetConfig` returns existing pre-shared keys as `"**********"`. If you send the mask back, `wgtypes.ParseKey` fails on the next connect. `SettingsContext.save` drops the field when it equals `"**********"`. See `modules/settings/SettingsContext.tsx`. @@ -242,7 +242,7 @@ The tray also reads a tray-only synthetic `"Error"` for icon purposes; the front `Config` (read-only mirror, all required): ```ts -{ managementUrl, adminUrl, configFile, logFile, preSharedKey, interfaceName: string; +{ managementUrl, configFile, logFile, preSharedKey, interfaceName: string; wireguardPort, mtu, sshJwtCacheTtl: number; disableAutoConnect, serverSshAllowed, rosenpassEnabled, rosenpassPermissive, @@ -254,7 +254,7 @@ The tray also reads a tray-only synthetic `"Error"` for icon purposes; the front disableSshAuth: boolean; } ``` -`SetConfigParams` has all `Config` fields as `field?: T | null` (partial update), plus the write-only `disableFirewall?: boolean | null`, plus `profileName` / `username` / `managementUrl` / `adminUrl` as required strings. +`SetConfigParams` has all `Config` fields as `field?: T | null` (partial update), plus the write-only `disableFirewall?: boolean | null`, plus `profileName` / `username` / `managementUrl` as required strings. `Features`: `{ disableProfiles, disableUpdateSettings, disableNetworks: boolean }`. diff --git a/client/ui/services/settings.go b/client/ui/services/settings.go index 7c20184bd..c3628fbdf 100644 --- a/client/ui/services/settings.go +++ b/client/ui/services/settings.go @@ -51,7 +51,6 @@ type ConfigParams struct { type Config struct { ManagementURL string `json:"managementUrl"` - AdminURL string `json:"adminUrl"` ConfigFile string `json:"configFile"` LogFile string `json:"logFile"` PreSharedKeySet bool `json:"preSharedKeySet"` @@ -84,7 +83,6 @@ type SetConfigParams struct { ProfileName string `json:"profileName"` Username string `json:"username"` ManagementURL string `json:"managementUrl"` - AdminURL string `json:"adminUrl"` InterfaceName *string `json:"interfaceName,omitempty"` WireguardPort *int64 `json:"wireguardPort,omitempty"` MTU *int64 `json:"mtu,omitempty"` @@ -144,7 +142,6 @@ func (s *Settings) GetConfig(ctx context.Context, p ConfigParams) (Config, error } return Config{ ManagementURL: resp.GetManagementUrl(), - AdminURL: resp.GetAdminURL(), ConfigFile: resp.GetConfigFile(), LogFile: resp.GetLogFile(), PreSharedKeySet: resp.GetPreSharedKey() != "", @@ -181,7 +178,6 @@ func (s *Settings) SetConfig(ctx context.Context, p SetConfigParams) (SaveOutcom ProfileName: p.ProfileName, Username: p.Username, ManagementUrl: p.ManagementURL, - AdminURL: p.AdminURL, InterfaceName: p.InterfaceName, WireguardPort: p.WireguardPort, Mtu: p.MTU,