diff --git a/api/file.go b/api/file.go
index 0f2fd9319299cbf1b10d7987ac7a59fbe634d50b..9a5de56691fa8256045e88e9b7e09159db27bcf4 100644
--- a/api/file.go
+++ b/api/file.go
@@ -31,6 +31,11 @@ func InitFile() {
}
func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) {
+ if !*utils.Cfg.FileSettings.EnableFileAttachments {
+ c.Err = model.NewAppError("uploadFile", "api.file.attachments.disabled.app_error", nil, "", http.StatusNotImplemented)
+ return
+ }
+
if r.ContentLength > *utils.Cfg.FileSettings.MaxFileSize {
c.Err = model.NewLocAppError("uploadFile", "api.file.upload_file.too_large.app_error", nil, "")
c.Err.StatusCode = http.StatusRequestEntityTooLarge
@@ -181,9 +186,7 @@ func getPublicFile(c *Context, w http.ResponseWriter, r *http.Request) {
func getFileInfoForRequest(c *Context, r *http.Request, requireFileVisible bool) (*model.FileInfo, *model.AppError) {
if len(utils.Cfg.FileSettings.DriverName) == 0 {
- err := model.NewLocAppError("getFileInfoForRequest", "api.file.get_file_info_for_request.storage.app_error", nil, "")
- err.StatusCode = http.StatusNotImplemented
- return nil, err
+ return nil, model.NewAppError("getFileInfoForRequest", "api.file.get_info_for_request.storage.app_error", nil, "", http.StatusNotImplemented)
}
params := mux.Vars(r)
diff --git a/api/file_test.go b/api/file_test.go
index 1e65c33e86aa95822e080f70ad9fecac8f4d99b9..40534d724afa392680ed834d3c89b83aa466de96 100644
--- a/api/file_test.go
+++ b/api/file_test.go
@@ -99,6 +99,18 @@ func TestUploadFile(t *testing.T) {
t.Fatalf("file preview should've been saved in %v", expectedPreviewPath)
}
+ enableFileAttachments := *utils.Cfg.FileSettings.EnableFileAttachments
+ defer func() {
+ *utils.Cfg.FileSettings.EnableFileAttachments = enableFileAttachments
+ }()
+ *utils.Cfg.FileSettings.EnableFileAttachments = false
+
+ if data, err := readTestFile("test.png"); err != nil {
+ t.Fatal(err)
+ } else if _, err = Client.UploadPostAttachment(data, channel.Id, "test.png"); err == nil {
+ t.Fatal("should have errored")
+ }
+
// Wait a bit for files to ready
time.Sleep(2 * time.Second)
diff --git a/api4/file.go b/api4/file.go
index 6bd751a6798dd6c492f45a1c0ac370ab34880b4a..09132b9a1622967b7f8032c8d2564cf6fef3927e 100644
--- a/api4/file.go
+++ b/api4/file.go
@@ -33,9 +33,13 @@ func InitFile() {
}
func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) {
+ if !*utils.Cfg.FileSettings.EnableFileAttachments {
+ c.Err = model.NewAppError("uploadFile", "api.file.attachments.disabled.app_error", nil, "", http.StatusNotImplemented)
+ return
+ }
+
if r.ContentLength > *utils.Cfg.FileSettings.MaxFileSize {
- c.Err = model.NewLocAppError("uploadFile", "api.file.upload_file.too_large.app_error", nil, "")
- c.Err.StatusCode = http.StatusRequestEntityTooLarge
+ c.Err = model.NewAppError("uploadFile", "api.file.upload_file.too_large.app_error", nil, "", http.StatusRequestEntityTooLarge)
return
}
diff --git a/api4/file_test.go b/api4/file_test.go
index 9124e893b456825d8af8bf92457ef3b5841d1c58..e48aabffc754b52e1267364d1805790139bc2a5b 100644
--- a/api4/file_test.go
+++ b/api4/file_test.go
@@ -102,6 +102,15 @@ func TestUploadFile(t *testing.T) {
_, resp = th.SystemAdminClient.UploadFile(data, channel.Id, "test.png")
CheckNoError(t, resp)
+
+ enableFileAttachments := *utils.Cfg.FileSettings.EnableFileAttachments
+ defer func() {
+ *utils.Cfg.FileSettings.EnableFileAttachments = enableFileAttachments
+ }()
+ *utils.Cfg.FileSettings.EnableFileAttachments = false
+
+ _, resp = th.SystemAdminClient.UploadFile(data, channel.Id, "test.png")
+ CheckNotImplementedStatus(t, resp)
}
func TestGetFile(t *testing.T) {
diff --git a/app/file.go b/app/file.go
index c5e2982d46648989efcd5f4185fd4429fe4bdb70..ad58de623bd68b03d0d1878315e665be17fae4ac 100644
--- a/app/file.go
+++ b/app/file.go
@@ -84,7 +84,7 @@ func ReadFile(path string) ([]byte, *model.AppError) {
return f, nil
}
} else {
- return nil, model.NewLocAppError("ReadFile", "api.file.read_file.configured.app_error", nil, "")
+ return nil, model.NewAppError("ReadFile", "api.file.read_file.configured.app_error", nil, "", http.StatusNotImplemented)
}
}
diff --git a/config/config.json b/config/config.json
index 3111d3831dfee29b5e9ff7fa352b65c3ad3b8692..352fa0fbf669965c9b05aef372fed6390ef3d7ef 100644
--- a/config/config.json
+++ b/config/config.json
@@ -97,6 +97,7 @@
"Symbol": false
},
"FileSettings": {
+ "EnableFileAttachments": true,
"MaxFileSize": 52428800,
"DriverName": "local",
"Directory": "./data/",
diff --git a/i18n/en.json b/i18n/en.json
index 48491e3e9e95cce7f5c0d0ce6f3ad297791e0529..209e40437b49883b48936d6b3f9ad0b549056c8b 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -1051,7 +1051,11 @@
},
{
"id": "api.file.get_info_for_request.storage.app_error",
- "translation": "Unable to get info for file. Image storage is not configured."
+ "translation": "Unable to get info for file. File storage is not configured."
+ },
+ {
+ "id": "api.file.attachments.disabled.app_error",
+ "translation": "File attachments have been disabled on this server."
},
{
"id": "api.file.get_public_file_old.storage.app_error",
diff --git a/model/config.go b/model/config.go
index 9d651035b36de2ecc949ac1999ec1246c9eeb02f..3015b332410207e32e9449dd9c2692997deee9e6 100644
--- a/model/config.go
+++ b/model/config.go
@@ -214,6 +214,7 @@ type PasswordSettings struct {
}
type FileSettings struct {
+ EnableFileAttachments *bool
MaxFileSize *int64
DriverName string
Directory string
@@ -474,6 +475,11 @@ func (o *Config) SetDefaults() {
*o.FileSettings.AmazonS3SSL = true // Secure by default.
}
+ if o.FileSettings.EnableFileAttachments == nil {
+ o.FileSettings.EnableFileAttachments = new(bool)
+ *o.FileSettings.EnableFileAttachments = true
+ }
+
if o.FileSettings.MaxFileSize == nil {
o.FileSettings.MaxFileSize = new(int64)
*o.FileSettings.MaxFileSize = 52428800 // 50 MB
diff --git a/utils/config.go b/utils/config.go
index ea28cc912c685ed646cca9e995ce0e62bf1df8da..25d222f3a96195aa7872e676cc550fba0f46c00e 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -405,6 +405,7 @@ func getClientConfig(c *model.Config) map[string]string {
props["ReportAProblemLink"] = *c.SupportSettings.ReportAProblemLink
props["SupportEmail"] = *c.SupportSettings.SupportEmail
+ props["EnableFileAttachments"] = strconv.FormatBool(*c.FileSettings.EnableFileAttachments)
props["EnablePublicLink"] = strconv.FormatBool(c.FileSettings.EnablePublicLink)
props["ProfileHeight"] = fmt.Sprintf("%v", c.FileSettings.ProfileHeight)
props["ProfileWidth"] = fmt.Sprintf("%v", c.FileSettings.ProfileWidth)
diff --git a/webapp/actions/websocket_actions.jsx b/webapp/actions/websocket_actions.jsx
index c6de4264738d0417762c4808c860ad31baca629d..4d2b5a2b5ac3168f471521cdb7d8fdee0d8ffe80 100644
--- a/webapp/actions/websocket_actions.jsx
+++ b/webapp/actions/websocket_actions.jsx
@@ -35,6 +35,7 @@ import store from 'stores/redux_store.jsx';
const dispatch = store.dispatch;
const getState = store.getState;
import {viewChannel, getChannelAndMyMember, getChannelStats} from 'mattermost-redux/actions/channels';
+import {setServerVersion} from 'mattermost-redux/actions/general';
import {ChannelTypes} from 'mattermost-redux/action_types';
const MAX_WEBSOCKET_FAILS = 7;
@@ -390,7 +391,7 @@ function handleStatusChangedEvent(msg) {
function handleHelloEvent(msg) {
Client.serverVersion = msg.data.server_version;
- AsyncClient.checkVersion();
+ setServerVersion(msg.data.server_version)(dispatch, getState);
}
function handleWebrtc(msg) {
diff --git a/webapp/components/admin_console/storage_settings.jsx b/webapp/components/admin_console/storage_settings.jsx
index 3b634dc53f48b1338ee05bc9a5e3a5e47f86ab9a..1400b673c729cc7be4db779787a8f0e834bbd08f 100644
--- a/webapp/components/admin_console/storage_settings.jsx
+++ b/webapp/components/admin_console/storage_settings.jsx
@@ -25,6 +25,7 @@ export default class StorageSettings extends AdminSettings {
}
getConfigFromState(config) {
+ config.FileSettings.EnableFileAttachments = this.state.enableFileAttachments;
config.FileSettings.MaxFileSize = this.parseInt(this.state.maxFileSize) * 1024 * 1024;
config.FileSettings.DriverName = this.state.driverName;
config.FileSettings.Directory = this.state.directory;
@@ -39,6 +40,7 @@ export default class StorageSettings extends AdminSettings {
getStateFromConfig(config) {
return {
+ enableFileAttachments: config.FileSettings.EnableFileAttachments,
maxFileSize: config.FileSettings.MaxFileSize / 1024 / 1024,
driverName: config.FileSettings.DriverName,
directory: config.FileSettings.Directory,
@@ -199,6 +201,23 @@ export default class StorageSettings extends AdminSettings {
onChange={this.handleChange}
disabled={this.state.driverName !== DRIVER_S3}
/>
+