summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/file_test.go6
-rw-r--r--api/user_test.go12
-rw-r--r--api4/apitestlib.go6
-rw-r--r--app/admin.go31
-rw-r--r--i18n/en.json32
-rw-r--r--model/config.go25
-rw-r--r--utils/config.go74
-rw-r--r--utils/file.go36
-rw-r--r--webapp/components/admin_console/storage_settings.jsx21
-rwxr-xr-xwebapp/i18n/en.json2
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.",