PLT-586 fixing issues with security alert
Этот коммит содержится в:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
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)
|
||||
|
||||
if (currentTime - lastSecurityTime) > 1000*60*60*24*1 {
|
||||
l4g.Info("Checking for security update from Mattermost")
|
||||
l4g.Debug("Checking for security update from Mattermost")
|
||||
|
||||
id := props["DiagnosticId"]
|
||||
if len(id) == 0 {
|
||||
id = model.NewId()
|
||||
systemId := &model.System{Name: "DiagnosticId", Value: id}
|
||||
<-api.Srv.Store.System().Save(systemId)
|
||||
}
|
||||
|
||||
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.")
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -104,6 +104,7 @@ type UserStore interface {
|
||||
UpdateFailedPasswordAttempts(userId string, attempts int) StoreChannel
|
||||
GetForExport(teamId string) StoreChannel
|
||||
GetTotalUsersCount() StoreChannel
|
||||
GetTotalActiveUsersCount() StoreChannel
|
||||
GetSystemAdminProfiles() StoreChannel
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
@@ -137,39 +136,6 @@ export default class PrivacySettings extends React.Component {
|
||||
</div>
|
||||
</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}
|
||||
|
||||
@@ -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))) {
|
||||
@@ -304,6 +306,39 @@ export default class ServiceSettings extends React.Component {
|
||||
</div>
|
||||
</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}
|
||||
|
||||
Ссылка в новой задаче
Block a user