github.com/crspeller/mattermost-server@v0.0.0-20190328001957-a200beb3d111/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/crspeller/mattermost-server/model" 16 "github.com/crspeller/mattermost-server/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 if teamSettings, ok := envCfg["TeamSettings"]; !ok { 165 t.Fatal("TeamSettings is missing from envConfig") 166 } else if teamSettingsAsMap, ok := teamSettings.(map[string]interface{}); !ok { 167 t.Fatal("TeamSettings is not a map in envConfig") 168 } else { 169 if siteNameInEnv, ok := teamSettingsAsMap["SiteName"].(bool); !ok || !siteNameInEnv { 170 t.Fatal("SiteName should be in envConfig") 171 } 172 173 if customBrandTextInEnv, ok := teamSettingsAsMap["CustomBrandText"].(bool); !ok || !customBrandTextInEnv { 174 t.Fatal("SiteName should be in envConfig") 175 } 176 } 177 178 os.Unsetenv("MM_TEAMSETTINGS_SITENAME") 179 os.Unsetenv("MM_TEAMSETTINGS_CUSTOMBRANDTEXT") 180 181 cfg, envCfg, err = unmarshalConfig(strings.NewReader(config), true) 182 require.Nil(t, err) 183 184 assert.Equal(t, "Mattermost", *cfg.TeamSettings.SiteName) 185 186 if _, ok := envCfg["TeamSettings"]; ok { 187 t.Fatal("TeamSettings should be missing from envConfig") 188 } 189 }) 190 191 t.Run("boolean setting", func(t *testing.T) { 192 os.Setenv("MM_SERVICESETTINGS_ENABLECOMMANDS", "false") 193 defer os.Unsetenv("MM_SERVICESETTINGS_ENABLECOMMANDS") 194 195 cfg, envCfg, err := unmarshalConfig(strings.NewReader(config), true) 196 require.Nil(t, err) 197 198 if *cfg.ServiceSettings.EnableCommands { 199 t.Fatal("Couldn't read config from environment var") 200 } 201 202 if serviceSettings, ok := envCfg["ServiceSettings"]; !ok { 203 t.Fatal("ServiceSettings is missing from envConfig") 204 } else if serviceSettingsAsMap, ok := serviceSettings.(map[string]interface{}); !ok { 205 t.Fatal("ServiceSettings is not a map in envConfig") 206 } else { 207 if enableCommandsInEnv, ok := serviceSettingsAsMap["EnableCommands"].(bool); !ok || !enableCommandsInEnv { 208 t.Fatal("EnableCommands should be in envConfig") 209 } 210 } 211 }) 212 213 t.Run("integer setting", func(t *testing.T) { 214 os.Setenv("MM_SERVICESETTINGS_READTIMEOUT", "400") 215 defer os.Unsetenv("MM_SERVICESETTINGS_READTIMEOUT") 216 217 cfg, envCfg, err := unmarshalConfig(strings.NewReader(config), true) 218 require.Nil(t, err) 219 220 assert.Equal(t, 400, *cfg.ServiceSettings.ReadTimeout) 221 222 if serviceSettings, ok := envCfg["ServiceSettings"]; !ok { 223 t.Fatal("ServiceSettings is missing from envConfig") 224 } else if serviceSettingsAsMap, ok := serviceSettings.(map[string]interface{}); !ok { 225 t.Fatal("ServiceSettings is not a map in envConfig") 226 } else { 227 if readTimeoutInEnv, ok := serviceSettingsAsMap["ReadTimeout"].(bool); !ok || !readTimeoutInEnv { 228 t.Fatal("ReadTimeout should be in envConfig") 229 } 230 } 231 }) 232 233 t.Run("setting missing from config.json", func(t *testing.T) { 234 os.Setenv("MM_SERVICESETTINGS_SITEURL", "https://example.com") 235 defer os.Unsetenv("MM_SERVICESETTINGS_SITEURL") 236 237 cfg, envCfg, err := unmarshalConfig(strings.NewReader(config), true) 238 require.Nil(t, err) 239 240 assert.Equal(t, "https://example.com", *cfg.ServiceSettings.SiteURL) 241 242 if serviceSettings, ok := envCfg["ServiceSettings"]; !ok { 243 t.Fatal("ServiceSettings is missing from envConfig") 244 } else if serviceSettingsAsMap, ok := serviceSettings.(map[string]interface{}); !ok { 245 t.Fatal("ServiceSettings is not a map in envConfig") 246 } else { 247 if siteURLInEnv, ok := serviceSettingsAsMap["SiteURL"].(bool); !ok || !siteURLInEnv { 248 t.Fatal("SiteURL should be in envConfig") 249 } 250 } 251 }) 252 253 t.Run("empty string setting", func(t *testing.T) { 254 os.Setenv("MM_SUPPORTSETTINGS_TERMSOFSERVICELINK", "") 255 defer os.Unsetenv("MM_SUPPORTSETTINGS_TERMSOFSERVICELINK") 256 257 cfg, envCfg, err := unmarshalConfig(strings.NewReader(config), true) 258 require.Nil(t, err) 259 260 assert.Empty(t, *cfg.SupportSettings.TermsOfServiceLink) 261 262 if supportSettings, ok := envCfg["SupportSettings"]; !ok { 263 t.Fatal("SupportSettings is missing from envConfig") 264 } else if supportSettingsAsMap, ok := supportSettings.(map[string]interface{}); !ok { 265 t.Fatal("SupportSettings is not a map in envConfig") 266 } else { 267 if termsOfServiceLinkInEnv, ok := supportSettingsAsMap["TermsOfServiceLink"].(bool); !ok || !termsOfServiceLinkInEnv { 268 t.Fatal("TermsOfServiceLink should be in envConfig") 269 } 270 } 271 }) 272 273 t.Run("plugin directory settings", func(t *testing.T) { 274 os.Setenv("MM_PLUGINSETTINGS_ENABLE", "false") 275 os.Setenv("MM_PLUGINSETTINGS_DIRECTORY", "/temp/plugins") 276 os.Setenv("MM_PLUGINSETTINGS_CLIENTDIRECTORY", "/temp/clientplugins") 277 defer os.Unsetenv("MM_PLUGINSETTINGS_ENABLE") 278 defer os.Unsetenv("MM_PLUGINSETTINGS_DIRECTORY") 279 defer os.Unsetenv("MM_PLUGINSETTINGS_CLIENTDIRECTORY") 280 281 cfg, envCfg, err := unmarshalConfig(strings.NewReader(config), true) 282 require.Nil(t, err) 283 284 assert.Equal(t, false, *cfg.PluginSettings.Enable) 285 assert.Equal(t, "/temp/plugins", *cfg.PluginSettings.Directory) 286 assert.Equal(t, "/temp/clientplugins", *cfg.PluginSettings.ClientDirectory) 287 288 if pluginSettings, ok := envCfg["PluginSettings"]; !ok { 289 t.Fatal("PluginSettings is missing from envConfig") 290 } else if pluginSettingsAsMap, ok := pluginSettings.(map[string]interface{}); !ok { 291 t.Fatal("PluginSettings is not a map in envConfig") 292 } else { 293 if directory, ok := pluginSettingsAsMap["Directory"].(bool); !ok || !directory { 294 t.Fatal("Directory should be in envConfig") 295 } 296 if clientDirectory, ok := pluginSettingsAsMap["ClientDirectory"].(bool); !ok || !clientDirectory { 297 t.Fatal("ClientDirectory should be in envConfig") 298 } 299 } 300 }) 301 302 t.Run("plugin specific settings cannot be overridden via environment", func(t *testing.T) { 303 os.Setenv("MM_PLUGINSETTINGS_PLUGINS_JIRA_ENABLED", "false") 304 os.Setenv("MM_PLUGINSETTINGS_PLUGINS_JIRA_SECRET", "env-secret") 305 os.Setenv("MM_PLUGINSETTINGS_PLUGINSTATES_JIRA_ENABLE", "false") 306 defer os.Unsetenv("MM_PLUGINSETTINGS_PLUGINS_JIRA_ENABLED") 307 defer os.Unsetenv("MM_PLUGINSETTINGS_PLUGINS_JIRA_SECRET") 308 defer os.Unsetenv("MM_PLUGINSETTINGS_PLUGINSTATES_JIRA_ENABLE") 309 310 cfg, envCfg, err := unmarshalConfig(strings.NewReader(config), true) 311 require.Nil(t, err) 312 313 if pluginsJira, ok := cfg.PluginSettings.Plugins["jira"]; !ok { 314 t.Fatal("PluginSettings.Plugins.jira is missing from config") 315 } else { 316 if enabled, ok := pluginsJira["enabled"]; !ok { 317 t.Fatal("PluginSettings.Plugins.jira.enabled is missing from config") 318 } else { 319 assert.Equal(t, "true", enabled) 320 } 321 322 if secret, ok := pluginsJira["secret"]; !ok { 323 t.Fatal("PluginSettings.Plugins.jira.secret is missing from config") 324 } else { 325 assert.Equal(t, "config-secret", secret) 326 } 327 } 328 329 if pluginStatesJira, ok := cfg.PluginSettings.PluginStates["jira"]; !ok { 330 t.Fatal("PluginSettings.PluginStates.jira is missing from config") 331 } else { 332 require.Equal(t, true, pluginStatesJira.Enable) 333 } 334 335 if pluginSettings, ok := envCfg["PluginSettings"]; !ok { 336 t.Fatal("PluginSettings is missing from envConfig") 337 } else if pluginSettingsAsMap, ok := pluginSettings.(map[string]interface{}); !ok { 338 t.Fatal("PluginSettings is not a map in envConfig") 339 } else { 340 if plugins, ok := pluginSettingsAsMap["Plugins"].(map[string]interface{}); !ok { 341 t.Fatal("PluginSettings.Plugins is not a map in envConfig") 342 } else if _, ok := plugins["jira"].(map[string]interface{}); ok { 343 t.Fatal("PluginSettings.Plugins.jira should not be a map in envConfig") 344 } 345 346 if pluginStates, ok := pluginSettingsAsMap["PluginStates"].(map[string]interface{}); !ok { 347 t.Fatal("PluginSettings.PluginStates is missing from envConfig") 348 } else if _, ok := pluginStates["jira"].(map[string]interface{}); ok { 349 t.Fatal("PluginSettings.PluginStates.jira should not be a map in envConfig") 350 } 351 } 352 }) 353 } 354 355 func TestReadConfig_ImageProxySettings(t *testing.T) { 356 utils.TranslationsPreInit() 357 358 t.Run("deprecated settings should still be read properly", func(t *testing.T) { 359 config, _, err := unmarshalConfig(bytes.NewReader([]byte(`{ 360 "ServiceSettings": { 361 "ImageProxyType": "OldImageProxyType", 362 "ImageProxyURL": "OldImageProxyURL", 363 "ImageProxyOptions": "OldImageProxyOptions" 364 } 365 }`)), false) 366 367 require.Nil(t, err) 368 369 assert.Equal(t, model.NewString("OldImageProxyType"), config.ServiceSettings.DEPRECATED_DO_NOT_USE_ImageProxyType) 370 assert.Equal(t, model.NewString("OldImageProxyURL"), config.ServiceSettings.DEPRECATED_DO_NOT_USE_ImageProxyURL) 371 assert.Equal(t, model.NewString("OldImageProxyOptions"), config.ServiceSettings.DEPRECATED_DO_NOT_USE_ImageProxyOptions) 372 }) 373 }