diff --git a/cmd/syncthing/gui.go b/cmd/syncthing/gui.go index b7129add4..ae6a4b1d9 100644 --- a/cmd/syncthing/gui.go +++ b/cmd/syncthing/gui.go @@ -353,6 +353,7 @@ func restPostConfig(m *model.Model, w http.ResponseWriter, r *http.Request) { if curAcc := cfg.Options().URAccepted; newCfg.Options.URAccepted > curAcc { // UR was enabled newCfg.Options.URAccepted = usageReportVersion + newCfg.Options.URUniqueID = randomString(6) err := sendUsageReport(m) if err != nil { l.Infoln("Usage report:", err) @@ -361,6 +362,7 @@ func restPostConfig(m *model.Model, w http.ResponseWriter, r *http.Request) { } else if newCfg.Options.URAccepted < curAcc { // UR was disabled newCfg.Options.URAccepted = -1 + newCfg.Options.URUniqueID = "" stopUsageReporting() } diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go index d70426c1d..f2ce4f71e 100644 --- a/cmd/syncthing/main.go +++ b/cmd/syncthing/main.go @@ -556,9 +556,15 @@ func syncthingMain() { if opts.URAccepted > 0 && opts.URAccepted < usageReportVersion { l.Infoln("Anonymous usage report has changed; revoking acceptance") opts.URAccepted = 0 + opts.URUniqueID = "" cfg.SetOptions(opts) } if opts.URAccepted >= usageReportVersion { + if opts.URUniqueID == "" { + // Previously the ID was generated from the node ID. We now need + // to generate a new one. + opts.URUniqueID = randomString(6) + } go usageReportingLoop(m) go func() { time.Sleep(10 * time.Minute) diff --git a/cmd/syncthing/usage_report.go b/cmd/syncthing/usage_report.go index 63c302ea4..b5619c593 100644 --- a/cmd/syncthing/usage_report.go +++ b/cmd/syncthing/usage_report.go @@ -23,7 +23,6 @@ import ( "net" "net/http" "runtime" - "strings" "time" "github.com/syncthing/syncthing/internal/model" @@ -38,7 +37,7 @@ var stopUsageReportingCh = make(chan struct{}) func reportData(m *model.Model) map[string]interface{} { res := make(map[string]interface{}) - res["uniqueID"] = strings.ToLower(myID.String()[:6]) + res["uniqueID"] = cfg.Options().URUniqueID res["version"] = Version res["longVersion"] = LongVersion res["platform"] = runtime.GOOS + "-" + runtime.GOARCH diff --git a/internal/config/config.go b/internal/config/config.go index 5fce4b14b..62a171c2e 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -173,6 +173,7 @@ type OptionsConfiguration struct { UPnPLease int `xml:"upnpLeaseMinutes" default:"0"` UPnPRenewal int `xml:"upnpRenewalMinutes" default:"30"` URAccepted int `xml:"urAccepted"` // Accepted usage reporting version; 0 for off (undecided), -1 for off (permanently) + URUniqueID string `xml:"urUniqueID"` // Unique ID for reporting purposes, regenerated when UR is turned on. RestartOnWakeup bool `xml:"restartOnWakeup" default:"true"` AutoUpgradeIntervalH int `xml:"autoUpgradeIntervalH" default:"12"` // 0 for off KeepTemporariesH int `xml:"keepTemporariesH" default:"24"` // 0 for off @@ -278,6 +279,7 @@ func (cfg *Configuration) prepare(myID protocol.DeviceID) { if cfg.Options.Deprecated_URDeclined { cfg.Options.URAccepted = -1 + cfg.Options.URUniqueID = "" } cfg.Options.Deprecated_URDeclined = false cfg.Options.Deprecated_UREnabled = false @@ -381,6 +383,10 @@ func ChangeRequiresRestart(from, to Configuration) bool { } } + // Changing usage reporting to on or off does not require a restart. + to.Options.URAccepted = from.Options.URAccepted + to.Options.URUniqueID = from.Options.URUniqueID + // All of the generic options require restart if !reflect.DeepEqual(from.Options, to.Options) || !reflect.DeepEqual(from.GUI, to.GUI) { return true