MM-24037 Adding getKnowUsers API endpoint (#14332)

* Adding getKnowUsers API endpoint

* Adding i18n strings

* Fixing golint errors

* Adding doc strings

* Remove debug line

* Updating app_iface

* Fixing gofmt
Этот коммит содержится в:
Jesús Espino
2020-04-28 12:52:43 +02:00
коммит произвёл GitHub
родитель d3b36e3455
Коммит 224b72c61e
13 изменённых файлов: 373 добавлений и 0 удалений

Просмотреть файл

@@ -7641,6 +7641,24 @@ func (s *OpenTracingLayerUserStore) GetForLogin(loginId string, allowSignInWithU
return resultVar0, resultVar1
}
func (s *OpenTracingLayerUserStore) GetKnownUsers(userID string) ([]string, *model.AppError) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "UserStore.GetKnownUsers")
s.Root.Store.SetContext(newCtx)
defer func() {
s.Root.Store.SetContext(origCtx)
}()
defer span.Finish()
resultVar0, resultVar1 := s.UserStore.GetKnownUsers(userID)
if resultVar1 != nil {
span.LogFields(spanlog.Error(resultVar1))
ext.Error.Set(span, true)
}
return resultVar0, resultVar1
}
func (s *OpenTracingLayerUserStore) GetNewUsersForTeam(teamId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
origCtx := s.Root.Store.Context()
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "UserStore.GetNewUsersForTeam")

Просмотреть файл

@@ -1770,3 +1770,23 @@ func (us SqlUserStore) AutocompleteUsersInChannel(teamId, channelId, term string
autocomplete.OutOfChannel = users
return autocomplete, nil
}
// GetKnownUsers returns the list of user ids of users with any direct
// relationship with a user. That means any user sharing any channel, including
// direct and group channels.
func (us SqlUserStore) GetKnownUsers(userId string) ([]string, *model.AppError) {
var userIds []string
usersQuery, args, _ := us.getQueryBuilder().
Select("DISTINCT ocm.UserId").
From("ChannelMembers AS cm").
Join("ChannelMembers AS ocm ON ocm.ChannelId = cm.ChannelId").
Where(sq.NotEq{"ocm.UserId": userId}).
Where(sq.Eq{"cm.UserId": userId}).
ToSql()
_, err := us.GetSearchReplica().Select(&userIds, usersQuery, args...)
if err != nil {
return nil, model.NewAppError("SqlUserStore.GetKnownUsers", "store.sql_user.get_known_users.get_users.app_error", nil, err.Error(), http.StatusInternalServerError)
}
return userIds, nil
}

Просмотреть файл

