model/config: filtering should work with structs too (#29663)

This commit is contained in:
Ibrahim Serdar Acikgoz 2024-12-20 19:29:02 +01:00 committed by GitHub
parent 9e01424b15
commit 5e7e441623
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 87 additions and 5 deletions

View file

@ -3689,7 +3689,7 @@ func (o *Config) Clone() *Config {
}
func (o *Config) ToJSONFiltered(tagType, tagValue string) ([]byte, error) {
filteredConfigMap := structToMapFilteredByTag(*o, tagType, tagValue)
filteredConfigMap := configToMapFilteredByTag(*o, tagType, tagValue)
for key, value := range filteredConfigMap {
v, ok := value.(map[string]any)
if ok && len(v) == 0 {
@ -4614,8 +4614,8 @@ func FilterConfig(cfg *Config, opts ConfigFilterOptions) (map[string]any, error)
}
for i := range opts.TagFilters {
filteredCfg = structToMapFilteredByTag(filteredCfg, opts.TagFilters[i].TagType, opts.TagFilters[i].TagName)
filteredDefaultCfg = structToMapFilteredByTag(defaultCfg, opts.TagFilters[i].TagType, opts.TagFilters[i].TagName)
filteredCfg = configToMapFilteredByTag(filteredCfg, opts.TagFilters[i].TagType, opts.TagFilters[i].TagName)
filteredDefaultCfg = configToMapFilteredByTag(filteredDefaultCfg, opts.TagFilters[i].TagType, opts.TagFilters[i].TagName)
}
if opts.RemoveDefaults {
@ -4636,8 +4636,26 @@ func FilterConfig(cfg *Config, opts ConfigFilterOptions) (map[string]any, error)
return filteredCfg, nil
}
// structToMapFilteredByTag converts a struct into a map removing those fields that has the tag passed
// configToMapFilteredByTag converts a struct into a map removing those fields that has the tag passed
// as argument
// t shall be either a Config struct value or a map[string]any
func configToMapFilteredByTag(t any, typeOfTag, filterTag string) map[string]any {
switch t.(type) {
case map[string]any:
var tc *Config
b, err := json.Marshal(t)
if err != nil {
// since this is an internal function, we can panic here
// because it should never happen
panic(err)
}
json.Unmarshal(b, &tc)
t = *tc
}
return structToMapFilteredByTag(t, typeOfTag, filterTag)
}
func structToMapFilteredByTag(t any, typeOfTag, filterTag string) map[string]any {
defer func() {
if r := recover(); r != nil {
@ -4688,6 +4706,11 @@ func structToMapFilteredByTag(t any, typeOfTag, filterTag string) map[string]any
// removeEmptyMapsAndSlices removes all the empty maps and slices from a map
func removeEmptyMapsAndSlices(m map[string]any) {
for k, v := range m {
if v == nil {
delete(m, k)
continue
}
switch vt := v.(type) {
case map[string]any:
removeEmptyMapsAndSlices(vt)

View file

@ -1559,7 +1559,7 @@ func TestConfigFilteredByTag(t *testing.T) {
c := Config{}
c.SetDefaults()
cfgMap := structToMapFilteredByTag(c, ConfigAccessTagType, ConfigAccessTagCloudRestrictable)
cfgMap := configToMapFilteredByTag(c, ConfigAccessTagType, ConfigAccessTagCloudRestrictable)
// Remove entire sections but the map is still there
clusterSettings, ok := cfgMap["SqlSettings"].(map[string]any)
@ -2088,4 +2088,63 @@ func TestFilterConfig(t *testing.T) {
require.NoError(t, err)
require.Equal(t, 1.0, m["PluginSettings"].(map[string]any)["Plugins"].(map[string]any)["com.mattermost.plugin-a"].(map[string]any)["setting"])
})
t.Run("should be able to filter specific tag", func(t *testing.T) {
cfg := &Config{}
cfg.SetDefaults()
m, err := FilterConfig(cfg, ConfigFilterOptions{
GetConfigOptions: GetConfigOptions{},
TagFilters: []FilterTag{
{
TagType: ConfigAccessTagType,
TagName: ConfigAccessTagCloudRestrictable,
},
},
})
require.NoError(t, err)
require.NotEmpty(t, m)
fileSettings, ok := m["FileSettings"]
require.True(t, ok)
enableFileAttachments, ok := fileSettings.(map[string]any)["EnableFileAttachments"]
require.True(t, ok)
require.Equal(t, true, enableFileAttachments)
// All fields of SqlSettings are ConfigAccessTagCloudRestrictable
_, ok = m["SqlSettings"]
require.False(t, ok)
})
t.Run("should be able to filter multiple tags", func(t *testing.T) {
cfg := &Config{}
cfg.SetDefaults()
m, err := FilterConfig(cfg, ConfigFilterOptions{
GetConfigOptions: GetConfigOptions{},
TagFilters: []FilterTag{
{
TagType: ConfigAccessTagType,
TagName: "site_file_sharing_and_downloads",
},
{
TagType: ConfigAccessTagType,
TagName: ConfigAccessTagCloudRestrictable,
},
},
})
require.NoError(t, err)
require.NotEmpty(t, m)
fileSettings, ok := m["FileSettings"]
require.True(t, ok)
// EnableFileAttachments has "site_file_sharing_and_downloads" tag
_, ok = fileSettings.(map[string]any)["EnableFileAttachments"]
require.False(t, ok)
// All fields of SqlSettings are ConfigAccessTagCloudRestrictable
_, ok = m["SqlSettings"]
require.False(t, ok)
})
}