MM-28733 : Admin Advisor v2 (#15515)
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
7c905b0890
Коммит
f74b86ae95
@@ -6550,6 +6550,24 @@ func (s *OpenTracingLayerSystemStore) SaveOrUpdate(system *model.System) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerSystemStore) SaveOrUpdateWithWarnMetricHandling(system *model.System) error {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "SystemStore.SaveOrUpdateWithWarnMetricHandling")
|
||||
s.Root.Store.SetContext(newCtx)
|
||||
defer func() {
|
||||
s.Root.Store.SetContext(origCtx)
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
err := s.SystemStore.SaveOrUpdateWithWarnMetricHandling(system)
|
||||
if err != nil {
|
||||
span.LogFields(spanlog.Error(err))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerSystemStore) Update(system *model.System) error {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "SystemStore.Update")
|
||||
@@ -7759,6 +7777,24 @@ func (s *OpenTracingLayerUserStore) AnalyticsActiveCount(time int64, options mod
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerUserStore) AnalyticsGetExternalUsers(hostDomain string) (bool, *model.AppError) {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "UserStore.AnalyticsGetExternalUsers")
|
||||
s.Root.Store.SetContext(newCtx)
|
||||
defer func() {
|
||||
s.Root.Store.SetContext(origCtx)
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
result, err := s.UserStore.AnalyticsGetExternalUsers(hostDomain)
|
||||
if err != nil {
|
||||
span.LogFields(spanlog.Error(err))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerUserStore) AnalyticsGetGuestCount() (int64, *model.AppError) {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "UserStore.AnalyticsGetGuestCount")
|
||||
|
||||
@@ -6060,6 +6060,26 @@ func (s *RetryLayerSystemStore) SaveOrUpdate(system *model.System) error {
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerSystemStore) SaveOrUpdateWithWarnMetricHandling(system *model.System) error {
|
||||
|
||||
tries := 0
|
||||
for {
|
||||
err := s.SystemStore.SaveOrUpdateWithWarnMetricHandling(system)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if !isRepeatableError(err) {
|
||||
return err
|
||||
}
|
||||
tries++
|
||||
if tries >= 3 {
|
||||
err = errors.Wrap(err, "giving up after 3 consecutive repeatable transaction failures")
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerSystemStore) Update(system *model.System) error {
|
||||
|
||||
tries := 0
|
||||
@@ -7364,6 +7384,12 @@ func (s *RetryLayerUserStore) AnalyticsActiveCount(time int64, options model.Use
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerUserStore) AnalyticsGetExternalUsers(hostDomain string) (bool, *model.AppError) {
|
||||
|
||||
return s.UserStore.AnalyticsGetExternalUsers(hostDomain)
|
||||
|
||||
}
|
||||
|
||||
func (s *RetryLayerUserStore) AnalyticsGetGuestCount() (int64, *model.AppError) {
|
||||
|
||||
return s.UserStore.AnalyticsGetGuestCount()
|
||||
|
||||
@@ -6,9 +6,13 @@ package sqlstore
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
"github.com/mattermost/mattermost-server/v5/store"
|
||||
"github.com/mattermost/mattermost-server/v5/utils"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -52,6 +56,26 @@ func (s SqlSystemStore) SaveOrUpdate(system *model.System) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s SqlSystemStore) SaveOrUpdateWithWarnMetricHandling(system *model.System) error {
|
||||
if err := s.GetMaster().SelectOne(&model.System{}, "SELECT * FROM Systems WHERE Name = :Name", map[string]interface{}{"Name": system.Name}); err == nil {
|
||||
if _, err := s.GetMaster().Update(system); err != nil {
|
||||
return errors.Wrapf(err, "failed to update system property with name=%s", system.Name)
|
||||
}
|
||||
} else {
|
||||
if err := s.GetMaster().Insert(system); err != nil {
|
||||
return errors.Wrapf(err, "failed to save system property with name=%s", system.Name)
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasPrefix(system.Name, model.WARN_METRIC_STATUS_STORE_PREFIX) && (system.Value == model.WARN_METRIC_STATUS_RUNONCE || system.Value == model.WARN_METRIC_STATUS_LIMIT_REACHED) {
|
||||
if err := s.SaveOrUpdate(&model.System{Name: model.SYSTEM_WARN_METRIC_LAST_RUN_TIMESTAMP_KEY, Value: strconv.FormatInt(utils.MillisFromTime(time.Now()), 10)}); err != nil {
|
||||
return errors.Wrapf(err, "failed to save system property with name=%s", model.SYSTEM_WARN_METRIC_LAST_RUN_TIMESTAMP_KEY)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s SqlSystemStore) Update(system *model.System) error {
|
||||
if _, err := s.GetMaster().Update(system); err != nil {
|
||||
return errors.Wrapf(err, "failed to update system property with name=%s", system.Name)
|
||||
|
||||
@@ -1474,6 +1474,14 @@ func (us SqlUserStore) AnalyticsGetInactiveUsersCount() (int64, *model.AppError)
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (us SqlUserStore) AnalyticsGetExternalUsers(hostDomain string) (bool, *model.AppError) {
|
||||
count, err := us.GetReplica().SelectInt("SELECT COUNT(Id) FROM Users WHERE LOWER(Email) NOT LIKE :HostDomain", map[string]interface{}{"HostDomain": "%@" + strings.ToLower(hostDomain)})
|
||||
if err != nil {
|
||||
return false, model.NewAppError("SqlUserStore.AnalyticsGetExternalUsers", "store.sql_user.analytics_get_external_users.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
return count > 0, nil
|
||||
}
|
||||
|
||||
func (us SqlUserStore) AnalyticsGetGuestCount() (int64, *model.AppError) {
|
||||
count, err := us.GetReplica().SelectInt("SELECT count(*) FROM Users WHERE Roles LIKE :Roles and DeleteAt = 0", map[string]interface{}{"Roles": "%system_guest%"})
|
||||
if err != nil {
|
||||
|
||||
@@ -339,6 +339,7 @@ type UserStore interface {
|
||||
SearchWithoutTeam(term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
||||
SearchInGroup(groupID string, term string, options *model.UserSearchOptions) ([]*model.User, *model.AppError)
|
||||
AnalyticsGetInactiveUsersCount() (int64, *model.AppError)
|
||||
AnalyticsGetExternalUsers(hostDomain string) (bool, *model.AppError)
|
||||
AnalyticsGetSystemAdminCount() (int64, *model.AppError)
|
||||
AnalyticsGetGuestCount() (int64, *model.AppError)
|
||||
GetProfilesNotInTeam(teamId string, groupConstrained bool, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError)
|
||||
@@ -438,6 +439,7 @@ type SystemStore interface {
|
||||
GetByName(name string) (*model.System, error)
|
||||
PermanentDeleteByName(name string) (*model.System, error)
|
||||
InsertIfExists(system *model.System) (*model.System, error)
|
||||
SaveOrUpdateWithWarnMetricHandling(system *model.System) error
|
||||
}
|
||||
|
||||
type WebhookStore interface {
|
||||
|
||||
@@ -134,6 +134,20 @@ func (_m *SystemStore) SaveOrUpdate(system *model.System) error {
|
||||
return r0
|
||||
}
|
||||
|
||||
// SaveOrUpdateWithWarnMetricHandling provides a mock function with given fields: system
|
||||
func (_m *SystemStore) SaveOrUpdateWithWarnMetricHandling(system *model.System) error {
|
||||
ret := _m.Called(system)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(*model.System) error); ok {
|
||||
r0 = rf(system)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// Update provides a mock function with given fields: system
|
||||
func (_m *SystemStore) Update(system *model.System) error {
|
||||
ret := _m.Called(system)
|
||||
|
||||
@@ -38,6 +38,29 @@ func (_m *UserStore) AnalyticsActiveCount(time int64, options model.UserCountOpt
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AnalyticsGetExternalUsers provides a mock function with given fields: hostDomain
|
||||
func (_m *UserStore) AnalyticsGetExternalUsers(hostDomain string) (bool, *model.AppError) {
|
||||
ret := _m.Called(hostDomain)
|
||||
|
||||
var r0 bool
|
||||
if rf, ok := ret.Get(0).(func(string) bool); ok {
|
||||
r0 = rf(hostDomain)
|
||||
} else {
|
||||
r0 = ret.Get(0).(bool)
|
||||
}
|
||||
|
||||
var r1 *model.AppError
|
||||
if rf, ok := ret.Get(1).(func(string) *model.AppError); ok {
|
||||
r1 = rf(hostDomain)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).(*model.AppError)
|
||||
}
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// AnalyticsGetGuestCount provides a mock function with given fields:
|
||||
func (_m *UserStore) AnalyticsGetGuestCount() (int64, *model.AppError) {
|
||||
ret := _m.Called()
|
||||
|
||||
@@ -21,6 +21,7 @@ func TestSystemStore(t *testing.T, ss store.Store) {
|
||||
t.Run("InsertIfExists", func(t *testing.T) {
|
||||
testInsertIfExists(t, ss)
|
||||
})
|
||||
t.Run("SaveOrUpdateWithWarnMetricHandling", func(t *testing.T) { testSystemStoreSaveOrUpdateWithWarnMetricHandling(t, ss) })
|
||||
}
|
||||
|
||||
func testSystemStore(t *testing.T, ss store.Store) {
|
||||
@@ -55,6 +56,33 @@ func testSystemStoreSaveOrUpdate(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
func testSystemStoreSaveOrUpdateWithWarnMetricHandling(t *testing.T, ss store.Store) {
|
||||
system := &model.System{Name: model.NewId(), Value: "value"}
|
||||
|
||||
err := ss.System().SaveOrUpdateWithWarnMetricHandling(system)
|
||||
require.Nil(t, err)
|
||||
|
||||
_, err = ss.System().GetByName(model.SYSTEM_WARN_METRIC_LAST_RUN_TIMESTAMP_KEY)
|
||||
assert.NotNil(t, err)
|
||||
|
||||
system.Name = "warn_metric_number_of_active_users_100"
|
||||
system.Value = model.WARN_METRIC_STATUS_RUNONCE
|
||||
err = ss.System().SaveOrUpdateWithWarnMetricHandling(system)
|
||||
require.Nil(t, err)
|
||||
|
||||
val1, nerr := ss.System().GetByName(model.SYSTEM_WARN_METRIC_LAST_RUN_TIMESTAMP_KEY)
|
||||
assert.Nil(t, nerr)
|
||||
|
||||
system.Name = "warn_metric_number_of_active_users_100"
|
||||
system.Value = model.WARN_METRIC_STATUS_ACK
|
||||
err = ss.System().SaveOrUpdateWithWarnMetricHandling(system)
|
||||
require.Nil(t, err)
|
||||
|
||||
val2, nerr := ss.System().GetByName(model.SYSTEM_WARN_METRIC_LAST_RUN_TIMESTAMP_KEY)
|
||||
assert.Nil(t, nerr)
|
||||
assert.Equal(t, val1, val2)
|
||||
}
|
||||
|
||||
func testSystemStorePermanentDeleteByName(t *testing.T, ss store.Store) {
|
||||
s1 := &model.System{Name: model.NewId(), Value: "value"}
|
||||
s2 := &model.System{Name: model.NewId(), Value: "value"}
|
||||
|
||||
@@ -39,6 +39,7 @@ func TestUserStore(t *testing.T, ss store.Store, s SqlSupplier) {
|
||||
t.Run("AnalyticsGetInactiveUsersCount", func(t *testing.T) { testUserStoreAnalyticsGetInactiveUsersCount(t, ss) })
|
||||
t.Run("AnalyticsGetSystemAdminCount", func(t *testing.T) { testUserStoreAnalyticsGetSystemAdminCount(t, ss) })
|
||||
t.Run("AnalyticsGetGuestCount", func(t *testing.T) { testUserStoreAnalyticsGetGuestCount(t, ss) })
|
||||
t.Run("AnalyticsGetExternalUsers", func(t *testing.T) { testUserStoreAnalyticsGetExternalUsers(t, ss) })
|
||||
t.Run("Save", func(t *testing.T) { testUserStoreSave(t, ss) })
|
||||
t.Run("Update", func(t *testing.T) { testUserStoreUpdate(t, ss) })
|
||||
t.Run("UpdateUpdateAt", func(t *testing.T) { testUserStoreUpdateUpdateAt(t, ss) })
|
||||
@@ -3916,6 +3917,44 @@ func testUserStoreAnalyticsGetGuestCount(t *testing.T, ss store.Store) {
|
||||
require.Equal(t, countBefore+1, result, "Did not get the expected number of guests.")
|
||||
}
|
||||
|
||||
func testUserStoreAnalyticsGetExternalUsers(t *testing.T, ss store.Store) {
|
||||
localHostDomain := "mattermost.com"
|
||||
result, err := ss.User().AnalyticsGetExternalUsers(localHostDomain)
|
||||
require.Nil(t, err)
|
||||
assert.False(t, result)
|
||||
|
||||
u1 := model.User{}
|
||||
u1.Email = "a@mattermost.com"
|
||||
u1.Username = model.NewId()
|
||||
u1.Roles = "system_user system_admin"
|
||||
|
||||
u2 := model.User{}
|
||||
u2.Email = "b@example.com"
|
||||
u2.Username = model.NewId()
|
||||
u2.Roles = "system_user"
|
||||
|
||||
u3 := model.User{}
|
||||
u3.Email = "c@test.com"
|
||||
u3.Username = model.NewId()
|
||||
u3.Roles = "system_guest"
|
||||
|
||||
_, err = ss.User().Save(&u1)
|
||||
require.Nil(t, err, "couldn't save user")
|
||||
defer func() { require.Nil(t, ss.User().PermanentDelete(u1.Id)) }()
|
||||
|
||||
_, err = ss.User().Save(&u2)
|
||||
require.Nil(t, err, "couldn't save user")
|
||||
defer func() { require.Nil(t, ss.User().PermanentDelete(u2.Id)) }()
|
||||
|
||||
_, err = ss.User().Save(&u3)
|
||||
require.Nil(t, err, "couldn't save user")
|
||||
defer func() { require.Nil(t, ss.User().PermanentDelete(u3.Id)) }()
|
||||
|
||||
result, err = ss.User().AnalyticsGetExternalUsers(localHostDomain)
|
||||
require.Nil(t, err)
|
||||
assert.True(t, result)
|
||||
}
|
||||
|
||||
func testUserStoreGetProfilesNotInTeam(t *testing.T, ss store.Store) {
|
||||
team, err := ss.Team().Save(&model.Team{
|
||||
DisplayName: "Team",
|
||||
|
||||
@@ -5920,6 +5920,22 @@ func (s *TimerLayerSystemStore) SaveOrUpdate(system *model.System) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *TimerLayerSystemStore) SaveOrUpdateWithWarnMetricHandling(system *model.System) error {
|
||||
start := timemodule.Now()
|
||||
|
||||
err := s.SystemStore.SaveOrUpdateWithWarnMetricHandling(system)
|
||||
|
||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||
if s.Root.Metrics != nil {
|
||||
success := "false"
|
||||
if err == nil {
|
||||
success = "true"
|
||||
}
|
||||
s.Root.Metrics.ObserveStoreMethodDuration("SystemStore.SaveOrUpdateWithWarnMetricHandling", success, elapsed)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *TimerLayerSystemStore) Update(system *model.System) error {
|
||||
start := timemodule.Now()
|
||||
|
||||
@@ -7005,6 +7021,22 @@ func (s *TimerLayerUserStore) AnalyticsActiveCount(time int64, options model.Use
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerUserStore) AnalyticsGetExternalUsers(hostDomain string) (bool, *model.AppError) {
|
||||
start := timemodule.Now()
|
||||
|
||||
result, err := s.UserStore.AnalyticsGetExternalUsers(hostDomain)
|
||||
|
||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||
if s.Root.Metrics != nil {
|
||||
success := "false"
|
||||
if err == nil {
|
||||
success = "true"
|
||||
}
|
||||
s.Root.Metrics.ObserveStoreMethodDuration("UserStore.AnalyticsGetExternalUsers", success, elapsed)
|
||||
}
|
||||
return result, err
|
||||
}
|
||||
|
||||
func (s *TimerLayerUserStore) AnalyticsGetGuestCount() (int64, *model.AppError) {
|
||||
start := timemodule.Now()
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user