@@ -332,6 +332,7 @@ type UserStore interface {
DemoteUserToGuest(userID string) *model.AppError
DeactivateGuests() ([]string, *model.AppError)
AutocompleteUsersInChannel(teamId, channelId, term string, options *model.UserSearchOptions) (*model.UserAutocompleteInChannel, *model.AppError)
GetKnownUsers(userID string) ([]string, *model.AppError)
}
type BotStore interface {

Просмотреть файл

@@ -582,6 +582,31 @@ func (_m *UserStore) GetForLogin(loginId string, allowSignInWithUsername bool, a
return r0, r1
}
// GetKnownUsers provides a mock function with given fields: userID
func (_m *UserStore) GetKnownUsers(userID string) ([]string, *model.AppError) {
ret := _m.Called(userID)
var r0 []string
if rf, ok := ret.Get(0).(func(string) []string); ok {
r0 = rf(userID)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]string)
}
}
var r1 *model.AppError
if rf, ok := ret.Get(1).(func(string) *model.AppError); ok {
r1 = rf(userID)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
}
}
return r0, r1
}
// GetNewUsersForTeam provides a mock function with given fields: teamId, offset, limit, viewRestrictions
func (_m *UserStore) GetNewUsersForTeam(teamId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
ret := _m.Called(teamId, offset, limit, viewRestrictions)

Просмотреть файл

@@ -82,6 +82,7 @@ func TestUserStore(t *testing.T, ss store.Store, s SqlSupplier) {
t.Run("DemoteUserToGuest", func(t *testing.T) { testUserStoreDemoteUserToGuest(t, ss) })
t.Run("DeactivateGuests", func(t *testing.T) { testDeactivateGuests(t, ss) })
t.Run("ResetLastPictureUpdate", func(t *testing.T) { testUserStoreResetLastPictureUpdate(t, ss) })
t.Run("GetKnownUsers", func(t *testing.T) { testGetKnownUsers(t, ss) })
}
func testUserStoreSave(t *testing.T, ss store.Store) {
@@ -4624,3 +4625,134 @@ func testUserStoreResetLastPictureUpdate(t *testing.T, ss store.Store) {
assert.True(t, user2.UpdateAt > user.UpdateAt)
assert.Zero(t, user2.LastPictureUpdate)
}
func testGetKnownUsers(t *testing.T, ss store.Store) {
teamId := model.NewId()
u1, err := ss.User().Save(&model.User{
Email: MakeEmail(),
Username: "u1" + model.NewId(),
})
require.Nil(t, err)
defer func() { require.Nil(t, ss.User().PermanentDelete(u1.Id)) }()
_, err = ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u1.Id}, -1)
require.Nil(t, err)
u2, err := ss.User().Save(&model.User{
Email: MakeEmail(),
Username: "u2" + model.NewId(),
})
require.Nil(t, err)
defer func() { require.Nil(t, ss.User().PermanentDelete(u2.Id)) }()
_, err = ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u2.Id}, -1)
require.Nil(t, err)
u3, err := ss.User().Save(&model.User{
Email: MakeEmail(),
Username: "u3" + model.NewId(),
})
require.Nil(t, err)
defer func() { require.Nil(t, ss.User().PermanentDelete(u3.Id)) }()
_, err = ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u3.Id}, -1)
require.Nil(t, err)
_, err = ss.Bot().Save(&model.Bot{
UserId: u3.Id,
Username: u3.Username,
OwnerId: u1.Id,
})
require.Nil(t, err)
u3.IsBot = true
defer func() { require.Nil(t, ss.Bot().PermanentDelete(u3.Id)) }()
u4, err := ss.User().Save(&model.User{
Email: MakeEmail(),
Username: "u4" + model.NewId(),
})
require.Nil(t, err)
defer func() { require.Nil(t, ss.User().PermanentDelete(u4.Id)) }()
_, err = ss.Team().SaveMember(&model.TeamMember{TeamId: teamId, UserId: u4.Id}, -1)
require.Nil(t, err)
ch1 := &model.Channel{
TeamId: teamId,
DisplayName: "Profiles in channel",
Name: "profiles-" + model.NewId(),
Type: model.CHANNEL_OPEN,
}
c1, err := ss.Channel().Save(ch1, -1)
require.Nil(t, err)
ch2 := &model.Channel{
TeamId: teamId,
DisplayName: "Profiles in private",
Name: "profiles-" + model.NewId(),
Type: model.CHANNEL_PRIVATE,
}
c2, err := ss.Channel().Save(ch2, -1)
require.Nil(t, err)
ch3 := &model.Channel{
TeamId: teamId,
DisplayName: "Profiles in private",
Name: "profiles-" + model.NewId(),
Type: model.CHANNEL_PRIVATE,
}
c3, err := ss.Channel().Save(ch3, -1)
require.Nil(t, err)
_, err = ss.Channel().SaveMember(&model.ChannelMember{
ChannelId: c1.Id,
UserId: u1.Id,
NotifyProps: model.GetDefaultChannelNotifyProps(),
})
require.Nil(t, err)
_, err = ss.Channel().SaveMember(&model.ChannelMember{
ChannelId: c1.Id,
UserId: u2.Id,
NotifyProps: model.GetDefaultChannelNotifyProps(),
})
require.Nil(t, err)
_, err = ss.Channel().SaveMember(&model.ChannelMember{
ChannelId: c2.Id,
UserId: u3.Id,
NotifyProps: model.GetDefaultChannelNotifyProps(),
})
require.Nil(t, err)
_, err = ss.Channel().SaveMember(&model.ChannelMember{
ChannelId: c2.Id,
UserId: u1.Id,
NotifyProps: model.GetDefaultChannelNotifyProps(),
})
require.Nil(t, err)
_, err = ss.Channel().SaveMember(&model.ChannelMember{
ChannelId: c3.Id,
UserId: u4.Id,
NotifyProps: model.GetDefaultChannelNotifyProps(),
})
require.Nil(t, err)
t.Run("get know users sharing no channels", func(t *testing.T) {
userIds, err := ss.User().GetKnownUsers(u4.Id)
require.Nil(t, err)
assert.Empty(t, userIds)
})
t.Run("get know users sharing one channel", func(t *testing.T) {
userIds, err := ss.User().GetKnownUsers(u3.Id)
require.Nil(t, err)
assert.Len(t, userIds, 1)
assert.Equal(t, userIds[0], u1.Id)
})
t.Run("get know users sharing multiple channels", func(t *testing.T) {
userIds, err := ss.User().GetKnownUsers(u1.Id)
require.Nil(t, err)
assert.Len(t, userIds, 2)
assert.ElementsMatch(t, userIds, []string{u2.Id, u3.Id})
})
}

Просмотреть файл

@@ -6919,6 +6919,22 @@ func (s *TimerLayerUserStore) GetForLogin(loginId string, allowSignInWithUsernam
return resultVar0, resultVar1
}
func (s *TimerLayerUserStore) GetKnownUsers(userID string) ([]string, *model.AppError) {
start := timemodule.Now()
resultVar0, resultVar1 := s.UserStore.GetKnownUsers(userID)
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
if s.Root.Metrics != nil {
success := "false"
if resultVar1 == nil {
success = "true"
}
s.Root.Metrics.ObserveStoreMethodDuration("UserStore.GetKnownUsers", success, elapsed)
}
return resultVar0, resultVar1
}
func (s *TimerLayerUserStore) GetNewUsersForTeam(teamId string, offset int, limit int, viewRestrictions *model.ViewUsersRestrictions) ([]*model.User, *model.AppError) {
start := timemodule.Now()