PluginAPI: add ability to retrieve users by ids (#26936)

* pluginapi: ability to retrieve users by ids

* fix test
This commit is contained in:
Julien Tant
2024-05-15 07:06:40 -07:00
committed by GitHub
parent 0911e4dee7
commit e96db725ea
8 changed files with 171 additions and 0 deletions
+4
View File
@@ -246,6 +246,10 @@ func (api *PluginAPI) GetUsers(options *model.UserGetOptions) ([]*model.User, *m
return api.app.GetUsersFromProfiles(options)
}
func (api *PluginAPI) GetUsersByIds(usersID []string) ([]*model.User, *model.AppError) {
return api.app.GetUsers(usersID)
}
func (api *PluginAPI) GetUser(userID string) (*model.User, *model.AppError) {
return api.app.GetUser(userID)
}
+55
View File
@@ -431,6 +431,61 @@ func TestPluginAPIGetUsers(t *testing.T) {
}
}
func TestPluginAPIGetUsersByIds(t *testing.T) {
th := Setup(t).DeleteBots()
defer th.TearDown()
api := th.SetupPluginAPI()
user1, err := th.App.CreateUser(th.Context, &model.User{
Email: strings.ToLower(model.NewId()) + "success+test@example.com",
Password: "password",
Username: "user1" + model.NewId(),
})
require.Nil(t, err)
defer th.App.PermanentDeleteUser(th.Context, user1)
user2, err := th.App.CreateUser(th.Context, &model.User{
Email: strings.ToLower(model.NewId()) + "success+test@example.com",
Password: "password",
Username: "user2" + model.NewId(),
})
require.Nil(t, err)
defer th.App.PermanentDeleteUser(th.Context, user2)
user3, err := th.App.CreateUser(th.Context, &model.User{
Email: strings.ToLower(model.NewId()) + "success+test@example.com",
Password: "password",
Username: "user3" + model.NewId(),
})
require.Nil(t, err)
defer th.App.PermanentDeleteUser(th.Context, user3)
testCases := []struct {
Description string
requestedIDs []string
}{
{
"no users",
[]string{},
},
{
"getting 1 and 3",
[]string{user1.Id, user3.Id},
},
}
for _, testCase := range testCases {
t.Run(testCase.Description, func(t *testing.T) {
users, err := api.GetUsersByIds(testCase.requestedIDs)
assert.Nil(t, err)
assert.Equal(t, len(testCase.requestedIDs), len(users))
for _, user := range users {
assert.Contains(t, testCase.requestedIDs, user.Id)
}
})
}
}
func TestPluginAPIGetUsersInTeam(t *testing.T) {
th := Setup(t)
defer th.TearDown()
+6
View File
@@ -135,6 +135,12 @@ type API interface {
// Minimum server version: 5.10
GetUsers(options *model.UserGetOptions) ([]*model.User, *model.AppError)
// GetUsersByIds gets a list of users by their IDs.
//
// @tag User
// Minimum server version: 9.8
GetUsersByIds(userIDs []string) ([]*model.User, *model.AppError)
// GetUser gets a user.
//
// @tag User
@@ -160,6 +160,13 @@ func (api *apiTimerLayer) GetUsers(options *model.UserGetOptions) ([]*model.User
return _returnsA, _returnsB
}
func (api *apiTimerLayer) GetUsersByIds(userIDs []string) ([]*model.User, *model.AppError) {
startTime := timePkg.Now()
_returnsA, _returnsB := api.apiImpl.GetUsersByIds(userIDs)
api.recordTime(startTime, "GetUsersByIds", _returnsB == nil)
return _returnsA, _returnsB
}
func (api *apiTimerLayer) GetUser(userID string) (*model.User, *model.AppError) {
startTime := timePkg.Now()
_returnsA, _returnsB := api.apiImpl.GetUser(userID)
@@ -1665,6 +1665,35 @@ func (s *apiRPCServer) GetUsers(args *Z_GetUsersArgs, returns *Z_GetUsersReturns
return nil
}
type Z_GetUsersByIdsArgs struct {
A []string
}
type Z_GetUsersByIdsReturns struct {
A []*model.User
B *model.AppError
}
func (g *apiRPCClient) GetUsersByIds(userIDs []string) ([]*model.User, *model.AppError) {
_args := &Z_GetUsersByIdsArgs{userIDs}
_returns := &Z_GetUsersByIdsReturns{}
if err := g.client.Call("Plugin.GetUsersByIds", _args, _returns); err != nil {
log.Printf("RPC call to GetUsersByIds API failed: %s", err.Error())
}
return _returns.A, _returns.B
}
func (s *apiRPCServer) GetUsersByIds(args *Z_GetUsersByIdsArgs, returns *Z_GetUsersByIdsReturns) error {
if hook, ok := s.impl.(interface {
GetUsersByIds(userIDs []string) ([]*model.User, *model.AppError)
}); ok {
returns.A, returns.B = hook.GetUsersByIds(args.A)
} else {
return encodableError(fmt.Errorf("API GetUsersByIds called but not implemented."))
}
return nil
}
type Z_GetUserArgs struct {
A string
}
+32
View File
@@ -3064,6 +3064,38 @@ func (_m *API) GetUsers(options *model.UserGetOptions) ([]*model.User, *model.Ap
return r0, r1
}
// GetUsersByIds provides a mock function with given fields: userIDs
func (_m *API) GetUsersByIds(userIDs []string) ([]*model.User, *model.AppError) {
ret := _m.Called(userIDs)
if len(ret) == 0 {
panic("no return value specified for GetUsersByIds")
}
var r0 []*model.User
var r1 *model.AppError
if rf, ok := ret.Get(0).(func([]string) ([]*model.User, *model.AppError)); ok {
return rf(userIDs)
}
if rf, ok := ret.Get(0).(func([]string) []*model.User); ok {
r0 = rf(userIDs)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).([]*model.User)
}
}
if rf, ok := ret.Get(1).(func([]string) *model.AppError); ok {
r1 = rf(userIDs)
} else {
if ret.Get(1) != nil {
r1 = ret.Get(1).(*model.AppError)
}
}
return r0, r1
}
// GetUsersByUsernames provides a mock function with given fields: usernames
func (_m *API) GetUsersByUsernames(usernames []string) ([]*model.User, *model.AppError) {
ret := _m.Called(usernames)
+9
View File
@@ -49,6 +49,15 @@ func (u *UserService) List(options *model.UserGetOptions) ([]*model.User, error)
return users, normalizeAppErr(appErr)
}
// ListByUserIDs gets users by their IDs.
//
// Minimum server version: 9.8
func (u *UserService) ListByUserIDs(userIDs []string) ([]*model.User, error) {
users, appErr := u.api.GetUsersByIds(userIDs)
return users, normalizeAppErr(appErr)
}
// ListByUsernames gets users by their usernames.
//
// Minimum server version: 5.6
+29
View File
@@ -96,6 +96,35 @@ func TestGetUsers(t *testing.T) {
})
}
func TestListByUserIDs(t *testing.T) {
t.Run("success", func(t *testing.T) {
api := &plugintest.API{}
defer api.AssertExpectations(t)
client := pluginapi.NewClient(api, &plugintest.Driver{})
userIDs := []string{"123"}
expectedUsers := []*model.User{{Id: "123", Username: "test"}}
api.On("GetUsersByIds", userIDs).Return(expectedUsers, nil)
actualUsers, err := client.User.ListByUserIDs(userIDs)
require.NoError(t, err)
assert.Equal(t, expectedUsers, actualUsers)
})
t.Run("failure", func(t *testing.T) {
api := &plugintest.API{}
defer api.AssertExpectations(t)
client := pluginapi.NewClient(api, &plugintest.Driver{})
userIDs := []string{"123"}
api.On("GetUsersByIds", userIDs).Return(nil, newAppError())
actualUsers, err := client.User.ListByUserIDs(userIDs)
require.EqualError(t, err, "here: id, an error occurred")
assert.Nil(t, actualUsers)
})
}
func TestGetUser(t *testing.T) {
t.Run("success", func(t *testing.T) {
api := &plugintest.API{}