diff --git a/intel/filterlists/module.go b/intel/filterlists/module.go index b1ab9eb0..0bc0e3f1 100644 --- a/intel/filterlists/module.go +++ b/intel/filterlists/module.go @@ -16,12 +16,10 @@ var ( ) const ( - filterlistsDisabled = "filterlists:disabled" - filterlistsUpdateFailed = "filterlists:update-failed" - filterlistsStaleDataSurvived = "filterlists:staledata" - filterlistsStaleDataDescr = "Removing stale filter list records failed. Some connections may be overblocked." - filterlistsUpdateInProgress = "filterlists:update-in-progress" - filterlistsUpdateInProgressDescr = "Performance slightly degraded during list update." + filterlistsDisabled = "filterlists:disabled" + filterlistsUpdateFailed = "filterlists:update-failed" + filterlistsStaleDataSurvived = "filterlists:staledata" + filterlistsUpdateInProgress = "filterlists:update-in-progress" ) // booleans mainly used to decouple the module @@ -91,7 +89,7 @@ func start() error { if err != nil { log.Debugf("intel/filterlists: blocklists disabled, waiting for update (%s)", err) - module.Warning(filterlistsDisabled, "Blocklist features disabled, waiting for update") + warnAboutDisabledFilterLists() } else { log.Debugf("intel/filterlists: using cache database") close(filterListsLoaded) @@ -104,3 +102,11 @@ func stop() error { filterListsLoaded = make(chan struct{}) return nil } + +func warnAboutDisabledFilterLists() { + module.Warning( + filterlistsDisabled, + "Filter Lists Are Initializing", + "The Filter Lists are waiting for update system to check for updates in order to retrieve the filter list data. Until the filter lists are fully initialized, the filter lists feature is disabled.", + ) +} diff --git a/intel/filterlists/updater.go b/intel/filterlists/updater.go index 1cd75d9e..f433c458 100644 --- a/intel/filterlists/updater.go +++ b/intel/filterlists/updater.go @@ -23,17 +23,19 @@ func tryListUpdate(ctx context.Context) error { if err != nil { if !isLoaded() { - module.Error(filterlistsDisabled, err.Error()) + warnAboutDisabledFilterLists() } else { - module.Warning(filterlistsUpdateFailed, err.Error()) + module.Warning( + filterlistsUpdateFailed, + "Filter Lists Update Failed", + fmt.Sprintf("The filter lists system failed to process an update. Depending on the previous state, the filtering capabilities are now either impaired or not given. Refer to the error for more details: %s", err.Error()), + ) } return err } - // if the module is in an error, warning or hint state resolve that right now. - module.Resolve(filterlistsDisabled) - module.Resolve(filterlistsStaleDataSurvived) - module.Resolve(filterlistsUpdateInProgress) + // The list update suceeded, resolve any states. + module.Resolve("") return nil } @@ -44,7 +46,11 @@ func performUpdate(ctx context.Context) error { } defer updateInProgress.UnSet() - module.Hint(filterlistsUpdateInProgress, filterlistsUpdateInProgressDescr) + module.Hint( + filterlistsUpdateInProgress, + "Filter Lists Update In Progress", + "The filter list system is processing updates. While this might slightly degrade performance, the filter list system stays functional during this process.", + ) // First, update the list index. err := updateListIndex() @@ -119,7 +125,11 @@ func performUpdate(ctx context.Context) error { // if we failed to remove all stale cache entries // we abort now WITHOUT updating the database version. This means // we'll try again during the next update. - module.Warning(filterlistsStaleDataSurvived, filterlistsStaleDataDescr) + module.Warning( + filterlistsStaleDataSurvived, + "Filter Lists May Overblock", + fmt.Sprintf("The filter lists system successfully applied an update, but failed to delete old data. This means that the filtering system performs as usual, but may block more entries than it should. Refer to the error for more details: %s", err.Error()), + ) return fmt.Errorf("failed to cleanup stale cache records: %w", err) } } diff --git a/netenv/online-status.go b/netenv/online-status.go index cbc5f26f..b4e81b85 100644 --- a/netenv/online-status.go +++ b/netenv/online-status.go @@ -10,8 +10,6 @@ import ( "sync/atomic" "time" - "github.com/safing/portbase/database" - "github.com/safing/portbase/notifications" "github.com/safing/portbase/log" @@ -257,10 +255,7 @@ func setCaptivePortal(portalURL *url.URL) { func cleanUpPortalNotification() { if captivePortalNotification != nil { - err := captivePortalNotification.Delete() - if err != nil && err != database.ErrNotFound { - log.Warningf("netenv: failed to delete old captive portal notification: %s", err) - } + captivePortalNotification.Delete() captivePortalNotification = nil } } diff --git a/profile/config-update.go b/profile/config-update.go index c403112a..5c78aae7 100644 --- a/profile/config-update.go +++ b/profile/config-update.go @@ -123,7 +123,8 @@ func updateGlobalConfigProfile(ctx context.Context, task *modules.Task) error { // Add module warning to inform user. module.Warning( globalConfigProfileErrorID, - fmt.Sprintf("Failed to process global settings: %s", err), + "Internal Settings Failure", + fmt.Sprintf("The app settings layering system failed to process the global settings. This means that some global settings might not be applied correctly. You can try restarting the Portmaster to resolve this problem. Refer to the error for more details: %s", err), ) } diff --git a/resolver/resolvers.go b/resolver/resolvers.go index 40608faa..ca556d60 100644 --- a/resolver/resolvers.go +++ b/resolver/resolvers.go @@ -227,16 +227,22 @@ func loadResolvers() { ) if len(newResolvers) == 0 { - msg := "no (valid) dns servers found in configuration or system, falling back to defaults" - log.Warningf("resolver: %s", msg) - module.Warning(missingResolversErrorID, msg) + log.Warning("resolver: no (valid) dns server found in config or system, falling back to global defaults") + module.Warning( + missingResolversErrorID, + "Using Factory Default DNS Servers", + "The Portmaster could not find any (valid) DNS servers in the settings or system. In order to prevent being disconnected, the factory defaults are being used instead.", + ) // load defaults directly, overriding config system newResolvers = getConfiguredResolvers(defaultNameServers) if len(newResolvers) == 0 { - msg = "no (valid) dns servers found in configuration or system" - log.Criticalf("resolver: %s", msg) - module.Error(missingResolversErrorID, msg) + log.Critical("resolver: no (valid) dns server found in config, system or global defaults") + module.Error( + missingResolversErrorID, + "No DNS Server Configured", + "The Portmaster could not find any (valid) DNS servers in the settings or system. You will experience severe connectivity problems until resolved.", + ) } } diff --git a/updates/config.go b/updates/config.go index f5f9007d..5c1742fb 100644 --- a/updates/config.go +++ b/updates/config.go @@ -3,12 +3,15 @@ package updates import ( "context" + "github.com/safing/portbase/notifications" + "github.com/safing/portbase/config" "github.com/safing/portbase/log" ) const ( - cfgDevModeKey = "core/devMode" + cfgDevModeKey = "core/devMode" + updatesDisabledNotificationID = "updates:disabled" ) var ( @@ -85,7 +88,6 @@ func initConfig() { func updateRegistryConfig(_ context.Context, _ interface{}) error { changed := false - forceUpdate := false if releaseChannel() != previousReleaseChannel { registry.SetBeta(releaseChannel() == releaseChannelBeta) @@ -102,20 +104,33 @@ func updateRegistryConfig(_ context.Context, _ interface{}) error { if enableUpdates() != updatesCurrentlyEnabled { updatesCurrentlyEnabled = enableUpdates() changed = true - forceUpdate = updatesCurrentlyEnabled } if changed { registry.SelectVersions() module.TriggerEvent(VersionUpdateEvent, nil) - if forceUpdate { - module.Resolve(updateFailed) - _ = TriggerUpdate() - log.Infof("updates: automatic updates enabled again.") - } else if !updatesCurrentlyEnabled { - module.Warning(updateFailed, "Automatic updates are disabled! This also affects security updates and threat intelligence.") - log.Warningf("updates: automatic updates are now disabled.") + if updatesCurrentlyEnabled { + module.Resolve("") + if err := TriggerUpdate(); err != nil { + log.Warningf("updates: failed to trigger update: %s", err) + } + log.Infof("updates: automatic updates are now enabled") + } else { + notifications.NotifyWarn( + updatesDisabledNotificationID, + "Automatic Updates Disabled", + "The automatic update system is disabled through configuration. Please note that this is potentially dangerous, as this also affects security updates as well as the filter lists and threat intelligence feeds.", + notifications.Action{ + ID: "change", + Text: "Change", + Type: notifications.ActionTypeOpenSetting, + Payload: ¬ifications.ActionTypeOpenSettingPayload{ + Key: enableUpdatesKey, + }, + }, + ).AttachToModule(module) + log.Warningf("updates: automatic updates are now disabled") } } diff --git a/updates/main.go b/updates/main.go index 8257bfae..5d73a529 100644 --- a/updates/main.go +++ b/updates/main.go @@ -278,13 +278,30 @@ func checkForUpdates(ctx context.Context) (err error) { } defer log.Debugf("updates: finished checking for updates") - module.Hint(updateInProgress, updateInProcessDescr) + module.Hint( + updateInProgress, + "Checking for Updates", + "The Portmaster is currently checking for and downloading any available updates.", + ) defer func() { if err == nil { module.Resolve(updateInProgress) } else { - module.Warning(updateFailed, "Failed to update: "+err.Error()) + notifications.NotifyWarn( + updateFailed, + "Update Check Failed", + "The Portmaster failed to check for updates. This might be a temporary issue of your device, your network or the update servers. The Portmaster will automatically try again later.", + notifications.Action{ + ID: "retry", + Text: "Try Again", + Type: notifications.ActionTypeWebhook, + Payload: ¬ifications.ActionTypeWebhookPayload{ + URL: apiPathCheckForUpdates, + ResultAction: "display", + }, + }, + ).AttachToModule(module) } }() diff --git a/updates/upgrader.go b/updates/upgrader.go index 95c0a4e2..7414f693 100644 --- a/updates/upgrader.go +++ b/updates/upgrader.go @@ -109,10 +109,10 @@ func upgradeCoreNotify() error { ), Category: "Core", Message: fmt.Sprintf( - `:tada: Update to **Portmaster v%s** is available! -Please restart the Portmaster to apply the update.`, + `A new Portmaster version is available! Restart the Portmaster to upgrade to %s.`, pmCoreUpdate.Version(), ), + ShowOnSystem: true, AvailableActions: []*notifications.Action{ { ID: "restart", @@ -257,13 +257,10 @@ func warnOnIncorrectParentPath() { root := filepath.Dir(registry.StorageDir().Path) if !strings.HasPrefix(absPath, root) { log.Warningf("detected unexpected path %s for portmaster-start", absPath) - - notifications.Notify(¬ifications.Notification{ - EventID: "updates:unsupported-parent", - Type: notifications.Warning, - Title: "Unsupported Launcher", - Category: "Core", - Message: fmt.Sprintf( + notifications.NotifyWarn( + "updates:unsupported-parent", + "Unsupported Launcher", + fmt.Sprintf( "The portmaster has been launched by an unexpected %s binary at %s. Please configure your system to use the binary at %s as this version will be kept up to date automatically.", expectedFileName, absPath,