[MM-21793] Allow bots to be added to group synced channels and teams (#13672)

* MM-21793: Allow bots to be removed and added from group synced teams and channels

* MM-21793: Add tests for adding and removing a team and channel members

* MM-21793 Add punctuation to comments and remove unnecessary variable
Этот коммит содержится в:
Farhan Munshi
2020-01-29 11:01:06 -05:00
коммит произвёл GitHub
родитель ffb3897c8c
Коммит fa769e46d7
10 изменённых файлов: 191 добавлений и 45 удалений

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

@@ -1696,7 +1696,7 @@ func (a *App) removeUserFromChannel(userIdToRemove string, removerUserId string,
}
}
if channel.IsGroupConstrained() && userIdToRemove != removerUserId {
if channel.IsGroupConstrained() && userIdToRemove != removerUserId && !user.IsBot {
nonMembers, err := a.FilterNonGroupChannelMembers([]string{userIdToRemove}, channel)
if err != nil {
return model.NewAppError("removeUserFromChannel", "api.channel.remove_user_from_channel.app_error", nil, "", http.StatusInternalServerError)

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

@@ -1169,7 +1169,12 @@ func TestAddUserToChannel(t *testing.T) {
user1 := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""}
ruser1, _ := th.App.CreateUser(&user1)
defer th.App.PermanentDeleteUser(&user1)
bot := th.CreateBot()
botUser, _ := th.App.GetUser(bot.UserId)
defer th.App.PermanentDeleteBot(botUser.Id)
th.App.AddTeamMember(th.BasicTeam.Id, ruser1.Id)
th.App.AddTeamMember(th.BasicTeam.Id, bot.UserId)
group := th.CreateGroup()
@@ -1208,8 +1213,82 @@ func TestAddUserToChannel(t *testing.T) {
err = th.App.JoinChannel(th.BasicChannel, ruser2.Id)
require.Nil(t, err)
// Should allow a bot to be added to a public group synced channel
_, err = th.App.AddUserToChannel(botUser, th.BasicChannel)
require.Nil(t, err)
// verify user was added as an admin
cm2, err := th.App.GetChannelMember(th.BasicChannel.Id, ruser2.Id)
require.Nil(t, err)
require.True(t, cm2.SchemeAdmin)
privateChannel := th.CreatePrivateChannel(th.BasicTeam)
privateChannel.GroupConstrained = model.NewBool(true)
_, err = th.App.UpdateChannel(privateChannel)
require.Nil(t, err)
_, err = th.App.UpsertGroupSyncable(&model.GroupSyncable{
GroupId: group.Id,
SyncableId: privateChannel.Id,
Type: model.GroupSyncableTypeChannel,
})
require.Nil(t, err)
// Should allow a group synced user to be added to a group synced private channel
_, err = th.App.AddUserToChannel(ruser1, privateChannel)
require.Nil(t, err)
// Should allow a bot to be added to a private group synced channel
_, err = th.App.AddUserToChannel(botUser, privateChannel)
require.Nil(t, err)
}
func TestRemoveUserFromChannel(t *testing.T) {
th := Setup(t).InitBasic()
defer th.TearDown()
user := model.User{Email: strings.ToLower(model.NewId()) + "success+test@example.com", Nickname: "Darth Vader", Username: "vader" + model.NewId(), Password: "passwd1", AuthService: ""}
ruser, _ := th.App.CreateUser(&user)
defer th.App.PermanentDeleteUser(ruser)
bot := th.CreateBot()
botUser, _ := th.App.GetUser(bot.UserId)
defer th.App.PermanentDeleteBot(botUser.Id)
th.App.AddTeamMember(th.BasicTeam.Id, ruser.Id)
th.App.AddTeamMember(th.BasicTeam.Id, bot.UserId)
privateChannel := th.CreatePrivateChannel(th.BasicTeam)
_, err := th.App.AddUserToChannel(ruser, privateChannel)
require.Nil(t, err)
_, err = th.App.AddUserToChannel(botUser, privateChannel)
require.Nil(t, err)
group := th.CreateGroup()
_, err = th.App.UpsertGroupMember(group.Id, ruser.Id)
require.Nil(t, err)
_, err = th.App.UpsertGroupSyncable(&model.GroupSyncable{
GroupId: group.Id,
SyncableId: privateChannel.Id,
Type: model.GroupSyncableTypeChannel,
})
require.Nil(t, err)
privateChannel.GroupConstrained = model.NewBool(true)
_, err = th.App.UpdateChannel(privateChannel)
require.Nil(t, err)
// Should not allow a group synced user to be removed from channel
err = th.App.RemoveUserFromChannel(ruser.Id, th.SystemAdminUser.Id, privateChannel)
assert.Equal(t, err.Id, "api.channel.remove_members.denied")
// Should allow a user to remove themselves from group synced channel
err = th.App.RemoveUserFromChannel(ruser.Id, ruser.Id, privateChannel)
require.Nil(t, err)
// Should allow a bot to be removed from a group synced channel
err = th.App.RemoveUserFromChannel(botUser.Id, th.SystemAdminUser.Id, privateChannel)
require.Nil(t, err)
}

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

@@ -194,6 +194,28 @@ func (me *TestHelper) CreateUserOrGuest(guest bool) *model.User {
return user
}
func (me *TestHelper) CreateBot() *model.Bot {
id := model.NewId()
bot := &model.Bot{
Username: "bot" + id,
DisplayName: "a bot",
Description: "bot",
OwnerId: me.BasicUser.Id,
}
me.App.Log.SetConsoleLevel(mlog.LevelError)
bot, err := me.App.CreateBot(bot)
if err != nil {
mlog.Error(err.Error())
time.Sleep(time.Second)
panic(err)
}
me.App.Log.SetConsoleLevel(mlog.LevelDebug)
return bot
}
func (me *TestHelper) CreateChannel(team *model.Team) *model.Channel {
return me.createChannel(team, model.CHANNEL_OPEN)
}

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

@@ -2064,69 +2064,49 @@ func (a *App) RestrictUsersGetByPermissions(userId string, options *model.UserGe
}
// FilterNonGroupTeamMembers returns the subset of the given user IDs of the users who are not members of groups
// associated to the team.
func (a *App) FilterNonGroupTeamMembers(userIDs []string, team *model.Team) ([]string, error) {
// associated to the team excluding bots.
func (a *App) FilterNonGroupTeamMembers(userIds []string, team *model.Team) ([]string, error) {
teamGroupUsers, err := a.GetTeamGroupUsers(team.Id)
if err != nil {
return nil, err
}
// possible if no groups associated or no group members in any of the associated groups
if len(teamGroupUsers) == 0 {
return userIDs, nil
}
nonMemberIDs := []string{}
for _, userID := range userIDs {
userIsMember := false
for _, pu := range teamGroupUsers {
if pu.Id == userID {
userIsMember = true
break
}
}
if !userIsMember {
nonMemberIDs = append(nonMemberIDs, userID)
}
}
return nonMemberIDs, nil
return a.filterNonGroupUsers(userIds, teamGroupUsers)
}
// FilterNonGroupChannelMembers returns the subset of the given user IDs of the users who are not members of groups
// associated to the channel.
func (a *App) FilterNonGroupChannelMembers(userIDs []string, channel *model.Channel) ([]string, error) {
// associated to the channel excluding bots
func (a *App) FilterNonGroupChannelMembers(userIds []string, channel *model.Channel) ([]string, error) {
channelGroupUsers, err := a.GetChannelGroupUsers(channel.Id)
if err != nil {
return nil, err
}
return a.filterNonGroupUsers(userIds, channelGroupUsers)
}
// possible if no groups associated or no group members in any of the associated groups
if len(channelGroupUsers) == 0 {
return userIDs, nil
// filterNonGroupUsers is a helper function that takes a list of user ids and a list of users
// and returns the list of normal users present in userIds but not in groupUsers.
func (a *App) filterNonGroupUsers(userIds []string, groupUsers []*model.User) ([]string, error) {
nonMemberIds := []string{}
users, err := a.Srv.Store.User().GetProfileByIds(userIds, nil, false)
if err != nil {
return nil, err
}
nonMemberIDs := []string{}
for _, user := range users {
userIsMember := user.IsBot
for _, userID := range userIDs {
userIsMember := false
for _, pu := range channelGroupUsers {
if pu.Id == userID {
for _, pu := range groupUsers {
if pu.Id == user.Id {
userIsMember = true
break
}
}
if !userIsMember {
nonMemberIDs = append(nonMemberIDs, userID)
nonMemberIds = append(nonMemberIds, user.Id)
}
}
return nonMemberIDs, nil
return nonMemberIds, nil
}
func (a *App) RestrictUsersSearchByPermissions(userId string, options *model.UserSearchOptions) (*model.UserSearchOptions, *model.AppError) {