github.com/mattermosttest/mattermost-server/v5@v5.0.0-20200917143240-9dfa12e121f9/config/unmarshal_test.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package config
     5  
     6  import (
     7  	"bytes"
     8  	"os"
     9  	"strings"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  	"github.com/stretchr/testify/require"
    14  
    15  	"github.com/mattermost/mattermost-server/v5/model"
    16  	"github.com/mattermost/mattermost-server/v5/utils"
    17  )
    18  
    19  func TestGetDefaultsFromStruct(t *testing.T) {
    20  	s := struct {
    21  		TestSettings struct {
    22  			IntValue    int
    23  			BoolValue   bool
    24  			StringValue string
    25  		}
    26  		PointerToTestSettings *struct {
    27  			Value int
    28  		}
    29  	}{}
    30  
    31  	defaults := getDefaultsFromStruct(s)
    32  
    33  	assert.Equal(t, defaults["TestSettings.IntValue"], 0)
    34  	assert.Equal(t, defaults["TestSettings.BoolValue"], false)
    35  	assert.Equal(t, defaults["TestSettings.StringValue"], "")
    36  	assert.Equal(t, defaults["PointerToTestSettings.Value"], 0)
    37  	assert.NotContains(t, defaults, "PointerToTestSettings")
    38  	assert.Len(t, defaults, 4)
    39  }
    40  
    41  func TestUnmarshalConfig(t *testing.T) {
    42  	_, _, err := unmarshalConfig(bytes.NewReader([]byte(``)), false)
    43  	require.EqualError(t, err, "parsing error at line 1, character 1: unexpected end of JSON input")
    44  
    45  	_, _, err = unmarshalConfig(bytes.NewReader([]byte(`
    46  		{
    47  			malformed
    48  	`)), false)
    49  	require.EqualError(t, err, "parsing error at line 3, character 5: invalid character 'm' looking for beginning of object key string")
    50  }
    51  
    52  func TestUnmarshalConfig_PluginSettings(t *testing.T) {
    53  	config, _, err := unmarshalConfig(bytes.NewReader([]byte(`{
    54  		"PluginSettings": {
    55  			"Directory": "/temp/mattermost-plugins",
    56  			"Plugins": {
    57  				"com.example.plugin": {
    58  					"number": 1,
    59  					"string": "abc",
    60  					"boolean": false,
    61  					"abc.def.ghi": {
    62  						"abc": 123,
    63  						"def": "456"
    64  					}
    65  				},
    66  				"jira": {
    67  					"number": 2,
    68  					"string": "123",
    69  					"boolean": true,
    70  					"abc.def.ghi": {
    71  						"abc": 456,
    72  						"def": "123"
    73  					}
    74   				}
    75  			},
    76  			"PluginStates": {
    77  				"com.example.plugin": {
    78  					"enable": true
    79  				},
    80  				"jira": {
    81  					"enable": false
    82   				}
    83  			}
    84  		}
    85  	}`)), false)
    86  	require.Nil(t, err)
    87  
    88  	assert.Equal(t, "/temp/mattermost-plugins", *config.PluginSettings.Directory)
    89  
    90  	if assert.Contains(t, config.PluginSettings.Plugins, "com.example.plugin") {
    91  		assert.Equal(t, map[string]interface{}{
    92  			"number":  float64(1),
    93  			"string":  "abc",
    94  			"boolean": false,
    95  			"abc.def.ghi": map[string]interface{}{
    96  				"abc": float64(123),
    97  				"def": "456",
    98  			},
    99  		}, config.PluginSettings.Plugins["com.example.plugin"])
   100  	}
   101  	if assert.Contains(t, config.PluginSettings.PluginStates, "com.example.plugin") {
   102  		assert.Equal(t, model.PluginState{
   103  			Enable: true,
   104  		}, *config.PluginSettings.PluginStates["com.example.plugin"])
   105  	}
   106  
   107  	if assert.Contains(t, config.PluginSettings.Plugins, "jira") {
   108  		assert.Equal(t, map[string]interface{}{
   109  			"number":  float64(2),
   110  			"string":  "123",
   111  			"boolean": true,
   112  			"abc.def.ghi": map[string]interface{}{
   113  				"abc": float64(456),
   114  				"def": "123",
   115  			},
   116  		}, config.PluginSettings.Plugins["jira"])
   117  	}
   118  	if assert.Contains(t, config.PluginSettings.PluginStates, "jira") {
   119  		assert.Equal(t, model.PluginState{
   120  			Enable: false,
   121  		}, *config.PluginSettings.PluginStates["jira"])
   122  	}
   123  }
   124  
   125  func TestConfigFromEnviroVars(t *testing.T) {
   126  	config := `{
   127  		"ServiceSettings": {
   128  			"EnableCommands": true,
   129  			"ReadTimeout": 100
   130  		},
   131  		"TeamSettings": {
   132  			"SiteName": "Mattermost",
   133  			"CustomBrandText": ""
   134  		},
   135  		"SupportSettings": {
   136  			"TermsOfServiceLink": "https://about.mattermost.com/default-terms/"
   137  		},
   138  		"PluginSettings": {
   139  			"Enable": true,
   140  			"Plugins": {
   141  				"jira": {
   142  					"enabled": "true",
   143  					"secret": "config-secret"
   144  				}
   145  			},
   146  			"PluginStates": {
   147  				"jira": {
   148  					"Enable": true
   149  				}
   150  			}
   151  		}
   152  	}`
   153  
   154  	t.Run("string settings", func(t *testing.T) {
   155  		os.Setenv("MM_TEAMSETTINGS_SITENAME", "From Environment")
   156  		os.Setenv("MM_TEAMSETTINGS_CUSTOMBRANDTEXT", "Custom Brand")
   157  
   158  		cfg, envCfg, err := unmarshalConfig(strings.NewReader(config), true)
   159  		require.Nil(t, err)
   160  
   161  		assert.Equal(t, "From Environment", *cfg.TeamSettings.SiteName)
   162  		assert.Equal(t, "Custom Brand", *cfg.TeamSettings.CustomBrandText)
   163  
   164  		teamSettings, ok := envCfg["TeamSettings"]
   165  		require.True(t, ok, "TeamSettings is missing from envConfig")
   166  
   167  		teamSettingsAsMap, ok := teamSettings.(map[string]interface{})
   168  		require.True(t, ok, "TeamSettings is not a map in envConfig")
   169  
   170  		siteNameInEnv, ok := teamSettingsAsMap["SiteName"].(bool)
   171  		require.True(t, ok || siteNameInEnv, "SiteName should be in envConfig")
   172  
   173  		customBrandTextInEnv, ok := teamSettingsAsMap["CustomBrandText"].(bool)
   174  		require.True(t, ok || customBrandTextInEnv, "SiteName should be in envConfig")
   175  
   176  		os.Unsetenv("MM_TEAMSETTINGS_SITENAME")
   177  		os.Unsetenv("MM_TEAMSETTINGS_CUSTOMBRANDTEXT")
   178  
   179  		cfg, envCfg, err = unmarshalConfig(strings.NewReader(config), true)
   180  		require.Nil(t, err)
   181  
   182  		assert.Equal(t, "Mattermost", *cfg.TeamSettings.SiteName)
   183  
   184  		_, ok = envCfg["TeamSettings"]
   185  		require.False(t, ok, "TeamSettings should be missing from envConfig")
   186  	})
   187  
   188  	t.Run("boolean setting", func(t *testing.T) {
   189  		os.Setenv("MM_SERVICESETTINGS_ENABLECOMMANDS", "false")
   190  		defer os.Unsetenv("MM_SERVICESETTINGS_ENABLECOMMANDS")
   191  
   192  		cfg, envCfg, err := unmarshalConfig(strings.NewReader(config), true)
   193  		require.Nil(t, err)
   194  
   195  		require.False(t, *cfg.ServiceSettings.EnableCommands, "Couldn't read config from environment var")
   196  
   197  		serviceSettings, ok := envCfg["ServiceSettings"]
   198  		require.True(t, ok, "ServiceSettings is missing from envConfig")
   199  
   200  		serviceSettingsAsMap, ok := serviceSettings.(map[string]interface{})
   201  		require.True(t, ok, "ServiceSettings is not a map in envConfig")
   202  
   203  		enableCommandsInEnv, ok := serviceSettingsAsMap["EnableCommands"].(bool)
   204  		require.True(t, ok || enableCommandsInEnv, "EnableCommands should be in envConfig")
   205  	})
   206  
   207  	t.Run("integer setting", func(t *testing.T) {
   208  		os.Setenv("MM_SERVICESETTINGS_READTIMEOUT", "400")
   209  		defer os.Unsetenv("MM_SERVICESETTINGS_READTIMEOUT")
   210  
   211  		cfg, envCfg, err := unmarshalConfig(strings.NewReader(config), true)
   212  		require.Nil(t, err)
   213  
   214  		assert.Equal(t, 400, *cfg.ServiceSettings.ReadTimeout)
   215  
   216  		serviceSettings, ok := envCfg["ServiceSettings"]
   217  		require.True(t, ok, "ServiceSettings is missing from envConfig")
   218  
   219  		serviceSettingsAsMap, ok := serviceSettings.(map[string]interface{})
   220  		require.True(t, ok, "ServiceSettings is not a map in envConfig")
   221  
   222  		readTimeoutInEnv, ok := serviceSettingsAsMap["ReadTimeout"].(bool)
   223  		require.True(t, ok || readTimeoutInEnv, "ReadTimeout should be in envConfig")
   224  	})
   225  
   226  	t.Run("setting missing from config.json", func(t *testing.T) {
   227  		os.Setenv("MM_SERVICESETTINGS_SITEURL", "https://example.com")
   228  		defer os.Unsetenv("MM_SERVICESETTINGS_SITEURL")
   229  
   230  		cfg, envCfg, err := unmarshalConfig(strings.NewReader(config), true)
   231  		require.Nil(t, err)
   232  
   233  		assert.Equal(t, "https://example.com", *cfg.ServiceSettings.SiteURL)
   234  
   235  		serviceSettings, ok := envCfg["ServiceSettings"]
   236  		require.True(t, ok, "ServiceSettings is missing from envConfig")
   237  
   238  		serviceSettingsAsMap, ok := serviceSettings.(map[string]interface{})
   239  		require.True(t, ok, "ServiceSettings is not a map in envConfig")
   240  
   241  		siteURLInEnv, ok := serviceSettingsAsMap["SiteURL"].(bool)
   242  		require.True(t, ok || siteURLInEnv, "SiteURL should be in envConfig")
   243  	})
   244  
   245  	t.Run("empty string setting", func(t *testing.T) {
   246  		os.Setenv("MM_SUPPORTSETTINGS_TERMSOFSERVICELINK", "")
   247  		defer os.Unsetenv("MM_SUPPORTSETTINGS_TERMSOFSERVICELINK")
   248  
   249  		cfg, envCfg, err := unmarshalConfig(strings.NewReader(config), true)
   250  		require.Nil(t, err)
   251  
   252  		assert.Empty(t, *cfg.SupportSettings.TermsOfServiceLink)
   253  
   254  		supportSettings, ok := envCfg["SupportSettings"]
   255  		require.True(t, ok, "SupportSettings is missing from envConfig")
   256  
   257  		supportSettingsAsMap, ok := supportSettings.(map[string]interface{})
   258  		require.True(t, ok, "SupportSettings is not a map in envConfig")
   259  
   260  		termsOfServiceLinkInEnv, ok := supportSettingsAsMap["TermsOfServiceLink"].(bool)
   261  		require.True(t, ok || termsOfServiceLinkInEnv, "TermsOfServiceLink should be in envConfig")
   262  	})
   263  
   264  	t.Run("plugin directory settings", func(t *testing.T) {
   265  		os.Setenv("MM_PLUGINSETTINGS_ENABLE", "false")
   266  		os.Setenv("MM_PLUGINSETTINGS_DIRECTORY", "/temp/plugins")
   267  		os.Setenv("MM_PLUGINSETTINGS_CLIENTDIRECTORY", "/temp/clientplugins")
   268  		defer os.Unsetenv("MM_PLUGINSETTINGS_ENABLE")
   269  		defer os.Unsetenv("MM_PLUGINSETTINGS_DIRECTORY")
   270  		defer os.Unsetenv("MM_PLUGINSETTINGS_CLIENTDIRECTORY")
   271  
   272  		cfg, envCfg, err := unmarshalConfig(strings.NewReader(config), true)
   273  		require.Nil(t, err)
   274  
   275  		assert.Equal(t, false, *cfg.PluginSettings.Enable)
   276  		assert.Equal(t, "/temp/plugins", *cfg.PluginSettings.Directory)
   277  		assert.Equal(t, "/temp/clientplugins", *cfg.PluginSettings.ClientDirectory)
   278  
   279  		pluginSettings, ok := envCfg["PluginSettings"]
   280  		require.True(t, ok, "PluginSettings is missing from envConfig")
   281  
   282  		pluginSettingsAsMap, ok := pluginSettings.(map[string]interface{})
   283  		require.True(t, ok, "PluginSettings is not a map in envConfig")
   284  
   285  		directory, ok := pluginSettingsAsMap["Directory"].(bool)
   286  		require.True(t, ok || directory, "Directory should be in envConfig")
   287  
   288  		clientDirectory, ok := pluginSettingsAsMap["ClientDirectory"].(bool)
   289  		require.True(t, ok || clientDirectory, "ClientDirectory should be in envConfig")
   290  	})
   291  
   292  	t.Run("plugin specific settings cannot be overridden via environment", func(t *testing.T) {
   293  		os.Setenv("MM_PLUGINSETTINGS_PLUGINS_JIRA_ENABLED", "false")
   294  		os.Setenv("MM_PLUGINSETTINGS_PLUGINS_JIRA_SECRET", "env-secret")
   295  		os.Setenv("MM_PLUGINSETTINGS_PLUGINSTATES_JIRA_ENABLE", "false")
   296  		defer os.Unsetenv("MM_PLUGINSETTINGS_PLUGINS_JIRA_ENABLED")
   297  		defer os.Unsetenv("MM_PLUGINSETTINGS_PLUGINS_JIRA_SECRET")
   298  		defer os.Unsetenv("MM_PLUGINSETTINGS_PLUGINSTATES_JIRA_ENABLE")
   299  
   300  		cfg, envCfg, err := unmarshalConfig(strings.NewReader(config), true)
   301  		require.Nil(t, err)
   302  
   303  		pluginsJira, ok := cfg.PluginSettings.Plugins["jira"]
   304  		require.True(t, ok, "PluginSettings.Plugins.jira is missing from config")
   305  
   306  		enabled, ok := pluginsJira["enabled"]
   307  		require.True(t, ok, "PluginSettings.Plugins.jira.enabled is missing from config")
   308  		assert.Equal(t, "true", enabled)
   309  
   310  		secret, ok := pluginsJira["secret"]
   311  		require.True(t, ok, "PluginSettings.Plugins.jira.secret is missing from config")
   312  		assert.Equal(t, "config-secret", secret)
   313  
   314  		pluginStatesJira, ok := cfg.PluginSettings.PluginStates["jira"]
   315  		require.True(t, ok, "PluginSettings.PluginStates.jira is missing from config")
   316  		require.Equal(t, true, pluginStatesJira.Enable)
   317  
   318  		pluginSettings, ok := envCfg["PluginSettings"]
   319  		require.True(t, ok, "PluginSettings is missing from envConfig")
   320  
   321  		pluginSettingsAsMap, ok := pluginSettings.(map[string]interface{})
   322  		require.True(t, ok, "PluginSettings is not a map in envConfig")
   323  
   324  		plugins, ok := pluginSettingsAsMap["Plugins"].(map[string]interface{})
   325  		require.True(t, ok, "PluginSettings.Plugins is not a map in envConfig")
   326  
   327  		_, ok = plugins["jira"].(map[string]interface{})
   328  		require.False(t, ok, "PluginSettings.Plugins.jira should not be a map in envConfig")
   329  
   330  		pluginStates, ok := pluginSettingsAsMap["PluginStates"].(map[string]interface{})
   331  		require.True(t, ok, "PluginSettings.PluginStates is missing from envConfig")
   332  
   333  		_, ok = pluginStates["jira"].(map[string]interface{})
   334  		require.False(t, ok, "PluginSettings.PluginStates.jira should not be a map in envConfig")
   335  	})
   336  }
   337  
   338  func TestReadConfig_ImageProxySettings(t *testing.T) {
   339  	utils.TranslationsPreInit()
   340  
   341  	t.Run("deprecated settings should still be read properly", func(t *testing.T) {
   342  		config, _, err := unmarshalConfig(bytes.NewReader([]byte(`{
   343  			"ServiceSettings": {
   344  				"ImageProxyType": "OldImageProxyType",
   345  				"ImageProxyURL": "OldImageProxyURL",
   346  				"ImageProxyOptions": "OldImageProxyOptions"
   347  			}
   348  		}`)), false)
   349  
   350  		require.Nil(t, err)
   351  
   352  		assert.Equal(t, model.NewString("OldImageProxyType"), config.ServiceSettings.DEPRECATED_DO_NOT_USE_ImageProxyType)
   353  		assert.Equal(t, model.NewString("OldImageProxyURL"), config.ServiceSettings.DEPRECATED_DO_NOT_USE_ImageProxyURL)
   354  		assert.Equal(t, model.NewString("OldImageProxyOptions"), config.ServiceSettings.DEPRECATED_DO_NOT_USE_ImageProxyOptions)
   355  	})
   356  }