diff --git a/server/i18n/en.json b/server/i18n/en.json index 40f626291f..490d218c87 100644 --- a/server/i18n/en.json +++ b/server/i18n/en.json @@ -8811,6 +8811,10 @@ "id": "model.config.is_valid.listen_address.app_error", "translation": "Invalid listen address for service settings Must be set." }, + { + "id": "model.config.is_valid.local_mode_socket.app_error", + "translation": "Unable to locate local socket file directory." + }, { "id": "model.config.is_valid.localization.available_locales.app_error", "translation": "Available Languages must contain Default Client Language." diff --git a/server/model/config.go b/server/model/config.go index 6fe686d5e5..39ab83f4af 100644 --- a/server/model/config.go +++ b/server/model/config.go @@ -12,6 +12,7 @@ import ( "net/http" "net/url" "os" + "path/filepath" "reflect" "regexp" "strconv" @@ -3749,6 +3750,16 @@ func (s *ServiceSettings) isValid() *AppError { return NewAppError("Config.IsValid", "model.config.is_valid.collapsed_threads.app_error", nil, "", http.StatusBadRequest) } + // we check if file has a valid parent, the server will try to create the socket + // file if it doesn't exist, but we need to be sure if the directory exist or not + if *s.EnableLocalMode { + parent := filepath.Dir(*s.LocalModeSocketLocation) + _, err := os.Stat(parent) + if err != nil { + return NewAppError("Config.IsValid", "model.config.is_valid.local_mode_socket.app_error", nil, err.Error(), http.StatusBadRequest) + } + } + return nil } diff --git a/server/model/config_test.go b/server/model/config_test.go index f7972d3b67..7477fbb5ef 100644 --- a/server/model/config_test.go +++ b/server/model/config_test.go @@ -1409,40 +1409,63 @@ func TestConfigExportSettingsIsValid(t *testing.T) { } func TestConfigServiceSettingsIsValid(t *testing.T) { - cfg := Config{} - cfg.SetDefaults() + t.Run("local socket file should exist if local mode enabled", func(t *testing.T) { + cfg := Config{} + cfg.SetDefaults() - appErr := cfg.ServiceSettings.isValid() - require.Nil(t, appErr) + appErr := cfg.ServiceSettings.isValid() + require.Nil(t, appErr) - *cfg.ServiceSettings.CollapsedThreads = CollapsedThreadsDisabled - appErr = cfg.ServiceSettings.isValid() - require.Nil(t, appErr) + *cfg.ServiceSettings.EnableLocalMode = false + // we don't need to check as local mode is not enabled + *cfg.ServiceSettings.LocalModeSocketLocation = "an_invalid_path.socket" + appErr = cfg.ServiceSettings.isValid() + require.Nil(t, appErr) - *cfg.ServiceSettings.ThreadAutoFollow = false - appErr = cfg.ServiceSettings.isValid() - require.Nil(t, appErr) + // now we can check if the file exist or not + *cfg.ServiceSettings.EnableLocalMode = true + *cfg.ServiceSettings.LocalModeSocketLocation = "/invalid_directory/mattermost_local.socket" + appErr = cfg.ServiceSettings.isValid() + require.NotNil(t, appErr) + require.Equal(t, "model.config.is_valid.local_mode_socket.app_error", appErr.Id) + }) - *cfg.ServiceSettings.CollapsedThreads = CollapsedThreadsDefaultOff - appErr = cfg.ServiceSettings.isValid() - require.NotNil(t, appErr) - require.Equal(t, "model.config.is_valid.collapsed_threads.autofollow.app_error", appErr.Id) + t.Run("CRT settings should have consistent values", func(t *testing.T) { + cfg := Config{} + cfg.SetDefaults() - *cfg.ServiceSettings.CollapsedThreads = CollapsedThreadsDefaultOn - appErr = cfg.ServiceSettings.isValid() - require.NotNil(t, appErr) - require.Equal(t, "model.config.is_valid.collapsed_threads.autofollow.app_error", appErr.Id) + appErr := cfg.ServiceSettings.isValid() + require.Nil(t, appErr) - *cfg.ServiceSettings.CollapsedThreads = CollapsedThreadsAlwaysOn - appErr = cfg.ServiceSettings.isValid() - require.NotNil(t, appErr) - require.Equal(t, "model.config.is_valid.collapsed_threads.autofollow.app_error", appErr.Id) + *cfg.ServiceSettings.CollapsedThreads = CollapsedThreadsDisabled + appErr = cfg.ServiceSettings.isValid() + require.Nil(t, appErr) - *cfg.ServiceSettings.ThreadAutoFollow = true - *cfg.ServiceSettings.CollapsedThreads = "test_status" - appErr = cfg.ServiceSettings.isValid() - require.NotNil(t, appErr) - require.Equal(t, "model.config.is_valid.collapsed_threads.app_error", appErr.Id) + *cfg.ServiceSettings.ThreadAutoFollow = false + appErr = cfg.ServiceSettings.isValid() + require.Nil(t, appErr) + + *cfg.ServiceSettings.CollapsedThreads = CollapsedThreadsDefaultOff + appErr = cfg.ServiceSettings.isValid() + require.NotNil(t, appErr) + require.Equal(t, "model.config.is_valid.collapsed_threads.autofollow.app_error", appErr.Id) + + *cfg.ServiceSettings.CollapsedThreads = CollapsedThreadsDefaultOn + appErr = cfg.ServiceSettings.isValid() + require.NotNil(t, appErr) + require.Equal(t, "model.config.is_valid.collapsed_threads.autofollow.app_error", appErr.Id) + + *cfg.ServiceSettings.CollapsedThreads = CollapsedThreadsAlwaysOn + appErr = cfg.ServiceSettings.isValid() + require.NotNil(t, appErr) + require.Equal(t, "model.config.is_valid.collapsed_threads.autofollow.app_error", appErr.Id) + + *cfg.ServiceSettings.ThreadAutoFollow = true + *cfg.ServiceSettings.CollapsedThreads = "test_status" + appErr = cfg.ServiceSettings.isValid() + require.NotNil(t, appErr) + require.Equal(t, "model.config.is_valid.collapsed_threads.app_error", appErr.Id) + }) } func TestConfigDefaultCallsPluginState(t *testing.T) {