ipn/{localapi, ipnlocal}: forget the prior exit node when localAPI is used to zero the ExitNodeID (#11681)

Updates tailscale/corp#18724

When localAPI clients directly set ExitNodeID to "", the expected behaviour is that the prior exit node also gets zero'd - effectively setting the UI state back to 'no exit node was ever selected'

The IntenalExitNodePrior has been changed to be a non-opaque type, as it is read by the UI to render the users last selected exit node, and must be concrete. Future-us can either break this, or deprecate it and replace it with something more interesting.

Signed-off-by: Jonathan Nobels <jonathan@tailscale.com>
This commit is contained in:
Jonathan Nobels
2024-04-16 14:53:56 -04:00
committed by GitHub
parent 0fba9e7570
commit 7e2b4268d6
5 changed files with 72 additions and 27 deletions
+8 -1
View File
@@ -3096,7 +3096,7 @@ func (b *LocalBackend) SetUseExitNodeEnabled(v bool) (ipn.PrefsView, error) {
mp.ExitNodeIDSet = true
mp.ExitNodeID = ""
mp.InternalExitNodePriorSet = true
mp.InternalExitNodePrior = string(p0.ExitNodeID())
mp.InternalExitNodePrior = p0.ExitNodeID()
}
return b.editPrefsLockedOnEntry(mp, unlock)
}
@@ -3105,6 +3105,13 @@ func (b *LocalBackend) EditPrefs(mp *ipn.MaskedPrefs) (ipn.PrefsView, error) {
if mp.SetsInternal() {
return ipn.PrefsView{}, errors.New("can't set Internal fields")
}
// Zeroing the ExitNodeId via localAPI must also zero the prior exit node.
if mp.ExitNodeIDSet && mp.ExitNodeID == "" {
mp.InternalExitNodePrior = ""
mp.InternalExitNodePriorSet = true
}
unlock := b.lockAndGetUnlock()
defer unlock()
return b.editPrefsLockedOnEntry(mp, unlock)