MM-10417 Add local image proxy and enable by default (#9967)

* MM-10417 Add local image proxy and enable by default

* Remove unused function

* Add dependencies for willnorris/imageproxy

* Fixed compilation errors

* Lock to the master version of willnorris/imageproxy

* Fix atmos/camo proxy when no SiteURL is specified

* Re-add default values for deprecated settings

* Fix unit tests added by merge

* Pass imageproxy to App struct

* Remove unneeded locking when creating the image proxy

* Remove empty test file
Этот коммит содержится в:
Harrison Healey
2019-01-24 16:11:32 -04:00
коммит произвёл GitHub
родитель e961b4cd0d
Коммит ba5566d1a0
80 изменённых файлов: 19742 добавлений и 177 удалений

Просмотреть файл

@@ -174,6 +174,9 @@ const (
CLIENT_SIDE_CERT_CHECK_PRIMARY_AUTH = "primary"
CLIENT_SIDE_CERT_CHECK_SECONDARY_AUTH = "secondary"
IMAGE_PROXY_TYPE_LOCAL = "local"
IMAGE_PROXY_TYPE_ATMOS_CAMO = "atmos/camo"
)
var ServerTLSSupportedCiphers = map[string]uint16{
@@ -272,9 +275,9 @@ type ServiceSettings struct {
ExperimentalEnableDefaultChannelLeaveJoinMessages *bool
ExperimentalGroupUnreadChannels *string
ExperimentalChannelOrganization *bool
ImageProxyType *string
ImageProxyURL *string
ImageProxyOptions *string
DEPRECATED_DO_NOT_USE_ImageProxyType *string `json:"ImageProxyType"` // This field is deprecated and must not be used.
DEPRECATED_DO_NOT_USE_ImageProxyURL *string `json:"ImageProxyURL"` // This field is deprecated and must not be used.
DEPRECATED_DO_NOT_USE_ImageProxyOptions *string `json:"ImageProxyOptions"` // This field is deprecated and must not be used.
EnableAPITeamDeletion *bool
ExperimentalEnableHardenedMode *bool
EnableEmailInvitations *bool
@@ -550,16 +553,16 @@ func (s *ServiceSettings) SetDefaults() {
s.ExperimentalChannelOrganization = NewBool(experimentalUnreadEnabled)
}
if s.ImageProxyType == nil {
s.ImageProxyType = NewString("")
if s.DEPRECATED_DO_NOT_USE_ImageProxyType == nil {
s.DEPRECATED_DO_NOT_USE_ImageProxyType = NewString("")
}
if s.ImageProxyURL == nil {
s.ImageProxyURL = NewString("")
if s.DEPRECATED_DO_NOT_USE_ImageProxyURL == nil {
s.DEPRECATED_DO_NOT_USE_ImageProxyURL = NewString("")
}
if s.ImageProxyOptions == nil {
s.ImageProxyOptions = NewString("")
if s.DEPRECATED_DO_NOT_USE_ImageProxyOptions == nil {
s.DEPRECATED_DO_NOT_USE_ImageProxyOptions = NewString("")
}
if s.EnableAPITeamDeletion == nil {
@@ -1931,6 +1934,43 @@ func (s *TimezoneSettings) SetDefaults() {
}
}
type ImageProxySettings struct {
Enable *bool
ImageProxyType *string
RemoteImageProxyURL *string
RemoteImageProxyOptions *string
}
func (ips *ImageProxySettings) SetDefaults(ss ServiceSettings) {
if ips.Enable == nil {
ips.Enable = NewBool(true)
}
if ips.ImageProxyType == nil {
if ss.DEPRECATED_DO_NOT_USE_ImageProxyType == nil || *ss.DEPRECATED_DO_NOT_USE_ImageProxyType == "" {
ips.ImageProxyType = NewString(IMAGE_PROXY_TYPE_LOCAL)
} else {
ips.ImageProxyType = ss.DEPRECATED_DO_NOT_USE_ImageProxyType
}
}
if ips.RemoteImageProxyURL == nil {
if ss.DEPRECATED_DO_NOT_USE_ImageProxyURL == nil {
ips.RemoteImageProxyURL = NewString("")
} else {
ips.RemoteImageProxyURL = ss.DEPRECATED_DO_NOT_USE_ImageProxyURL
}
}
if ips.RemoteImageProxyOptions == nil {
if ss.DEPRECATED_DO_NOT_USE_ImageProxyOptions == nil {
ips.RemoteImageProxyOptions = NewString("")
} else {
ips.RemoteImageProxyOptions = ss.DEPRECATED_DO_NOT_USE_ImageProxyOptions
}
}
}
type ConfigFunc func() *Config
type Config struct {
@@ -1966,6 +2006,7 @@ type Config struct {
PluginSettings PluginSettings
DisplaySettings DisplaySettings
TimezoneSettings TimezoneSettings
ImageProxySettings ImageProxySettings
}
func (o *Config) Clone() *Config {
@@ -2037,6 +2078,7 @@ func (o *Config) SetDefaults() {
o.MessageExportSettings.SetDefaults()
o.TimezoneSettings.SetDefaults()
o.DisplaySettings.SetDefaults()
o.ImageProxySettings.SetDefaults(o.ServiceSettings)
}
func (o *Config) IsValid() *AppError {
@@ -2108,6 +2150,10 @@ func (o *Config) IsValid() *AppError {
return err
}
if err := o.ImageProxySettings.isValid(); err != nil {
return err
}
return nil
}
@@ -2392,16 +2438,6 @@ func (ss *ServiceSettings) isValid() *AppError {
return NewAppError("Config.IsValid", "model.config.is_valid.group_unread_channels.app_error", nil, "", http.StatusBadRequest)
}
switch *ss.ImageProxyType {
case "":
case "atmos/camo":
if *ss.ImageProxyOptions == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.atmos_camo_image_proxy_options.app_error", nil, "", http.StatusBadRequest)
}
default:
return NewAppError("Config.IsValid", "model.config.is_valid.image_proxy_type.app_error", nil, "", http.StatusBadRequest)
}
return nil
}
@@ -2521,6 +2557,27 @@ func (ds *DisplaySettings) isValid() *AppError {
return nil
}
func (ips *ImageProxySettings) isValid() *AppError {
if *ips.Enable {
switch *ips.ImageProxyType {
case IMAGE_PROXY_TYPE_LOCAL:
// No other settings to validate
case IMAGE_PROXY_TYPE_ATMOS_CAMO:
if *ips.RemoteImageProxyURL == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.atmos_camo_image_proxy_url.app_error", nil, "", http.StatusBadRequest)
}
if *ips.RemoteImageProxyOptions == "" {
return NewAppError("Config.IsValid", "model.config.is_valid.atmos_camo_image_proxy_options.app_error", nil, "", http.StatusBadRequest)
}
default:
return NewAppError("Config.IsValid", "model.config.is_valid.image_proxy_type.app_error", nil, "", http.StatusBadRequest)
}
}
return nil
}
func (o *Config) GetSanitizeOptions() map[string]bool {
options := map[string]bool{}
options["fullname"] = o.PrivacySettings.ShowFullName

Просмотреть файл

@@ -564,3 +564,128 @@ func TestListenAddressIsValidated(t *testing.T) {
}
}
func TestImageProxySettingsSetDefaults(t *testing.T) {
ss := ServiceSettings{
DEPRECATED_DO_NOT_USE_ImageProxyType: NewString(IMAGE_PROXY_TYPE_ATMOS_CAMO),
DEPRECATED_DO_NOT_USE_ImageProxyURL: NewString("http://images.example.com"),
DEPRECATED_DO_NOT_USE_ImageProxyOptions: NewString("1234abcd"),
}
t.Run("default, no old settings", func(t *testing.T) {
ips := ImageProxySettings{}
ips.SetDefaults(ServiceSettings{})
assert.Equal(t, true, *ips.Enable)
assert.Equal(t, IMAGE_PROXY_TYPE_LOCAL, *ips.ImageProxyType)
assert.Equal(t, "", *ips.RemoteImageProxyURL)
assert.Equal(t, "", *ips.RemoteImageProxyOptions)
})
t.Run("default, old settings", func(t *testing.T) {
ips := ImageProxySettings{}
ips.SetDefaults(ss)
assert.Equal(t, true, *ips.Enable)
assert.Equal(t, *ss.DEPRECATED_DO_NOT_USE_ImageProxyType, *ips.ImageProxyType)
assert.Equal(t, *ss.DEPRECATED_DO_NOT_USE_ImageProxyURL, *ips.RemoteImageProxyURL)
assert.Equal(t, *ss.DEPRECATED_DO_NOT_USE_ImageProxyOptions, *ips.RemoteImageProxyOptions)
})
t.Run("not default, old settings", func(t *testing.T) {
url := "http://images.mattermost.com"
options := "aaaaaaaa"
ips := ImageProxySettings{
Enable: NewBool(false),
ImageProxyType: NewString(IMAGE_PROXY_TYPE_LOCAL),
RemoteImageProxyURL: &url,
RemoteImageProxyOptions: &options,
}
ips.SetDefaults(ss)
assert.Equal(t, false, *ips.Enable)
assert.Equal(t, IMAGE_PROXY_TYPE_LOCAL, *ips.ImageProxyType)
assert.Equal(t, url, *ips.RemoteImageProxyURL)
assert.Equal(t, options, *ips.RemoteImageProxyOptions)
})
}
func TestImageProxySettingsIsValid(t *testing.T) {
for _, test := range []struct {
Name string
Enable bool
ImageProxyType string
RemoteImageProxyURL string
RemoteImageProxyOptions string
ExpectError bool
}{
{
Name: "disabled",
Enable: false,
ExpectError: false,
},
{
Name: "disabled with bad values",
Enable: false,
ImageProxyType: "garbage",
RemoteImageProxyURL: "garbage",
RemoteImageProxyOptions: "garbage",
ExpectError: false,
},
{
Name: "missing type",
Enable: true,
ImageProxyType: "",
ExpectError: true,
},
{
Name: "local",
Enable: true,
ImageProxyType: "local",
RemoteImageProxyURL: "garbage",
RemoteImageProxyOptions: "garbage",
ExpectError: false,
},
{
Name: "atmos/camo",
Enable: true,
ImageProxyType: IMAGE_PROXY_TYPE_ATMOS_CAMO,
RemoteImageProxyURL: "someurl",
RemoteImageProxyOptions: "someoptions",
ExpectError: false,
},
{
Name: "atmos/camo, missing url",
Enable: true,
ImageProxyType: IMAGE_PROXY_TYPE_ATMOS_CAMO,
RemoteImageProxyURL: "",
RemoteImageProxyOptions: "garbage",
ExpectError: true,
},
{
Name: "atmos/camo, missing options",
Enable: true,
ImageProxyType: IMAGE_PROXY_TYPE_ATMOS_CAMO,
RemoteImageProxyURL: "someurl",
RemoteImageProxyOptions: "",
ExpectError: true,
},
} {
t.Run(test.Name, func(t *testing.T) {
ips := &ImageProxySettings{
Enable: &test.Enable,
ImageProxyType: &test.ImageProxyType,
RemoteImageProxyURL: &test.RemoteImageProxyURL,
RemoteImageProxyOptions: &test.RemoteImageProxyOptions,
}
err := ips.isValid()
if test.ExpectError {
assert.NotNil(t, err)
} else {
assert.Nil(t, err)
}
})
}
}