github.com/haalcala/mattermost-server-change-repo/v5@v5.33.2/app/syncables_test.go (about)

     1  // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
     2  // See LICENSE.txt for license information.
     3  
     4  package app
     5  
     6  import (
     7  	"testing"
     8  
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/mattermost/mattermost-server/v5/model"
    12  )
    13  
    14  func TestCreateDefaultMemberships(t *testing.T) {
    15  	th := Setup(t).InitBasic()
    16  	defer th.TearDown()
    17  
    18  	singersTeam, err := th.App.CreateTeam(&model.Team{
    19  		DisplayName: "Singers",
    20  		Name:        "zz" + model.NewId(),
    21  		Email:       "singers@test.com",
    22  		Type:        model.TEAM_OPEN,
    23  	})
    24  	if err != nil {
    25  		t.Errorf("test team not created: %s", err.Error())
    26  	}
    27  
    28  	nerdsTeam, err := th.App.CreateTeam(&model.Team{
    29  		DisplayName: "Nerds",
    30  		Name:        "zz" + model.NewId(),
    31  		Email:       "nerds@test.com",
    32  		Type:        model.TEAM_INVITE,
    33  	})
    34  	if err != nil {
    35  		t.Errorf("test team not created: %s", err.Error())
    36  	}
    37  
    38  	practiceChannel, err := th.App.CreateChannel(&model.Channel{
    39  		TeamId:      singersTeam.Id,
    40  		DisplayName: "Practices",
    41  		Name:        model.NewId(),
    42  		Type:        model.CHANNEL_OPEN,
    43  	}, false)
    44  	if err != nil {
    45  		t.Errorf("test channel not created: %s", err.Error())
    46  	}
    47  
    48  	experimentsChannel, err := th.App.CreateChannel(&model.Channel{
    49  		TeamId:      singersTeam.Id,
    50  		DisplayName: "Experiments",
    51  		Name:        model.NewId(),
    52  		Type:        model.CHANNEL_PRIVATE,
    53  	}, false)
    54  	if err != nil {
    55  		t.Errorf("test channel not created: %s", err.Error())
    56  	}
    57  
    58  	gleeGroup, err := th.App.CreateGroup(&model.Group{
    59  		Name:        model.NewString(model.NewId()),
    60  		DisplayName: "Glee Club",
    61  		RemoteId:    model.NewId(),
    62  		Source:      model.GroupSourceLdap,
    63  	})
    64  	if err != nil {
    65  		t.Errorf("test group not created: %s", err.Error())
    66  	}
    67  
    68  	scienceGroup, err := th.App.CreateGroup(&model.Group{
    69  		Name:        model.NewString(model.NewId()),
    70  		DisplayName: "Science Club",
    71  		RemoteId:    model.NewId(),
    72  		Source:      model.GroupSourceLdap,
    73  	})
    74  	if err != nil {
    75  		t.Errorf("test group not created: %s", err.Error())
    76  	}
    77  
    78  	_, err = th.App.UpsertGroupSyncable(model.NewGroupChannel(gleeGroup.Id, practiceChannel.Id, true))
    79  	if err != nil {
    80  		t.Errorf("test groupchannel not created: %s", err.Error())
    81  	}
    82  
    83  	scienceTeamGroupSyncable, err := th.App.UpsertGroupSyncable(model.NewGroupTeam(scienceGroup.Id, nerdsTeam.Id, false))
    84  	if err != nil {
    85  		t.Errorf("test groupteam not created: %s", err.Error())
    86  	}
    87  
    88  	scienceChannelGroupSyncable, err := th.App.UpsertGroupSyncable(model.NewGroupChannel(scienceGroup.Id, experimentsChannel.Id, false))
    89  	if err != nil {
    90  		t.Errorf("test groupchannel not created: %s", err.Error())
    91  	}
    92  
    93  	singer1 := th.BasicUser
    94  	scientist1 := th.BasicUser2
    95  
    96  	_, err = th.App.UpsertGroupMember(gleeGroup.Id, singer1.Id)
    97  	if err != nil {
    98  		t.Errorf("test groupmember not created: %s", err.Error())
    99  	}
   100  
   101  	scientistGroupMember, err := th.App.UpsertGroupMember(scienceGroup.Id, scientist1.Id)
   102  	if err != nil {
   103  		t.Errorf("test groupmember not created: %s", err.Error())
   104  	}
   105  
   106  	pErr := th.App.CreateDefaultMemberships(0)
   107  	if pErr != nil {
   108  		t.Errorf("faild to populate syncables: %s", pErr.Error())
   109  	}
   110  
   111  	// Singer should be in team and channel
   112  	_, err = th.App.GetTeamMember(singersTeam.Id, singer1.Id)
   113  	if err != nil {
   114  		t.Errorf("error retrieving team member: %s", err.Error())
   115  	}
   116  	_, err = th.App.GetChannelMember(practiceChannel.Id, singer1.Id)
   117  	if err != nil {
   118  		t.Errorf("error retrieving channel member: %s", err.Error())
   119  	}
   120  
   121  	tMembers, err := th.App.GetTeamMembers(singersTeam.Id, 0, 999, nil)
   122  	if err != nil {
   123  		t.Errorf("error retrieving team members: %s", err.Error())
   124  	}
   125  	expected := 1
   126  	actual := len(tMembers)
   127  	if actual != expected {
   128  		t.Errorf("expected %d team members but got %d", expected, actual)
   129  	}
   130  
   131  	cMembersCount, err := th.App.GetChannelMemberCount(practiceChannel.Id)
   132  	if err != nil {
   133  		t.Errorf("error retrieving team members: %s", err.Error())
   134  	}
   135  	if cMembersCount != int64(expected) {
   136  		t.Errorf("expected %d team member but got %d", expected, cMembersCount)
   137  	}
   138  
   139  	// Scientist should not be in team or channel
   140  	_, err = th.App.GetTeamMember(nerdsTeam.Id, scientist1.Id)
   141  	if err.Id != "app.team.get_member.missing.app_error" {
   142  		t.Errorf("wrong error: %s", err.Id)
   143  	}
   144  
   145  	_, err = th.App.GetChannelMember(experimentsChannel.Id, scientist1.Id)
   146  	if err.Id != "app.channel.get_member.missing.app_error" {
   147  		t.Errorf("wrong error: %s", err.Id)
   148  	}
   149  
   150  	tMembers, err = th.App.GetTeamMembers(nerdsTeam.Id, 0, 999, nil)
   151  	if err != nil {
   152  		t.Errorf("error retrieving team members: %s", err.Error())
   153  	}
   154  	expected = 0
   155  	actual = len(tMembers)
   156  	if actual != expected {
   157  		t.Errorf("expected %d team members but got %d", expected, actual)
   158  	}
   159  
   160  	cMembersCount, err = th.App.GetChannelMemberCount(experimentsChannel.Id)
   161  	if err != nil {
   162  		t.Errorf("error retrieving team members: %s", err.Error())
   163  	}
   164  	if cMembersCount != int64(expected) {
   165  		t.Errorf("expected %d team members but got %d", expected, cMembersCount)
   166  	}
   167  
   168  	// update AutoAdd to true
   169  	scienceTeamGroupSyncable.AutoAdd = true
   170  	scienceTeamGroupSyncable, err = th.App.UpdateGroupSyncable(scienceTeamGroupSyncable)
   171  	if err != nil {
   172  		t.Errorf("error updating group syncable: %s", err.Error())
   173  	}
   174  
   175  	// Sync everything after syncable was created (proving that team updates trigger re-sync)
   176  	pErr = th.App.CreateDefaultMemberships(scientistGroupMember.CreateAt + 1)
   177  	if pErr != nil {
   178  		t.Errorf("faild to populate syncables: %s", pErr.Error())
   179  	}
   180  
   181  	// Scientist should be in team but not the channel
   182  	_, err = th.App.GetTeamMember(nerdsTeam.Id, scientist1.Id)
   183  	if err != nil {
   184  		t.Errorf("error retrieving team member: %s", err.Error())
   185  	}
   186  
   187  	_, err = th.App.GetChannelMember(experimentsChannel.Id, scientist1.Id)
   188  	if err.Id != "app.channel.get_member.missing.app_error" {
   189  		t.Errorf("wrong error: %s", err.Id)
   190  	}
   191  
   192  	tMembers, err = th.App.GetTeamMembers(nerdsTeam.Id, 0, 999, nil)
   193  	if err != nil {
   194  		t.Errorf("error retrieving team members: %s", err.Error())
   195  	}
   196  	expected = 1
   197  	actual = len(tMembers)
   198  	if actual != expected {
   199  		t.Errorf("expected %d team members but got %d", expected, actual)
   200  	}
   201  
   202  	expected = 0
   203  	cMembersCount, err = th.App.GetChannelMemberCount(experimentsChannel.Id)
   204  	if err != nil {
   205  		t.Errorf("error retrieving team members: %s", err.Error())
   206  	}
   207  	if cMembersCount != int64(expected) {
   208  		t.Errorf("expected %d team members but got %d", expected, cMembersCount)
   209  	}
   210  
   211  	// Update the channel syncable
   212  	scienceChannelGroupSyncable.AutoAdd = true
   213  	scienceChannelGroupSyncable, err = th.App.UpdateGroupSyncable(scienceChannelGroupSyncable)
   214  	if err != nil {
   215  		t.Errorf("error updating group syncable: %s", err.Error())
   216  	}
   217  
   218  	// Sync everything after syncable was created (proving that channel updates trigger re-sync)
   219  	pErr = th.App.CreateDefaultMemberships(scientistGroupMember.CreateAt + 1)
   220  	if pErr != nil {
   221  		t.Errorf("faild to populate syncables: %s", pErr.Error())
   222  	}
   223  
   224  	expected = 1
   225  	cMembersCount, err = th.App.GetChannelMemberCount(experimentsChannel.Id)
   226  	if err != nil {
   227  		t.Errorf("error retrieving team members: %s", err.Error())
   228  	}
   229  	if cMembersCount != int64(expected) {
   230  		t.Errorf("expected %d team members but got %d", expected, cMembersCount)
   231  	}
   232  
   233  	// singer leaves team and channel
   234  	err = th.App.LeaveChannel(practiceChannel.Id, singer1.Id)
   235  	if err != nil {
   236  		t.Errorf("error leaving channel: %s", err.Error())
   237  	}
   238  	err = th.App.LeaveTeam(singersTeam, singer1, "")
   239  	if err != nil {
   240  		t.Errorf("error leaving team: %s", err.Error())
   241  	}
   242  
   243  	// Even re-syncing from the beginning doesn't re-add to channel or team
   244  	pErr = th.App.CreateDefaultMemberships(0)
   245  	if pErr != nil {
   246  		t.Errorf("faild to populate syncables: %s", pErr.Error())
   247  	}
   248  
   249  	// Singer should not be in team or channel
   250  	tMember, err := th.App.GetTeamMember(singersTeam.Id, singer1.Id)
   251  	if err != nil {
   252  		t.Errorf("error retrieving team member: %s", err.Error())
   253  	}
   254  	if tMember.DeleteAt == 0 {
   255  		t.Error("expected team member to remain deleted")
   256  	}
   257  
   258  	_, err = th.App.GetChannelMember(practiceChannel.Id, singer1.Id)
   259  	if err == nil {
   260  		t.Error("Expected channel member to remain deleted")
   261  	}
   262  
   263  	// Ensure members are in channel
   264  	_, err = th.App.AddChannelMember(scientist1.Id, experimentsChannel, "", "")
   265  	if err != nil {
   266  		t.Errorf("unable to add user to channel: %s", err.Error())
   267  	}
   268  
   269  	// Add other user so that user can leave channel
   270  	_, err = th.App.AddTeamMember(singersTeam.Id, singer1.Id)
   271  	if err != nil {
   272  		t.Errorf("unable to add user to team: %s", err.Error())
   273  	}
   274  	_, err = th.App.AddChannelMember(singer1.Id, experimentsChannel, "", "")
   275  	if err != nil {
   276  		t.Errorf("unable to add user to channel: %s", err.Error())
   277  	}
   278  
   279  	// the channel syncable is updated
   280  	scienceChannelGroupSyncable, err = th.App.UpdateGroupSyncable(scienceChannelGroupSyncable)
   281  	if err != nil {
   282  		t.Errorf("error updating group syncable: %s", err.Error())
   283  	}
   284  
   285  	pErr = th.App.CreateDefaultMemberships(0)
   286  	if pErr != nil {
   287  		t.Errorf("faild to populate syncables: %s", pErr.Error())
   288  	}
   289  
   290  	timeBeforeLeaving := model.GetMillis()
   291  
   292  	// User leaves channel
   293  	err = th.App.LeaveChannel(experimentsChannel.Id, scientist1.Id)
   294  	if err != nil {
   295  		t.Errorf("unable to add user to channel: %s", err.Error())
   296  	}
   297  
   298  	timeAfterLeaving := model.GetMillis()
   299  
   300  	// Purging channelmemberhistory doesn't re-add user to channel
   301  	_, nErr := th.App.Srv().Store.ChannelMemberHistory().PermanentDeleteBatch(timeBeforeLeaving, 1000)
   302  	if nErr != nil {
   303  		t.Errorf("error permanently deleting channelmemberhistory: %s", nErr.Error())
   304  	}
   305  
   306  	pErr = th.App.CreateDefaultMemberships(scienceChannelGroupSyncable.UpdateAt)
   307  	if pErr != nil {
   308  		t.Errorf("failed to populate syncables: %s", pErr.Error())
   309  	}
   310  
   311  	_, err = th.App.GetChannelMember(experimentsChannel.Id, scientist1.Id)
   312  	if err == nil {
   313  		t.Error("Expected channel member to remain deleted")
   314  	}
   315  
   316  	// Purging channelmemberhistory doesn't re-add user to channel
   317  	_, nErr = th.App.Srv().Jobs.Store.ChannelMemberHistory().PermanentDeleteBatch(timeAfterLeaving, 1000)
   318  	if nErr != nil {
   319  		t.Errorf("error permanently deleting channelmemberhistory: %s", nErr.Error())
   320  	}
   321  
   322  	pErr = th.App.CreateDefaultMemberships(scienceChannelGroupSyncable.UpdateAt)
   323  	if pErr != nil {
   324  		t.Errorf("failed to populate syncables: %s", pErr.Error())
   325  	}
   326  
   327  	// Channel member is re-added.
   328  	_, err = th.App.GetChannelMember(experimentsChannel.Id, scientist1.Id)
   329  	if err != nil {
   330  		t.Errorf("expected channel member: %s", err.Error())
   331  	}
   332  
   333  	t.Run("Team with restricted domains skips over members that do not match the allowed domains", func(t *testing.T) {
   334  		restrictedUser := th.CreateUser()
   335  		restrictedUser.Email = "restricted@mattermost.org"
   336  		_, err = th.App.UpdateUser(restrictedUser, false)
   337  		require.Nil(t, err)
   338  		_, err = th.App.UpsertGroupMember(scienceGroup.Id, restrictedUser.Id)
   339  		require.Nil(t, err)
   340  
   341  		restrictedTeam, err := th.App.CreateTeam(&model.Team{
   342  			DisplayName:    "Restricted",
   343  			Name:           "restricted" + model.NewId(),
   344  			Email:          "restricted@mattermost.org",
   345  			AllowedDomains: "mattermost.org",
   346  			Type:           model.TEAM_OPEN,
   347  		})
   348  		require.Nil(t, err)
   349  		_, err = th.App.UpsertGroupSyncable(model.NewGroupTeam(scienceGroup.Id, restrictedTeam.Id, true))
   350  		require.Nil(t, err)
   351  
   352  		restrictedChannel, err := th.App.CreateChannel(&model.Channel{
   353  			TeamId:      restrictedTeam.Id,
   354  			DisplayName: "Restricted",
   355  			Name:        "restricted" + model.NewId(),
   356  			Type:        model.CHANNEL_OPEN,
   357  		}, false)
   358  		require.Nil(t, err)
   359  		_, err = th.App.UpsertGroupSyncable(model.NewGroupChannel(scienceGroup.Id, restrictedChannel.Id, true))
   360  		require.Nil(t, err)
   361  
   362  		pErr = th.App.CreateDefaultMemberships(0)
   363  		require.NoError(t, pErr)
   364  
   365  		// Ensure only the restricted user was added to both the team and channel
   366  		cMembersCount, err = th.App.GetChannelMemberCount(restrictedChannel.Id)
   367  		require.Nil(t, err)
   368  		require.Equal(t, cMembersCount, int64(1))
   369  		tmembers, err := th.App.GetTeamMembers(restrictedTeam.Id, 0, 100, nil)
   370  		require.Nil(t, err)
   371  		require.Len(t, tmembers, 1)
   372  		require.Equal(t, tmembers[0].UserId, restrictedUser.Id)
   373  	})
   374  }
   375  
   376  func TestDeleteGroupMemberships(t *testing.T) {
   377  	th := Setup(t).InitBasic()
   378  	defer th.TearDown()
   379  
   380  	group := th.CreateGroup()
   381  
   382  	userIDs := []string{th.BasicUser.Id, th.BasicUser2.Id, th.SystemAdminUser.Id}
   383  
   384  	var err *model.AppError
   385  	// add users to teams and channels
   386  	for _, userID := range userIDs {
   387  		_, err = th.App.AddTeamMember(th.BasicTeam.Id, userID)
   388  		require.Nil(t, err)
   389  
   390  		_, err = th.App.AddChannelMember(userID, th.BasicChannel, "", "")
   391  		require.Nil(t, err)
   392  	}
   393  
   394  	// make team group-constrained
   395  	team := th.BasicTeam
   396  	team.GroupConstrained = model.NewBool(true)
   397  	team, err = th.App.UpdateTeam(team)
   398  	require.Nil(t, err)
   399  	require.True(t, *team.GroupConstrained)
   400  
   401  	// make channel group-constrained
   402  	channel := th.BasicChannel
   403  	channel.GroupConstrained = model.NewBool(true)
   404  	channel, err = th.App.UpdateChannel(channel)
   405  	require.Nil(t, err)
   406  	require.True(t, *channel.GroupConstrained)
   407  
   408  	// create groupteam and groupchannel
   409  	_, err = th.App.UpsertGroupSyncable(model.NewGroupTeam(group.Id, team.Id, true))
   410  	require.Nil(t, err)
   411  	_, err = th.App.UpsertGroupSyncable(model.NewGroupChannel(group.Id, channel.Id, true))
   412  	require.Nil(t, err)
   413  
   414  	// verify the member count
   415  	tmembers, err := th.App.GetTeamMembers(th.BasicTeam.Id, 0, 100, nil)
   416  	require.Nil(t, err)
   417  	require.Len(t, tmembers, 3)
   418  
   419  	cmemberCount, err := th.App.GetChannelMemberCount(th.BasicChannel.Id)
   420  	require.Nil(t, err)
   421  	require.Equal(t, 3, int(cmemberCount))
   422  
   423  	// add a user to the group
   424  	_, err = th.App.UpsertGroupMember(group.Id, th.SystemAdminUser.Id)
   425  	require.Nil(t, err)
   426  
   427  	// run the delete
   428  	appErr := th.App.DeleteGroupConstrainedMemberships()
   429  	require.NoError(t, appErr)
   430  
   431  	// verify the new member counts
   432  	tmembers, err = th.App.GetTeamMembers(th.BasicTeam.Id, 0, 100, nil)
   433  	require.Nil(t, err)
   434  	require.Len(t, tmembers, 1)
   435  	require.Equal(t, th.SystemAdminUser.Id, tmembers[0].UserId)
   436  
   437  	cmembers, err := th.App.GetChannelMembersPage(channel.Id, 0, 99)
   438  	require.Nil(t, err)
   439  	require.Len(t, (*cmembers), 1)
   440  	require.Equal(t, th.SystemAdminUser.Id, (*cmembers)[0].UserId)
   441  }
   442  
   443  func TestSyncSyncableRoles(t *testing.T) {
   444  	th := Setup(t).InitBasic()
   445  	defer th.TearDown()
   446  
   447  	team := th.CreateTeam()
   448  
   449  	channel := th.CreateChannel(team)
   450  	channel.GroupConstrained = model.NewBool(true)
   451  	channel, err := th.App.UpdateChannel(channel)
   452  	require.Nil(t, err)
   453  
   454  	user1 := th.CreateUser()
   455  	user2 := th.CreateUser()
   456  	group := th.CreateGroup()
   457  
   458  	teamSyncable, err := th.App.UpsertGroupSyncable(&model.GroupSyncable{
   459  		SyncableId: team.Id,
   460  		Type:       model.GroupSyncableTypeTeam,
   461  		GroupId:    group.Id,
   462  	})
   463  	require.Nil(t, err)
   464  
   465  	channelSyncable, err := th.App.UpsertGroupSyncable(&model.GroupSyncable{
   466  		SyncableId: channel.Id,
   467  		Type:       model.GroupSyncableTypeChannel,
   468  		GroupId:    group.Id,
   469  	})
   470  	require.Nil(t, err)
   471  
   472  	for _, user := range []*model.User{user1, user2} {
   473  		_, err = th.App.UpsertGroupMember(group.Id, user.Id)
   474  		require.Nil(t, err)
   475  
   476  		var tm *model.TeamMember
   477  		tm, err = th.App.AddTeamMember(team.Id, user.Id)
   478  		require.Nil(t, err)
   479  		require.False(t, tm.SchemeAdmin)
   480  
   481  		cm := th.AddUserToChannel(user, channel)
   482  		require.False(t, cm.SchemeAdmin)
   483  	}
   484  
   485  	teamSyncable.SchemeAdmin = true
   486  	_, err = th.App.UpdateGroupSyncable(teamSyncable)
   487  	require.Nil(t, err)
   488  
   489  	channelSyncable.SchemeAdmin = true
   490  	_, err = th.App.UpdateGroupSyncable(channelSyncable)
   491  	require.Nil(t, err)
   492  
   493  	err = th.App.SyncSyncableRoles(channel.Id, model.GroupSyncableTypeChannel)
   494  	require.Nil(t, err)
   495  
   496  	err = th.App.SyncSyncableRoles(team.Id, model.GroupSyncableTypeTeam)
   497  	require.Nil(t, err)
   498  
   499  	for _, user := range []*model.User{user1, user2} {
   500  		tm, err := th.App.GetTeamMember(team.Id, user.Id)
   501  		require.Nil(t, err)
   502  		require.True(t, tm.SchemeAdmin)
   503  
   504  		cm, err := th.App.GetChannelMember(channel.Id, user.Id)
   505  		require.Nil(t, err)
   506  		require.True(t, cm.SchemeAdmin)
   507  	}
   508  }