diff options
-rw-r--r-- | api/file_test.go | 6 | ||||
-rw-r--r-- | api/user_test.go | 12 | ||||
-rw-r--r-- | api4/apitestlib.go | 6 | ||||
-rw-r--r-- | app/admin.go | 31 | ||||
-rw-r--r-- | i18n/en.json | 32 | ||||
-rw-r--r-- | model/config.go | 25 | ||||
-rw-r--r-- | utils/config.go | 74 | ||||
-rw-r--r-- | utils/file.go | 36 | ||||
-rw-r--r-- | webapp/components/admin_console/storage_settings.jsx | 21 | ||||
-rwxr-xr-x | webapp/i18n/en.json | 2 |
10 files changed, 207 insertions, 38 deletions
diff --git a/api/file_test.go b/api/file_test.go index 0d64608c3..bac8f2619 100644 --- a/api/file_test.go +++ b/api/file_test.go @@ -875,17 +875,17 @@ func s3New(endpoint, accessKey, secretKey string, secure bool, signV2 bool, regi func cleanupTestFile(info *model.FileInfo) error { if *utils.Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 { - endpoint := utils.Cfg.FileSettings.AmazonS3Endpoint + endpoint := *utils.Cfg.FileSettings.AmazonS3Endpoint accessKey := utils.Cfg.FileSettings.AmazonS3AccessKeyId secretKey := utils.Cfg.FileSettings.AmazonS3SecretAccessKey secure := *utils.Cfg.FileSettings.AmazonS3SSL signV2 := *utils.Cfg.FileSettings.AmazonS3SignV2 - region := utils.Cfg.FileSettings.AmazonS3Region + region := *utils.Cfg.FileSettings.AmazonS3Region s3Clnt, err := s3New(endpoint, accessKey, secretKey, secure, signV2, region) if err != nil { return err } - bucket := utils.Cfg.FileSettings.AmazonS3Bucket + bucket := *utils.Cfg.FileSettings.AmazonS3Bucket if err := s3Clnt.RemoveObject(bucket, info.Path); err != nil { return err } diff --git a/api/user_test.go b/api/user_test.go index e11391434..8c68876d0 100644 --- a/api/user_test.go +++ b/api/user_test.go @@ -690,17 +690,17 @@ func TestUserCreateImage(t *testing.T) { } if *utils.Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 { - endpoint := utils.Cfg.FileSettings.AmazonS3Endpoint + endpoint := *utils.Cfg.FileSettings.AmazonS3Endpoint accessKey := utils.Cfg.FileSettings.AmazonS3AccessKeyId secretKey := utils.Cfg.FileSettings.AmazonS3SecretAccessKey secure := *utils.Cfg.FileSettings.AmazonS3SSL signV2 := *utils.Cfg.FileSettings.AmazonS3SignV2 - region := utils.Cfg.FileSettings.AmazonS3Region + region := *utils.Cfg.FileSettings.AmazonS3Region s3Clnt, err := s3New(endpoint, accessKey, secretKey, secure, signV2, region) if err != nil { t.Fatal(err) } - bucket := utils.Cfg.FileSettings.AmazonS3Bucket + bucket := *utils.Cfg.FileSettings.AmazonS3Bucket if err = s3Clnt.RemoveObject(bucket, "/users/"+user.Id+"/profile.png"); err != nil { t.Fatal(err) } @@ -796,17 +796,17 @@ func TestUserUploadProfileImage(t *testing.T) { Client.DoApiGet("/users/"+user.Id+"/image", "", "") if *utils.Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 { - endpoint := utils.Cfg.FileSettings.AmazonS3Endpoint + endpoint := *utils.Cfg.FileSettings.AmazonS3Endpoint accessKey := utils.Cfg.FileSettings.AmazonS3AccessKeyId secretKey := utils.Cfg.FileSettings.AmazonS3SecretAccessKey secure := *utils.Cfg.FileSettings.AmazonS3SSL signV2 := *utils.Cfg.FileSettings.AmazonS3SignV2 - region := utils.Cfg.FileSettings.AmazonS3Region + region := *utils.Cfg.FileSettings.AmazonS3Region s3Clnt, err := s3New(endpoint, accessKey, secretKey, secure, signV2, region) if err != nil { t.Fatal(err) } - bucket := utils.Cfg.FileSettings.AmazonS3Bucket + bucket := *utils.Cfg.FileSettings.AmazonS3Bucket if err = s3Clnt.RemoveObject(bucket, "/users/"+user.Id+"/profile.png"); err != nil { t.Fatal(err) } diff --git a/api4/apitestlib.go b/api4/apitestlib.go index b634de0d4..883b7b931 100644 --- a/api4/apitestlib.go +++ b/api4/apitestlib.go @@ -659,17 +659,17 @@ func s3New(endpoint, accessKey, secretKey string, secure bool, signV2 bool, regi func cleanupTestFile(info *model.FileInfo) error { if *utils.Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 { - endpoint := utils.Cfg.FileSettings.AmazonS3Endpoint + endpoint := *utils.Cfg.FileSettings.AmazonS3Endpoint accessKey := utils.Cfg.FileSettings.AmazonS3AccessKeyId secretKey := utils.Cfg.FileSettings.AmazonS3SecretAccessKey secure := *utils.Cfg.FileSettings.AmazonS3SSL signV2 := *utils.Cfg.FileSettings.AmazonS3SignV2 - region := utils.Cfg.FileSettings.AmazonS3Region + region := *utils.Cfg.FileSettings.AmazonS3Region s3Clnt, err := s3New(endpoint, accessKey, secretKey, secure, signV2, region) if err != nil { return err } - bucket := utils.Cfg.FileSettings.AmazonS3Bucket + bucket := *utils.Cfg.FileSettings.AmazonS3Bucket if err := s3Clnt.RemoveObject(bucket, info.Path); err != nil { return err } diff --git a/app/admin.go b/app/admin.go index 609e37c96..531163046 100644 --- a/app/admin.go +++ b/app/admin.go @@ -11,13 +11,14 @@ import ( "runtime/debug" + "net/http" + l4g "github.com/alecthomas/log4go" "github.com/mattermost/platform/einterfaces" "github.com/mattermost/platform/jobs" "github.com/mattermost/platform/model" "github.com/mattermost/platform/store" "github.com/mattermost/platform/utils" - "net/http" ) func GetLogs(page, perPage int) ([]string, *model.AppError) { @@ -153,6 +154,34 @@ func SaveConfig(cfg *model.Config, sendConfigChangeClusterMessage bool) *model.A return err } + if *cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 { + if !utils.ValidateAmazonS3Endpoint(*cfg.FileSettings.AmazonS3Endpoint) { + *cfg.FileSettings.AmazonS3Endpoint = model.FILE_SETTINGS_DEFAULT_AMAZON_S3_ENDPOINT + l4g.Warn(utils.T("utils.config.set_amazon_endpoint"), model.FILE_SETTINGS_DEFAULT_AMAZON_S3_ENDPOINT) + } + + if !utils.ValidateAmazonS3Region(*cfg.FileSettings.AmazonS3Region) { + *cfg.FileSettings.AmazonS3Region = model.FILE_SETTINGS_DEFAULT_AMAZON_S3_REGION + l4g.Warn(utils.T("utils.config.set_amazon_region"), model.FILE_SETTINGS_DEFAULT_AMAZON_S3_REGION) + } + + _, bucketLocation, err := utils.ValidateAmazonS3Bucket(cfg) + if err != nil { + return err + } + + for endpoint, region := range utils.AWS_S3_ENDPOINT_MAP { + if bucketLocation == *cfg.FileSettings.AmazonS3Region { + *cfg.FileSettings.AmazonS3Endpoint = endpoint + l4g.Warn(utils.T("utils.config.set_amazon_endpoint"), endpoint) + + *cfg.FileSettings.AmazonS3Region = region + l4g.Warn(utils.T("utils.config.set_amazon_region"), region) + break + } + } + } + if *utils.Cfg.ClusterSettings.Enable && *utils.Cfg.ClusterSettings.ReadOnlyConfig { return model.NewAppError("saveConfig", "ent.cluster.save_config.error", nil, "", http.StatusForbidden) } diff --git a/i18n/en.json b/i18n/en.json index 5f7aadcb2..8ada9ce6c 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -6524,6 +6524,38 @@ "translation": "Unable to load mattermost configuration file: Adding DefaultClientLocale to AvailableLocales." }, { + "id": "utils.config.bucket_empty.app_error", + "translation": "Amazon S3 Bucket field is required." + }, + { + "id": "utils.config.error_checking_bucket_exist.app_error", + "translation": "Encountered an error when checking if Amazon S3 Bucket exists. The bucket may not be created yet or cannot be found on the predefined endpoint." + }, + { + "id": "utils.config.error_creating_bucket.app_error", + "translation": "Encountered an error when creating the Amazon S3 Bucket. Confirm you have the proper permissions and try again." + }, + { + "id": "utils.config.bad_connection_to_s3_or_minio.app_error", + "translation": "Bad connection to S3 or Minio cloud storage. Please try again." + }, + { + "id": "utils.config.create_amazon_bucket", + "translation": "Create Amazon S3 Bucket: '%v'." + }, + { + "id": "utils.config.create_amazon_bucket_error", + "translation": "Error in creating Amazon S3 Bucket: '%v'." + }, + { + "id": "utils.config.set_amazon_endpoint", + "translation": "Set Amazon S3 Endpoint to '%v'." + }, + { + "id": "utils.config.set_amazon_region", + "translation": "Set Amazon S3 Region to '%v'." + }, + { "id": "utils.config.load_config.decoding.panic", "translation": "Error decoding config file={{.Filename}}, err={{.Error}}" }, diff --git a/model/config.go b/model/config.go index 311a43261..c6fd84ed0 100644 --- a/model/config.go +++ b/model/config.go @@ -88,6 +88,9 @@ const ( SQL_SETTINGS_DEFAULT_DATA_SOURCE = "mmuser:mostest@tcp(dockerhost:3306)/mattermost_test?charset=utf8mb4,utf8&readTimeout=30s&writeTimeout=30s" + FILE_SETTINGS_DEFAULT_AMAZON_S3_ENDPOINT = "s3.amazonaws.com" + FILE_SETTINGS_DEFAULT_AMAZON_S3_REGION = "us-east-1" + EMAIL_SETTINGS_DEFAULT_FEEDBACK_ORGANIZATION = "" SUPPORT_SETTINGS_DEFAULT_TERMS_OF_SERVICE_LINK = "https://about.mattermost.com/default-terms/" @@ -266,9 +269,9 @@ type FileSettings struct { InitialFont string AmazonS3AccessKeyId string AmazonS3SecretAccessKey string - AmazonS3Bucket string - AmazonS3Region string - AmazonS3Endpoint string + AmazonS3Bucket *string + AmazonS3Region *string + AmazonS3Endpoint *string AmazonS3SSL *bool AmazonS3SignV2 *bool AmazonS3SSE *bool @@ -588,9 +591,19 @@ func (o *Config) SetDefaults() { *o.FileSettings.DriverName = IMAGE_DRIVER_LOCAL } - if o.FileSettings.AmazonS3Endpoint == "" { - // Defaults to "s3.amazonaws.com" - o.FileSettings.AmazonS3Endpoint = "s3.amazonaws.com" + if o.FileSettings.AmazonS3Bucket == nil { + o.FileSettings.AmazonS3Bucket = new(string) + *o.FileSettings.AmazonS3Bucket = "" + } + + if o.FileSettings.AmazonS3Region == nil { + o.FileSettings.AmazonS3Region = new(string) + *o.FileSettings.AmazonS3Region = FILE_SETTINGS_DEFAULT_AMAZON_S3_REGION + } + + if o.FileSettings.AmazonS3Endpoint == nil { + o.FileSettings.AmazonS3Endpoint = new(string) + *o.FileSettings.AmazonS3Endpoint = FILE_SETTINGS_DEFAULT_AMAZON_S3_ENDPOINT } if o.FileSettings.AmazonS3SSL == nil { diff --git a/utils/config.go b/utils/config.go index b99194c46..b8ec43eb5 100644 --- a/utils/config.go +++ b/utils/config.go @@ -18,6 +18,7 @@ import ( l4g "github.com/alecthomas/log4go" "github.com/fsnotify/fsnotify" + s3 "github.com/minio/minio-go" "github.com/spf13/viper" "net/http" @@ -46,6 +47,25 @@ var ClientCfg map[string]string = map[string]string{} var originalDisableDebugLvl l4g.Level = l4g.DEBUG var siteURL = "" +var AWS_S3_ENDPOINT_MAP = map[string]string{ + "s3.amazonaws.com": "us-east-1", + "s3-us-east-2.amazonaws.com": "us-east-2", + "s3-us-west-2.amazonaws.com": "us-west-2", + "s3-us-west-1.amazonaws.com": "us-west-1", + "s3.ca-central-1.amazonaws.com": "ca-central-1", + "s3-eu-west-1.amazonaws.com": "eu-west-1", + "s3-eu-west-2.amazonaws.com": "eu-west-2", + "s3-eu-central-1.amazonaws.com": "eu-central-1", + "s3-ap-south-1.amazonaws.com": "ap-south-1", + "s3-ap-southeast-1.amazonaws.com": "ap-southeast-1", + "s3-ap-southeast-2.amazonaws.com": "ap-southeast-2", + "s3-ap-northeast-1.amazonaws.com": "ap-northeast-1", + "s3-ap-northeast-2.amazonaws.com": "ap-northeast-2", + "s3-sa-east-1.amazonaws.com": "sa-east-1", + "s3-us-gov-west-1.amazonaws.com": "us-gov-west-1", + "s3.cn-north-1.amazonaws.com.cn": "cn-north-1", +} + func GetSiteURL() string { return siteURL } @@ -689,3 +709,57 @@ func IsLeader() bool { return true } } + +func ValidateAmazonS3Endpoint(endpoint string) bool { + _, valid := AWS_S3_ENDPOINT_MAP[endpoint] + + return valid +} + +func ValidateAmazonS3Region(region string) bool { + for _, awsRegion := range AWS_S3_ENDPOINT_MAP { + if awsRegion == region { + return true + } + } + + return false +} + +func ValidateAmazonS3Bucket(cfg *model.Config) (bool, string, *model.AppError) { + if *cfg.FileSettings.AmazonS3Bucket == "" { + return false, "", model.NewAppError("ValidateAmazonS3Bucket", "utils.config.bucket_empty.app_error", nil, "", http.StatusBadRequest) + } + + endpoint := *cfg.FileSettings.AmazonS3Endpoint + bucket := *cfg.FileSettings.AmazonS3Bucket + accessKey := cfg.FileSettings.AmazonS3AccessKeyId + secretKey := cfg.FileSettings.AmazonS3SecretAccessKey + secure := *cfg.FileSettings.AmazonS3SSL + + s3Clnt, err := s3.New(endpoint, accessKey, secretKey, secure) + if err != nil { + return false, "", model.NewAppError("ValidateAmazonS3Bucket", "utils.config.bad_connection_to_s3_or_minio.app_error", nil, err.Error(), http.StatusBadRequest) + } + + bucketLocation, err := s3Clnt.GetBucketLocation(bucket) + if err != nil { + bucketLocation = *cfg.FileSettings.AmazonS3Region + + exists, err := s3Clnt.BucketExists(bucket) + if err != nil { + return false, "", model.NewAppError("ValidateAmazonS3Bucket", "utils.config.error_checking_bucket_exist.app_error", nil, err.Error(), http.StatusBadRequest) + } + + if !exists { + err := s3Clnt.MakeBucket(bucket, bucketLocation) + if err != nil { + l4g.Error(T("utils.config.create_amazon_bucket_error"), bucket) + return false, "", model.NewAppError("ValidateAmazonS3Bucket", "utils.config.error_creating_bucket.app_error", nil, err.Error(), http.StatusBadRequest) + } + l4g.Warn(T("utils.config.create_amazon_bucket"), bucket) + } + } + + return true, bucketLocation, nil +} diff --git a/utils/file.go b/utils/file.go index 19fa335c4..d8926cfaa 100644 --- a/utils/file.go +++ b/utils/file.go @@ -48,13 +48,13 @@ func s3New(endpoint, accessKey, secretKey string, secure bool, signV2 bool, regi func TestFileConnection() *model.AppError { if *Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 { - endpoint := Cfg.FileSettings.AmazonS3Endpoint + endpoint := *Cfg.FileSettings.AmazonS3Endpoint accessKey := Cfg.FileSettings.AmazonS3AccessKeyId secretKey := Cfg.FileSettings.AmazonS3SecretAccessKey secure := *Cfg.FileSettings.AmazonS3SSL signV2 := *Cfg.FileSettings.AmazonS3SignV2 - region := Cfg.FileSettings.AmazonS3Region - bucket := Cfg.FileSettings.AmazonS3Bucket + region := *Cfg.FileSettings.AmazonS3Region + bucket := *Cfg.FileSettings.AmazonS3Bucket s3Clnt, err := s3New(endpoint, accessKey, secretKey, secure, signV2, region) if err != nil { @@ -91,17 +91,17 @@ func TestFileConnection() *model.AppError { func ReadFile(path string) ([]byte, *model.AppError) { if *Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 { - endpoint := Cfg.FileSettings.AmazonS3Endpoint + endpoint := *Cfg.FileSettings.AmazonS3Endpoint accessKey := Cfg.FileSettings.AmazonS3AccessKeyId secretKey := Cfg.FileSettings.AmazonS3SecretAccessKey secure := *Cfg.FileSettings.AmazonS3SSL signV2 := *Cfg.FileSettings.AmazonS3SignV2 - region := Cfg.FileSettings.AmazonS3Region + region := *Cfg.FileSettings.AmazonS3Region s3Clnt, err := s3New(endpoint, accessKey, secretKey, secure, signV2, region) if err != nil { return nil, model.NewLocAppError("ReadFile", "api.file.read_file.s3.app_error", nil, err.Error()) } - bucket := Cfg.FileSettings.AmazonS3Bucket + bucket := *Cfg.FileSettings.AmazonS3Bucket minioObject, err := s3Clnt.GetObject(bucket, path) defer minioObject.Close() if err != nil { @@ -125,12 +125,12 @@ func ReadFile(path string) ([]byte, *model.AppError) { func MoveFile(oldPath, newPath string) *model.AppError { if *Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 { - endpoint := Cfg.FileSettings.AmazonS3Endpoint + endpoint := *Cfg.FileSettings.AmazonS3Endpoint accessKey := Cfg.FileSettings.AmazonS3AccessKeyId secretKey := Cfg.FileSettings.AmazonS3SecretAccessKey secure := *Cfg.FileSettings.AmazonS3SSL signV2 := *Cfg.FileSettings.AmazonS3SignV2 - region := Cfg.FileSettings.AmazonS3Region + region := *Cfg.FileSettings.AmazonS3Region encrypt := false if *Cfg.FileSettings.AmazonS3SSE && IsLicensed() && *License().Features.Compliance { encrypt = true @@ -139,7 +139,7 @@ func MoveFile(oldPath, newPath string) *model.AppError { if err != nil { return model.NewLocAppError("moveFile", "api.file.write_file.s3.app_error", nil, err.Error()) } - bucket := Cfg.FileSettings.AmazonS3Bucket + bucket := *Cfg.FileSettings.AmazonS3Bucket source := s3.NewSourceInfo(bucket, oldPath, nil) destination, err := s3.NewDestinationInfo(bucket, newPath, nil, CopyMetadata(encrypt)) @@ -169,12 +169,12 @@ func MoveFile(oldPath, newPath string) *model.AppError { func WriteFile(f []byte, path string) *model.AppError { if *Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 { - endpoint := Cfg.FileSettings.AmazonS3Endpoint + endpoint := *Cfg.FileSettings.AmazonS3Endpoint accessKey := Cfg.FileSettings.AmazonS3AccessKeyId secretKey := Cfg.FileSettings.AmazonS3SecretAccessKey secure := *Cfg.FileSettings.AmazonS3SSL signV2 := *Cfg.FileSettings.AmazonS3SignV2 - region := Cfg.FileSettings.AmazonS3Region + region := *Cfg.FileSettings.AmazonS3Region encrypt := false if *Cfg.FileSettings.AmazonS3SSE && IsLicensed() && *License().Features.Compliance { encrypt = true @@ -185,7 +185,7 @@ func WriteFile(f []byte, path string) *model.AppError { return model.NewLocAppError("WriteFile", "api.file.write_file.s3.app_error", nil, err.Error()) } - bucket := Cfg.FileSettings.AmazonS3Bucket + bucket := *Cfg.FileSettings.AmazonS3Bucket ext := filepath.Ext(path) metaData := S3Metadata(encrypt, "binary/octet-stream") if model.IsFileExtImage(ext) { @@ -222,19 +222,19 @@ func writeFileLocally(f []byte, path string) *model.AppError { func RemoveFile(path string) *model.AppError { if *Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 { - endpoint := Cfg.FileSettings.AmazonS3Endpoint + endpoint := *Cfg.FileSettings.AmazonS3Endpoint accessKey := Cfg.FileSettings.AmazonS3AccessKeyId secretKey := Cfg.FileSettings.AmazonS3SecretAccessKey secure := *Cfg.FileSettings.AmazonS3SSL signV2 := *Cfg.FileSettings.AmazonS3SignV2 - region := Cfg.FileSettings.AmazonS3Region + region := *Cfg.FileSettings.AmazonS3Region s3Clnt, err := s3New(endpoint, accessKey, secretKey, secure, signV2, region) if err != nil { return model.NewLocAppError("RemoveFile", "utils.file.remove_file.s3.app_error", nil, err.Error()) } - bucket := Cfg.FileSettings.AmazonS3Bucket + bucket := *Cfg.FileSettings.AmazonS3Bucket if err := s3Clnt.RemoveObject(bucket, path); err != nil { return model.NewLocAppError("RemoveFile", "utils.file.remove_file.s3.app_error", nil, err.Error()) } @@ -271,12 +271,12 @@ func getPathsFromObjectInfos(in <-chan s3.ObjectInfo) <-chan string { func RemoveDirectory(path string) *model.AppError { if *Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 { - endpoint := Cfg.FileSettings.AmazonS3Endpoint + endpoint := *Cfg.FileSettings.AmazonS3Endpoint accessKey := Cfg.FileSettings.AmazonS3AccessKeyId secretKey := Cfg.FileSettings.AmazonS3SecretAccessKey secure := *Cfg.FileSettings.AmazonS3SSL signV2 := *Cfg.FileSettings.AmazonS3SignV2 - region := Cfg.FileSettings.AmazonS3Region + region := *Cfg.FileSettings.AmazonS3Region s3Clnt, err := s3New(endpoint, accessKey, secretKey, secure, signV2, region) if err != nil { @@ -285,7 +285,7 @@ func RemoveDirectory(path string) *model.AppError { doneCh := make(chan struct{}) - bucket := Cfg.FileSettings.AmazonS3Bucket + bucket := *Cfg.FileSettings.AmazonS3Bucket for err := range s3Clnt.RemoveObjects(bucket, getPathsFromObjectInfos(s3Clnt.ListObjects(bucket, path, true, doneCh))) { if err.Err != nil { doneCh <- struct{}{} diff --git a/webapp/components/admin_console/storage_settings.jsx b/webapp/components/admin_console/storage_settings.jsx index 4b20a8b93..54bbdb798 100644 --- a/webapp/components/admin_console/storage_settings.jsx +++ b/webapp/components/admin_console/storage_settings.jsx @@ -34,6 +34,7 @@ export default class StorageSettings extends AdminSettings { config.FileSettings.AmazonS3AccessKeyId = this.state.amazonS3AccessKeyId; config.FileSettings.AmazonS3SecretAccessKey = this.state.amazonS3SecretAccessKey; config.FileSettings.AmazonS3Bucket = this.state.amazonS3Bucket; + config.FileSettings.AmazonS3Region = this.state.amazonS3Region; config.FileSettings.AmazonS3Endpoint = this.state.amazonS3Endpoint; config.FileSettings.AmazonS3SSL = this.state.amazonS3SSL; config.FileSettings.AmazonS3SSE = this.state.amazonS3SSE; @@ -53,6 +54,7 @@ export default class StorageSettings extends AdminSettings { amazonS3AccessKeyId: config.FileSettings.AmazonS3AccessKeyId, amazonS3SecretAccessKey: config.FileSettings.AmazonS3SecretAccessKey, amazonS3Bucket: config.FileSettings.AmazonS3Bucket, + amazonS3Region: config.FileSettings.AmazonS3Region, amazonS3Endpoint: config.FileSettings.AmazonS3Endpoint, amazonS3SSL: config.FileSettings.AmazonS3SSL, amazonS3SSE: config.FileSettings.AmazonS3SSE, @@ -242,6 +244,25 @@ export default class StorageSettings extends AdminSettings { disabled={this.state.driverName !== DRIVER_S3} /> <TextSetting + id='amazonS3Region' + label={ + <FormattedMessage + id='admin.image.amazonS3RegionTitle' + defaultMessage='Amazon S3 Region:' + /> + } + placeholder={Utils.localizeMessage('admin.image.amazonS3RegionExample', 'Ex "us-east-1"')} + helpText={ + <FormattedMessage + id='admin.image.amazonS3RegionDescription' + defaultMessage='(Optional) AWS region you selected when creating your S3 bucket. If no region is set, Mattermost attempts to get the appropriate region from AWS, or sets it to "us-east-1" if none found.' + /> + } + value={this.state.amazonS3Region} + onChange={this.handleChange} + disabled={this.state.driverName !== DRIVER_S3} + /> + <TextSetting id='amazonS3Endpoint' label={ <FormattedMessage diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json index f111c5dd5..87da9c943 100755 --- a/webapp/i18n/en.json +++ b/webapp/i18n/en.json @@ -475,7 +475,7 @@ "admin.image.amazonS3IdDescription": "Obtain this credential from your Amazon EC2 administrator.", "admin.image.amazonS3IdExample": "E.g.: \"AKIADTOVBGERKLCBV\"", "admin.image.amazonS3IdTitle": "Amazon S3 Access Key ID:", - "admin.image.amazonS3RegionDescription": "AWS region you selected for creating your S3 bucket.", + "admin.image.amazonS3RegionDescription": "(Optional) AWS region you selected when creating your S3 bucket. If no region is set, Mattermost attempts to get the appropriate region from AWS, or sets it to 'us-east-1' if none found.", "admin.image.amazonS3RegionExample": "E.g.: \"us-east-1\"", "admin.image.amazonS3RegionTitle": "Amazon S3 Region:", "admin.image.amazonS3SSEDescription": "When true, encrypt files in Amazon S3 using server-side encryption with Amazon S3-managed keys. See <a href=\"https://about.mattermost.com/default-server-side-encryption\">documentation</a> to learn more.", |