mirror of
https://github.com/mattermost/mattermost.git
synced 2025-02-25 18:55:24 -06:00
* MM-14412: Enables force removals of team/channel members base on group constraints. * Renames some existing methods and variables. * Change return types to ChannelMembers and TeamMembers for some existing methods. * Adds option to change LDAP_DATA to either 'qa' or 'test' with env variable. * Adds methods to retrieve ChannelMembers and TeamMembers that, based on group constraints, should be deleted. * Adds helper functions to create GroupTeams and GroupChannels. * MM-14412: Switches to helper methods for GroupSyncable creation in test files. * MM-14412: Style fix. * MM-14412: Switches remaining GroupSyncable instances to be created with helper functions. * MM-14412: Typo fix. * MM-11412: Build fixes. * MM-14412: Checks if user is team member before re-adding. * MM-14412: Update for change of GroupConstrained fields type.
396 lines
12 KiB
Go
396 lines
12 KiB
Go
package app
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/mattermost/mattermost-server/model"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestCreateDefaultMemberships(t *testing.T) {
|
|
th := Setup(t).InitBasic()
|
|
defer th.TearDown()
|
|
|
|
singersTeam, err := th.App.CreateTeam(&model.Team{
|
|
DisplayName: "Singers",
|
|
Name: model.NewId(),
|
|
Email: "singers@test.com",
|
|
Type: model.TEAM_OPEN,
|
|
})
|
|
if err != nil {
|
|
t.Errorf("test team not created: %s", err.Error())
|
|
}
|
|
|
|
nerdsTeam, err := th.App.CreateTeam(&model.Team{
|
|
DisplayName: "Nerds",
|
|
Name: model.NewId(),
|
|
Email: "nerds@test.com",
|
|
Type: model.TEAM_INVITE,
|
|
})
|
|
if err != nil {
|
|
t.Errorf("test team not created: %s", err.Error())
|
|
}
|
|
|
|
practiceChannel, err := th.App.CreateChannel(&model.Channel{
|
|
TeamId: singersTeam.Id,
|
|
DisplayName: "Practices",
|
|
Name: model.NewId(),
|
|
Type: model.CHANNEL_OPEN,
|
|
}, false)
|
|
if err != nil {
|
|
t.Errorf("test channel not created: %s", err.Error())
|
|
}
|
|
|
|
experimentsChannel, err := th.App.CreateChannel(&model.Channel{
|
|
TeamId: singersTeam.Id,
|
|
DisplayName: "Experiments",
|
|
Name: model.NewId(),
|
|
Type: model.CHANNEL_PRIVATE,
|
|
}, false)
|
|
if err != nil {
|
|
t.Errorf("test channel not created: %s", err.Error())
|
|
}
|
|
|
|
gleeGroup, err := th.App.CreateGroup(&model.Group{
|
|
Name: model.NewId(),
|
|
DisplayName: "Glee Club",
|
|
RemoteId: model.NewId(),
|
|
Source: model.GroupSourceLdap,
|
|
})
|
|
if err != nil {
|
|
t.Errorf("test group not created: %s", err.Error())
|
|
}
|
|
|
|
scienceGroup, err := th.App.CreateGroup(&model.Group{
|
|
Name: model.NewId(),
|
|
DisplayName: "Science Club",
|
|
RemoteId: model.NewId(),
|
|
Source: model.GroupSourceLdap,
|
|
})
|
|
if err != nil {
|
|
t.Errorf("test group not created: %s", err.Error())
|
|
}
|
|
|
|
_, err = th.App.CreateGroupSyncable(model.NewGroupChannel(gleeGroup.Id, practiceChannel.Id, true))
|
|
if err != nil {
|
|
t.Errorf("test groupchannel not created: %s", err.Error())
|
|
}
|
|
|
|
scienceTeamGroupSyncable, err := th.App.CreateGroupSyncable(model.NewGroupTeam(scienceGroup.Id, nerdsTeam.Id, false))
|
|
if err != nil {
|
|
t.Errorf("test groupteam not created: %s", err.Error())
|
|
}
|
|
|
|
scienceChannelGroupSyncable, err := th.App.CreateGroupSyncable(model.NewGroupChannel(scienceGroup.Id, experimentsChannel.Id, false))
|
|
if err != nil {
|
|
t.Errorf("test groupchannel not created: %s", err.Error())
|
|
}
|
|
|
|
singer1 := th.BasicUser
|
|
scientist1 := th.BasicUser2
|
|
|
|
_, err = th.App.CreateOrRestoreGroupMember(gleeGroup.Id, singer1.Id)
|
|
if err != nil {
|
|
t.Errorf("test groupmember not created: %s", err.Error())
|
|
}
|
|
|
|
scientistGroupMember, err := th.App.CreateOrRestoreGroupMember(scienceGroup.Id, scientist1.Id)
|
|
if err != nil {
|
|
t.Errorf("test groupmember not created: %s", err.Error())
|
|
}
|
|
|
|
pErr := th.App.CreateDefaultMemberships(0)
|
|
if pErr != nil {
|
|
t.Errorf("faild to populate syncables: %s", pErr.Error())
|
|
}
|
|
|
|
// Singer should be in team and channel
|
|
_, err = th.App.GetTeamMember(singersTeam.Id, singer1.Id)
|
|
if err != nil {
|
|
t.Errorf("error retrieving team member: %s", err.Error())
|
|
}
|
|
_, err = th.App.GetChannelMember(practiceChannel.Id, singer1.Id)
|
|
if err != nil {
|
|
t.Errorf("error retrieving channel member: %s", err.Error())
|
|
}
|
|
|
|
tMembers, err := th.App.GetTeamMembers(singersTeam.Id, 0, 999)
|
|
if err != nil {
|
|
t.Errorf("error retrieving team members: %s", err.Error())
|
|
}
|
|
expected := 1
|
|
actual := len(tMembers)
|
|
if actual != expected {
|
|
t.Errorf("expected %d team members but got %d", expected, actual)
|
|
}
|
|
|
|
cMembersCount, err := th.App.GetChannelMemberCount(practiceChannel.Id)
|
|
if err != nil {
|
|
t.Errorf("error retrieving team members: %s", err.Error())
|
|
}
|
|
if cMembersCount != int64(expected) {
|
|
t.Errorf("expected %d team member but got %d", expected, cMembersCount)
|
|
}
|
|
|
|
// Scientist should not be in team or channel
|
|
_, err = th.App.GetTeamMember(nerdsTeam.Id, scientist1.Id)
|
|
if err.Id != "store.sql_team.get_member.missing.app_error" {
|
|
t.Errorf("wrong error: %s", err.Id)
|
|
}
|
|
|
|
_, err = th.App.GetChannelMember(experimentsChannel.Id, scientist1.Id)
|
|
if err.Id != "store.sql_channel.get_member.missing.app_error" {
|
|
t.Errorf("wrong error: %s", err.Id)
|
|
}
|
|
|
|
tMembers, err = th.App.GetTeamMembers(nerdsTeam.Id, 0, 999)
|
|
if err != nil {
|
|
t.Errorf("error retrieving team members: %s", err.Error())
|
|
}
|
|
expected = 0
|
|
actual = len(tMembers)
|
|
if actual != expected {
|
|
t.Errorf("expected %d team members but got %d", expected, actual)
|
|
}
|
|
|
|
cMembersCount, err = th.App.GetChannelMemberCount(experimentsChannel.Id)
|
|
if err != nil {
|
|
t.Errorf("error retrieving team members: %s", err.Error())
|
|
}
|
|
if cMembersCount != int64(expected) {
|
|
t.Errorf("expected %d team members but got %d", expected, cMembersCount)
|
|
}
|
|
|
|
// update AutoAdd to true
|
|
scienceTeamGroupSyncable.AutoAdd = true
|
|
scienceTeamGroupSyncable, err = th.App.UpdateGroupSyncable(scienceTeamGroupSyncable)
|
|
if err != nil {
|
|
t.Errorf("error updating group syncable: %s", err.Error())
|
|
}
|
|
|
|
// Sync everything after syncable was created (proving that team updates trigger re-sync)
|
|
pErr = th.App.CreateDefaultMemberships(scientistGroupMember.CreateAt + 1)
|
|
if pErr != nil {
|
|
t.Errorf("faild to populate syncables: %s", pErr.Error())
|
|
}
|
|
|
|
// Scientist should be in team but not the channel
|
|
_, err = th.App.GetTeamMember(nerdsTeam.Id, scientist1.Id)
|
|
if err != nil {
|
|
t.Errorf("error retrieving team member: %s", err.Error())
|
|
}
|
|
|
|
_, err = th.App.GetChannelMember(experimentsChannel.Id, scientist1.Id)
|
|
if err.Id != "store.sql_channel.get_member.missing.app_error" {
|
|
t.Errorf("wrong error: %s", err.Id)
|
|
}
|
|
|
|
tMembers, err = th.App.GetTeamMembers(nerdsTeam.Id, 0, 999)
|
|
if err != nil {
|
|
t.Errorf("error retrieving team members: %s", err.Error())
|
|
}
|
|
expected = 1
|
|
actual = len(tMembers)
|
|
if actual != expected {
|
|
t.Errorf("expected %d team members but got %d", expected, actual)
|
|
}
|
|
|
|
expected = 0
|
|
cMembersCount, err = th.App.GetChannelMemberCount(experimentsChannel.Id)
|
|
if err != nil {
|
|
t.Errorf("error retrieving team members: %s", err.Error())
|
|
}
|
|
if cMembersCount != int64(expected) {
|
|
t.Errorf("expected %d team members but got %d", expected, cMembersCount)
|
|
}
|
|
|
|
// Update the channel syncable
|
|
scienceChannelGroupSyncable.AutoAdd = true
|
|
scienceChannelGroupSyncable, err = th.App.UpdateGroupSyncable(scienceChannelGroupSyncable)
|
|
if err != nil {
|
|
t.Errorf("error updating group syncable: %s", err.Error())
|
|
}
|
|
|
|
// Sync everything after syncable was created (proving that channel updates trigger re-sync)
|
|
pErr = th.App.CreateDefaultMemberships(scientistGroupMember.CreateAt + 1)
|
|
if pErr != nil {
|
|
t.Errorf("faild to populate syncables: %s", pErr.Error())
|
|
}
|
|
|
|
expected = 1
|
|
cMembersCount, err = th.App.GetChannelMemberCount(experimentsChannel.Id)
|
|
if err != nil {
|
|
t.Errorf("error retrieving team members: %s", err.Error())
|
|
}
|
|
if cMembersCount != int64(expected) {
|
|
t.Errorf("expected %d team members but got %d", expected, cMembersCount)
|
|
}
|
|
|
|
// singer leaves team and channel
|
|
err = th.App.LeaveChannel(practiceChannel.Id, singer1.Id)
|
|
if err != nil {
|
|
t.Errorf("error leaving channel: %s", err.Error())
|
|
}
|
|
err = th.App.LeaveTeam(singersTeam, singer1, "")
|
|
if err != nil {
|
|
t.Errorf("error leaving team: %s", err.Error())
|
|
}
|
|
|
|
// Even re-syncing from the beginning doesn't re-add to channel or team
|
|
pErr = th.App.CreateDefaultMemberships(0)
|
|
if pErr != nil {
|
|
t.Errorf("faild to populate syncables: %s", pErr.Error())
|
|
}
|
|
|
|
// Singer should not be in team or channel
|
|
tMember, err := th.App.GetTeamMember(singersTeam.Id, singer1.Id)
|
|
if err != nil {
|
|
t.Errorf("error retrieving team member: %s", err.Error())
|
|
}
|
|
if tMember.DeleteAt == 0 {
|
|
t.Error("expected team member to remain deleted")
|
|
}
|
|
|
|
_, err = th.App.GetChannelMember(practiceChannel.Id, singer1.Id)
|
|
if err == nil {
|
|
t.Error("Expected channel member to remain deleted")
|
|
}
|
|
|
|
// Ensure members are in channel
|
|
_, err = th.App.AddChannelMember(scientist1.Id, experimentsChannel, "", "", "")
|
|
if err != nil {
|
|
t.Errorf("unable to add user to channel: %s", err.Error())
|
|
}
|
|
|
|
// Add other user so that user can leave channel
|
|
_, err = th.App.AddTeamMember(singersTeam.Id, singer1.Id)
|
|
if err != nil {
|
|
t.Errorf("unable to add user to team: %s", err.Error())
|
|
}
|
|
_, err = th.App.AddChannelMember(singer1.Id, experimentsChannel, "", "", "")
|
|
if err != nil {
|
|
t.Errorf("unable to add user to channel: %s", err.Error())
|
|
}
|
|
|
|
// the channel syncable is updated
|
|
scienceChannelGroupSyncable, err = th.App.UpdateGroupSyncable(scienceChannelGroupSyncable)
|
|
if err != nil {
|
|
t.Errorf("error updating group syncable: %s", err.Error())
|
|
}
|
|
|
|
pErr = th.App.CreateDefaultMemberships(0)
|
|
if pErr != nil {
|
|
t.Errorf("faild to populate syncables: %s", pErr.Error())
|
|
}
|
|
|
|
timeBeforeLeaving := model.GetMillis()
|
|
|
|
// User leaves channel
|
|
err = th.App.LeaveChannel(experimentsChannel.Id, scientist1.Id)
|
|
if err != nil {
|
|
t.Errorf("unable to add user to channel: %s", err.Error())
|
|
}
|
|
|
|
timeAfterLeaving := model.GetMillis()
|
|
|
|
// Purging channelmemberhistory doesn't re-add user to channel
|
|
result := <-th.App.Srv.Store.ChannelMemberHistory().PermanentDeleteBatch(timeBeforeLeaving, 1000)
|
|
if result.Err != nil {
|
|
t.Errorf("error permanently deleting channelmemberhistory: %s", result.Err.Error())
|
|
}
|
|
|
|
pErr = th.App.CreateDefaultMemberships(scienceChannelGroupSyncable.UpdateAt)
|
|
if pErr != nil {
|
|
t.Errorf("failed to populate syncables: %s", pErr.Error())
|
|
}
|
|
|
|
_, err = th.App.GetChannelMember(experimentsChannel.Id, scientist1.Id)
|
|
if err == nil {
|
|
t.Error("Expected channel member to remain deleted")
|
|
}
|
|
|
|
// Purging channelmemberhistory doesn't re-add user to channel
|
|
result = <-th.App.Srv.Jobs.Store.ChannelMemberHistory().PermanentDeleteBatch(timeAfterLeaving, 1000)
|
|
if result.Err != nil {
|
|
t.Errorf("error permanently deleting channelmemberhistory: %s", result.Err.Error())
|
|
}
|
|
|
|
pErr = th.App.CreateDefaultMemberships(scienceChannelGroupSyncable.UpdateAt)
|
|
if pErr != nil {
|
|
t.Errorf("failed to populate syncables: %s", pErr.Error())
|
|
}
|
|
|
|
// Channel member is re-added.
|
|
_, err = th.App.GetChannelMember(experimentsChannel.Id, scientist1.Id)
|
|
if err != nil {
|
|
t.Errorf("expected channel member: %s", err.Error())
|
|
}
|
|
}
|
|
|
|
func TestDeleteGroupMemberships(t *testing.T) {
|
|
th := Setup(t).InitBasic()
|
|
defer th.TearDown()
|
|
|
|
group := th.CreateGroup()
|
|
|
|
userIDs := []string{th.BasicUser.Id, th.BasicUser2.Id, th.SystemAdminUser.Id}
|
|
|
|
var err *model.AppError
|
|
// add users to teams and channels
|
|
for _, userID := range userIDs {
|
|
_, err = th.App.AddTeamMember(th.BasicTeam.Id, userID)
|
|
require.Nil(t, err)
|
|
|
|
_, err = th.App.AddChannelMember(userID, th.BasicChannel, "", "", "")
|
|
require.Nil(t, err)
|
|
}
|
|
|
|
// make team group-constrained
|
|
team := th.BasicTeam
|
|
team.GroupConstrained = model.NewBool(true)
|
|
team, err = th.App.UpdateTeam(team)
|
|
require.Nil(t, err)
|
|
require.True(t, *team.GroupConstrained)
|
|
|
|
// make channel group-constrained
|
|
channel := th.BasicChannel
|
|
channel.GroupConstrained = model.NewBool(true)
|
|
channel, err = th.App.UpdateChannel(channel)
|
|
require.Nil(t, err)
|
|
require.True(t, *channel.GroupConstrained)
|
|
|
|
// create groupteam and groupchannel
|
|
_, err = th.App.CreateGroupSyncable(model.NewGroupTeam(group.Id, team.Id, true))
|
|
require.Nil(t, err)
|
|
_, err = th.App.CreateGroupSyncable(model.NewGroupChannel(group.Id, channel.Id, true))
|
|
require.Nil(t, err)
|
|
|
|
// verify the member count
|
|
tmembers, err := th.App.GetTeamMembers(th.BasicTeam.Id, 0, 100)
|
|
require.Nil(t, err)
|
|
require.Len(t, tmembers, 3)
|
|
|
|
cmemberCount, err := th.App.GetChannelMemberCount(th.BasicChannel.Id)
|
|
require.Nil(t, err)
|
|
require.Equal(t, 3, int(cmemberCount))
|
|
|
|
// add a user to the group
|
|
_, err = th.App.CreateOrRestoreGroupMember(group.Id, th.SystemAdminUser.Id)
|
|
require.Nil(t, err)
|
|
|
|
// run the delete
|
|
appErr := th.App.DeleteGroupConstrainedMemberships()
|
|
require.Nil(t, appErr)
|
|
|
|
// verify the new member counts
|
|
tmembers, err = th.App.GetTeamMembers(th.BasicTeam.Id, 0, 100)
|
|
require.Nil(t, err)
|
|
require.Len(t, tmembers, 1)
|
|
require.Equal(t, th.SystemAdminUser.Id, tmembers[0].UserId)
|
|
|
|
cmembers, err := th.App.GetChannelMembersPage(channel.Id, 0, 99)
|
|
require.Nil(t, err)
|
|
require.Len(t, (*cmembers), 1)
|
|
require.Equal(t, th.SystemAdminUser.Id, (*cmembers)[0].UserId)
|
|
}
|