summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/admin.go2
-rw-r--r--config/config.json6
-rw-r--r--docker/1.1/config_docker.json6
-rw-r--r--docker/dev/config_docker.json6
-rw-r--r--docker/local/config_docker.json6
-rw-r--r--mattermost.go38
-rw-r--r--model/config.go13
-rw-r--r--store/sql_user_store.go21
-rw-r--r--store/sql_user_store_test.go20
-rw-r--r--store/store.go1
-rw-r--r--utils/config.go2
-rw-r--r--utils/diagnostic.go17
-rw-r--r--web/react/components/admin_console/privacy_settings.jsx34
-rw-r--r--web/react/components/admin_console/service_settings.jsx37
14 files changed, 135 insertions, 74 deletions
diff --git a/api/admin.go b/api/admin.go
index 2167868e0..cd1e5d2de 100644
--- a/api/admin.go
+++ b/api/admin.go
@@ -104,6 +104,8 @@ func saveConfig(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
+ cfg.SetDefaults()
+
if err := cfg.IsValid(); err != nil {
c.Err = err
return
diff --git a/config/config.json b/config/config.json
index 919737da7..8ef151350 100644
--- a/config/config.json
+++ b/config/config.json
@@ -8,7 +8,8 @@
"EnableIncomingWebhooks": true,
"EnablePostUsernameOverride": false,
"EnablePostIconOverride": false,
- "EnableTesting": false
+ "EnableTesting": false,
+ "EnableSecurityFixAlert": true
},
"TeamSettings": {
"SiteName": "Mattermost",
@@ -77,8 +78,7 @@
},
"PrivacySettings": {
"ShowEmailAddress": true,
- "ShowFullName": true,
- "EnableSecurityFixAlert": true
+ "ShowFullName": true
},
"GitLabSettings": {
"Enable": false,
diff --git a/docker/1.1/config_docker.json b/docker/1.1/config_docker.json
index ab5b0a7be..653b6ffd7 100644
--- a/docker/1.1/config_docker.json
+++ b/docker/1.1/config_docker.json
@@ -8,7 +8,8 @@
"EnableIncomingWebhooks": true,
"EnablePostUsernameOverride": false,
"EnablePostIconOverride": false,
- "EnableTesting": false
+ "EnableTesting": false,
+ "EnableSecurityFixAlert": true
},
"TeamSettings": {
"SiteName": "Mattermost",
@@ -77,8 +78,7 @@
},
"PrivacySettings": {
"ShowEmailAddress": true,
- "ShowFullName": true,
- "EnableSecurityFixAlert": true
+ "ShowFullName": true
},
"GitLabSettings": {
"Enable": false,
diff --git a/docker/dev/config_docker.json b/docker/dev/config_docker.json
index ab5b0a7be..653b6ffd7 100644
--- a/docker/dev/config_docker.json
+++ b/docker/dev/config_docker.json
@@ -8,7 +8,8 @@
"EnableIncomingWebhooks": true,
"EnablePostUsernameOverride": false,
"EnablePostIconOverride": false,
- "EnableTesting": false
+ "EnableTesting": false,
+ "EnableSecurityFixAlert": true
},
"TeamSettings": {
"SiteName": "Mattermost",
@@ -77,8 +78,7 @@
},
"PrivacySettings": {
"ShowEmailAddress": true,
- "ShowFullName": true,
- "EnableSecurityFixAlert": true
+ "ShowFullName": true
},
"GitLabSettings": {
"Enable": false,
diff --git a/docker/local/config_docker.json b/docker/local/config_docker.json
index ab5b0a7be..653b6ffd7 100644
--- a/docker/local/config_docker.json
+++ b/docker/local/config_docker.json
@@ -8,7 +8,8 @@
"EnableIncomingWebhooks": true,
"EnablePostUsernameOverride": false,
"EnablePostIconOverride": false,
- "EnableTesting": false
+ "EnableTesting": false,
+ "EnableSecurityFixAlert": true
},
"TeamSettings": {
"SiteName": "Mattermost",
@@ -77,8 +78,7 @@
},
"PrivacySettings": {
"ShowEmailAddress": true,
- "ShowFullName": true,
- "EnableSecurityFixAlert": true
+ "ShowFullName": true
},
"GitLabSettings": {
"Enable": false,
diff --git a/mattermost.go b/mattermost.go
index 6c0f0a1bf..b8a44d26e 100644
--- a/mattermost.go
+++ b/mattermost.go
@@ -81,28 +81,28 @@ func main() {
func securityAndDiagnosticsJob() {
go func() {
for {
- if utils.Cfg.PrivacySettings.EnableSecurityFixAlert && model.IsOfficalBuild() {
+ if *utils.Cfg.ServiceSettings.EnableSecurityFixAlert { // && model.IsOfficalBuild() {
if result := <-api.Srv.Store.System().Get(); result.Err == nil {
props := result.Data.(model.StringMap)
lastSecurityTime, _ := strconv.ParseInt(props["LastSecurityTime"], 10, 0)
currentTime := model.GetMillis()
- id := props["DiagnosticId"]
- if len(id) == 0 {
- id = model.NewId()
- systemId := &model.System{Name: "DiagnosticId", Value: id}
- <-api.Srv.Store.System().Save(systemId)
- }
+ if (currentTime - lastSecurityTime) > 1000*60*60*24*1 {
+ l4g.Debug("Checking for security update from Mattermost")
- v := url.Values{}
- v.Set(utils.PROP_DIAGNOSTIC_ID, id)
- v.Set(utils.PROP_DIAGNOSTIC_BUILD, model.CurrentVersion+"."+model.BuildNumber)
- v.Set(utils.PROP_DIAGNOSTIC_DATABASE, utils.Cfg.SqlSettings.DriverName)
- v.Set(utils.PROP_DIAGNOSTIC_OS, runtime.GOOS)
- v.Set(utils.PROP_DIAGNOSTIC_CATEGORY, utils.VAL_DIAGNOSTIC_CATEGORY_DEFAULT)
+ id := props["DiagnosticId"]
+ if len(id) == 0 {
+ id = model.NewId()
+ systemId := &model.System{Name: "DiagnosticId", Value: id}
+ <-api.Srv.Store.System().Save(systemId)
+ }
- if (currentTime - lastSecurityTime) > 1000*60*60*24*1 {
- l4g.Info("Checking for security update from Mattermost")
+ v := url.Values{}
+ v.Set(utils.PROP_DIAGNOSTIC_ID, id)
+ v.Set(utils.PROP_DIAGNOSTIC_BUILD, model.CurrentVersion+"."+model.BuildNumber)
+ v.Set(utils.PROP_DIAGNOSTIC_DATABASE, utils.Cfg.SqlSettings.DriverName)
+ v.Set(utils.PROP_DIAGNOSTIC_OS, runtime.GOOS)
+ v.Set(utils.PROP_DIAGNOSTIC_CATEGORY, utils.VAL_DIAGNOSTIC_CATEGORY_DEFAULT)
systemSecurityLastTime := &model.System{Name: "LastSecurityTime", Value: strconv.FormatInt(currentTime, 10)}
if lastSecurityTime == 0 {
@@ -111,6 +111,14 @@ func securityAndDiagnosticsJob() {
<-api.Srv.Store.System().Update(systemSecurityLastTime)
}
+ if ucr := <-api.Srv.Store.User().GetTotalUsersCount(); ucr.Err == nil {
+ v.Set(utils.PROP_DIAGNOSTIC_USER_COUNT, strconv.FormatInt(ucr.Data.(int64), 10))
+ }
+
+ if ucr := <-api.Srv.Store.User().GetTotalActiveUsersCount(); ucr.Err == nil {
+ v.Set(utils.PROP_DIAGNOSTIC_ACTIVE_USER_COUNT, strconv.FormatInt(ucr.Data.(int64), 10))
+ }
+
res, err := http.Get(utils.DIAGNOSTIC_URL + "/security?" + v.Encode())
if err != nil {
l4g.Error("Failed to get security update information from Mattermost.")
diff --git a/model/config.go b/model/config.go
index e4b99ad4a..8a11b7bb7 100644
--- a/model/config.go
+++ b/model/config.go
@@ -32,6 +32,7 @@ type ServiceSettings struct {
EnablePostUsernameOverride bool
EnablePostIconOverride bool
EnableTesting bool
+ EnableSecurityFixAlert *bool
}
type SSOSettings struct {
@@ -110,9 +111,8 @@ type RateLimitSettings struct {
}
type PrivacySettings struct {
- ShowEmailAddress bool
- ShowFullName bool
- EnableSecurityFixAlert bool
+ ShowEmailAddress bool
+ ShowFullName bool
}
type TeamSettings struct {
@@ -163,6 +163,13 @@ func ConfigFromJson(data io.Reader) *Config {
}
}
+func (o *Config) SetDefaults() {
+ if o.ServiceSettings.EnableSecurityFixAlert == nil {
+ o.ServiceSettings.EnableSecurityFixAlert = new(bool)
+ *o.ServiceSettings.EnableSecurityFixAlert = true
+ }
+}
+
func (o *Config) IsValid() *AppError {
if o.ServiceSettings.MaximumLoginAttempts <= 0 {
diff --git a/store/sql_user_store.go b/store/sql_user_store.go
index 011acd7e4..dc6b07a16 100644
--- a/store/sql_user_store.go
+++ b/store/sql_user_store.go
@@ -530,3 +530,24 @@ func (us SqlUserStore) GetTotalUsersCount() StoreChannel {
return storeChannel
}
+
+func (us SqlUserStore) GetTotalActiveUsersCount() StoreChannel {
+ storeChannel := make(StoreChannel)
+
+ go func() {
+ result := StoreResult{}
+
+ time := model.GetMillis() - (1000 * 60 * 60 * 12)
+
+ if count, err := us.GetReplica().SelectInt("SELECT COUNT(Id) FROM Users WHERE LastActivityAt > :Time", map[string]interface{}{"Time": time}); err != nil {
+ result.Err = model.NewAppError("SqlUserStore.GetTotalActiveUsersCount", "We could not count the users", err.Error())
+ } else {
+ result.Data = count
+ }
+
+ storeChannel <- result
+ close(storeChannel)
+ }()
+
+ return storeChannel
+}
diff --git a/store/sql_user_store_test.go b/store/sql_user_store_test.go
index be21c8bd2..874baf634 100644
--- a/store/sql_user_store_test.go
+++ b/store/sql_user_store_test.go
@@ -206,7 +206,7 @@ func TestUserStoreGet(t *testing.T) {
}
}
-func TestUserCountt(t *testing.T) {
+func TestUserCount(t *testing.T) {
Setup()
u1 := model.User{}
@@ -224,6 +224,24 @@ func TestUserCountt(t *testing.T) {
}
}
+func TestActiveUserCount(t *testing.T) {
+ Setup()
+
+ u1 := model.User{}
+ u1.TeamId = model.NewId()
+ u1.Email = model.NewId()
+ Must(store.User().Save(&u1))
+
+ if result := <-store.User().GetTotalActiveUsersCount(); result.Err != nil {
+ t.Fatal(result.Err)
+ } else {
+ count := result.Data.(int64)
+ if count <= 0 {
+ t.Fatal()
+ }
+ }
+}
+
func TestUserStoreGetProfiles(t *testing.T) {
Setup()
diff --git a/store/store.go b/store/store.go
index 1c4d08e36..e539bc98a 100644
--- a/store/store.go
+++ b/store/store.go
@@ -104,6 +104,7 @@ type UserStore interface {
UpdateFailedPasswordAttempts(userId string, attempts int) StoreChannel
GetForExport(teamId string) StoreChannel
GetTotalUsersCount() StoreChannel
+ GetTotalActiveUsersCount() StoreChannel
GetSystemAdminProfiles() StoreChannel
}
diff --git a/utils/config.go b/utils/config.go
index 44ee14a6e..2c6f30bf0 100644
--- a/utils/config.go
+++ b/utils/config.go
@@ -150,6 +150,8 @@ func LoadConfig(fileName string) {
CfgFileName = fileName
}
+ config.SetDefaults()
+
if err := config.IsValid(); err != nil {
panic("Error validating config file=" + fileName + ", err=" + err.Message)
}
diff --git a/utils/diagnostic.go b/utils/diagnostic.go
index da02e771b..7d13e0e52 100644
--- a/utils/diagnostic.go
+++ b/utils/diagnostic.go
@@ -13,17 +13,18 @@ import (
const (
DIAGNOSTIC_URL = "https://d7zmvsa9e04kk.cloudfront.net"
- PROP_DIAGNOSTIC_ID = "id"
- PROP_DIAGNOSTIC_CATEGORY = "c"
- VAL_DIAGNOSTIC_CATEGORY_DEFAULT = "d"
- PROP_DIAGNOSTIC_BUILD = "b"
- PROP_DIAGNOSTIC_DATABASE = "db"
- PROP_DIAGNOSTIC_OS = "os"
- PROP_DIAGNOSTIC_USER_COUNT = "uc"
+ PROP_DIAGNOSTIC_ID = "id"
+ PROP_DIAGNOSTIC_CATEGORY = "c"
+ VAL_DIAGNOSTIC_CATEGORY_DEFAULT = "d"
+ PROP_DIAGNOSTIC_BUILD = "b"
+ PROP_DIAGNOSTIC_DATABASE = "db"
+ PROP_DIAGNOSTIC_OS = "os"
+ PROP_DIAGNOSTIC_USER_COUNT = "uc"
+ PROP_DIAGNOSTIC_ACTIVE_USER_COUNT = "auc"
)
func SendDiagnostic(values url.Values) {
- if Cfg.PrivacySettings.EnableSecurityFixAlert && model.IsOfficalBuild() {
+ if *Cfg.ServiceSettings.EnableSecurityFixAlert && model.IsOfficalBuild() {
res, err := http.Get(DIAGNOSTIC_URL + "/i?" + values.Encode())
if err != nil {
diff --git a/web/react/components/admin_console/privacy_settings.jsx b/web/react/components/admin_console/privacy_settings.jsx
index a32ca3136..70ec04f4a 100644
--- a/web/react/components/admin_console/privacy_settings.jsx
+++ b/web/react/components/admin_console/privacy_settings.jsx
@@ -30,7 +30,6 @@ export default class PrivacySettings extends React.Component {
var config = this.props.config;
config.PrivacySettings.ShowEmailAddress = React.findDOMNode(this.refs.ShowEmailAddress).checked;
config.PrivacySettings.ShowFullName = React.findDOMNode(this.refs.ShowFullName).checked;
- config.PrivacySettings.EnableSecurityFixAlert = React.findDOMNode(this.refs.EnableSecurityFixAlert).checked;
Client.saveConfig(
config,
@@ -138,39 +137,6 @@ export default class PrivacySettings extends React.Component {
</div>
<div className='form-group'>
- <label
- className='control-label col-sm-4'
- htmlFor='EnableSecurityFixAlert'
- >
- {'Send Error and Diagnostic: '}
- </label>
- <div className='col-sm-8'>
- <label className='radio-inline'>
- <input
- type='radio'
- name='EnableSecurityFixAlert'
- value='true'
- ref='EnableSecurityFixAlert'
- defaultChecked={this.props.config.PrivacySettings.EnableSecurityFixAlert}
- onChange={this.handleChange}
- />
- {'true'}
- </label>
- <label className='radio-inline'>
- <input
- type='radio'
- name='EnableSecurityFixAlert'
- value='false'
- defaultChecked={!this.props.config.PrivacySettings.EnableSecurityFixAlert}
- onChange={this.handleChange}
- />
- {'false'}
- </label>
- <p className='help-text'>{'When true, System Administrators are notified by email if a relevant security fix alert has been announced in the last 12 hours. Requires email to be enabled.'}</p>
- </div>
- </div>
-
- <div className='form-group'>
<div className='col-sm-12'>
{serverError}
<button
diff --git a/web/react/components/admin_console/service_settings.jsx b/web/react/components/admin_console/service_settings.jsx
index 3968d9820..f29d62646 100644
--- a/web/react/components/admin_console/service_settings.jsx
+++ b/web/react/components/admin_console/service_settings.jsx
@@ -35,11 +35,13 @@ export default class ServiceSettings extends React.Component {
config.ServiceSettings.SegmentDeveloperKey = React.findDOMNode(this.refs.SegmentDeveloperKey).value.trim();
config.ServiceSettings.GoogleDeveloperKey = React.findDOMNode(this.refs.GoogleDeveloperKey).value.trim();
- //config.ServiceSettings.EnableOAuthServiceProvider = React.findDOMNode(this.refs.EnableOAuthServiceProvider).checked;
config.ServiceSettings.EnableIncomingWebhooks = React.findDOMNode(this.refs.EnableIncomingWebhooks).checked;
config.ServiceSettings.EnablePostUsernameOverride = React.findDOMNode(this.refs.EnablePostUsernameOverride).checked;
config.ServiceSettings.EnablePostIconOverride = React.findDOMNode(this.refs.EnablePostIconOverride).checked;
config.ServiceSettings.EnableTesting = React.findDOMNode(this.refs.EnableTesting).checked;
+ config.ServiceSettings.EnableSecurityFixAlert = React.findDOMNode(this.refs.EnableSecurityFixAlert).checked;
+
+ //config.ServiceSettings.EnableOAuthServiceProvider = React.findDOMNode(this.refs.EnableOAuthServiceProvider).checked;
var MaximumLoginAttempts = 10;
if (!isNaN(parseInt(React.findDOMNode(this.refs.MaximumLoginAttempts).value, 10))) {
@@ -305,6 +307,39 @@ export default class ServiceSettings extends React.Component {
</div>
<div className='form-group'>
+ <label
+ className='control-label col-sm-4'
+ htmlFor='EnableSecurityFixAlert'
+ >
+ {'Enable Security Alerts: '}
+ </label>
+ <div className='col-sm-8'>
+ <label className='radio-inline'>
+ <input
+ type='radio'
+ name='EnableSecurityFixAlert'
+ value='true'
+ ref='EnableSecurityFixAlert'
+ defaultChecked={this.props.config.ServiceSettings.EnableSecurityFixAlert}
+ onChange={this.handleChange}
+ />
+ {'true'}
+ </label>
+ <label className='radio-inline'>
+ <input
+ type='radio'
+ name='EnableSecurityFixAlert'
+ value='false'
+ defaultChecked={!this.props.config.ServiceSettings.EnableSecurityFixAlert}
+ onChange={this.handleChange}
+ />
+ {'false'}
+ </label>
+ <p className='help-text'>{'When true, System Administrators are notified by email if a relevant security fix alert has been announced in the last 12 hours. Requires email to be enabled.'}</p>
+ </div>
+ </div>
+
+ <div className='form-group'>
<div className='col-sm-12'>
{serverError}
<button