From 1100cea6a42bfed6035ed9cccd19d8493282c22e Mon Sep 17 00:00:00 2001 From: riccardom Date: Wed, 3 Jun 2026 22:59:01 +0200 Subject: [PATCH] Add events to resync UI to actual config This also provide fixup for UI no aligning to changed config when coming from cli up with config flags. --- client/server/mdm.go | 45 ++++++++++++++++++++++++++++++++--------- client/server/server.go | 2 ++ client/ui/client_ui.go | 11 ++++++++++ 3 files changed, 49 insertions(+), 9 deletions(-) diff --git a/client/server/mdm.go b/client/server/mdm.go index 0b3633c83..179bc743f 100644 --- a/client/server/mdm.go +++ b/client/server/mdm.go @@ -60,20 +60,46 @@ func (s *Server) onMDMPolicyChange(_, curr *mdm.Policy) { return } - // Notify any active gRPC SubscribeEvents subscriber (typically the UI - // tray) that the daemon's effective configuration has changed. - // Reusing the SYSTEM category keeps the proto enum stable for - // backwards-compat; metadata["source"]="mdm" + ["type"]="policy_changed" - // disambiguates the trigger for handler routing on the client side. - managed := curr.ManagedKeys() + // publishConfigChangedEvent has already fired inside + // restartEngineForMDM with source="mdm". Here we additionally emit an + // MDM-specific user-visible toast so the operator knows their IT + // policy was applied (UserMessage != "" triggers the GUI notifier). + _ = curr s.statusRecorder.PublishEvent( proto.SystemEvent_INFO, proto.SystemEvent_SYSTEM, - fmt.Sprintf("MDM policy applied; engine restarted with %d managed key(s)", len(managed)), + "MDM policy applied", "NetBird configuration was updated by your IT policy.", + map[string]string{"source": "mdm", "type": "policy_applied"}, + ) +} + +// publishConfigChangedEvent broadcasts a SystemEvent informing any active +// SubscribeEvents subscriber (typically the GUI tray) that the daemon's +// effective Config has been replaced and any cached client-side view +// should be refreshed. Callers pass a stable `source` label so the GUI +// can distinguish a startup spawn from a user-triggered Up or an +// MDM-driven restart. Reusing the SYSTEM category keeps the proto enum +// stable; metadata.type="config_changed" routes to the GUI's refresh +// handler. UserMessage is left empty so the system tray does not toast +// for every internal restart; the MDM path emits a separate +// "policy_applied" event (with UserMessage) for that purpose. +func (s *Server) publishConfigChangedEvent(source string) { + if s.statusRecorder == nil { + return + } + var managed []string + if s.config != nil { + managed = s.config.Policy().ManagedKeys() + } + s.statusRecorder.PublishEvent( + proto.SystemEvent_INFO, + proto.SystemEvent_SYSTEM, + fmt.Sprintf("daemon config changed (source=%s)", source), + "", map[string]string{ - "source": "mdm", - "type": "policy_changed", + "source": source, + "type": "config_changed", "managed_fields": strings.Join(managed, ","), }, ) @@ -122,6 +148,7 @@ func (s *Server) restartEngineForMDM() error { s.clientGiveUpChan = make(chan struct{}) log.Info("MDM restart: spawning connectWithRetryRuns with re-resolved config") go s.connectWithRetryRuns(ctx, config, s.statusRecorder, s.clientRunningChan, s.clientGiveUpChan) + s.publishConfigChangedEvent("mdm") return nil } diff --git a/client/server/server.go b/client/server/server.go index 19fca03c3..fb67f8c85 100644 --- a/client/server/server.go +++ b/client/server/server.go @@ -230,6 +230,7 @@ func (s *Server) Start() error { s.clientRunningChan = make(chan struct{}) s.clientGiveUpChan = make(chan struct{}) go s.connectWithRetryRuns(ctx, config, s.statusRecorder, s.clientRunningChan, s.clientGiveUpChan) + s.publishConfigChangedEvent("startup") return nil } @@ -768,6 +769,7 @@ func (s *Server) Up(callerCtx context.Context, msg *proto.UpRequest) (*proto.UpR s.clientGiveUpChan = make(chan struct{}) go s.connectWithRetryRuns(ctx, s.config, s.statusRecorder, s.clientRunningChan, s.clientGiveUpChan) + s.publishConfigChangedEvent("up_rpc") s.mutex.Unlock() return s.waitForUp(callerCtx) diff --git a/client/ui/client_ui.go b/client/ui/client_ui.go index c4b644354..dd31559fb 100644 --- a/client/ui/client_ui.go +++ b/client/ui/client_ui.go @@ -1150,6 +1150,17 @@ func (s *serviceClient) onTrayReady() { s.onUpdateAvailable(newVersion, enforced) } }) + s.eventManager.AddHandler(func(event *proto.SystemEvent) { + // Daemon emits a config_changed event after every engine spawn + // (Server.Start, Server.Up, MDM ticker restart). Re-sync the + // tray submenu checkboxes from the fresh daemon-side config so + // the user does not have to restart the tray to see CLI- or + // MDM-driven changes. + if event.Category == proto.SystemEvent_SYSTEM && event.Metadata["type"] == "config_changed" { + log.Infof("config_changed event received (source=%s); refreshing settings", event.Metadata["source"]) + s.loadSettings() + } + }) go s.eventManager.Start(s.ctx) go s.eventHandler.listen(s.ctx)