Team/Channel members bulk save/update/delete (#14053)
* Members Save Multiple * Multiple Channel Members implemented * Working version with member multi save and multi update * Adding tests to the save multiple team members store methods * Tests passing for SaveMember * Adding remove members tests * Working on channel store tests * More work on testing properly SaveMember and SaveMultipleMembers on channels * More work on testing properly SaveMember and SaveMultipleMembers on teams * Adding tests for update multiple members for team * Adding tests for update multiple members for channel * Fixing some tets * Fixing tests * Fixing tests * Fixing i18n * Addressing govet problems * Addressing govet problems * Addressing govet problems * Addressing govet problems * Addressing PR comments (and removing TODO) * Addressing PR comments * Fixed broken test * Removing unnecesary i18n translation string
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
d2848cc167
Коммит
cfe65a33a5
@@ -1526,6 +1526,363 @@ func TestImportImportUser(t *testing.T) {
|
||||
assert.Equal(t, "", channelMember.ExplicitRoles)
|
||||
}
|
||||
|
||||
func TestImportUserTeams(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
team2 := th.CreateTeam()
|
||||
channel2 := th.CreateChannel(th.BasicTeam)
|
||||
channel3 := th.CreateChannel(team2)
|
||||
customRole := th.CreateRole("test_custom_role")
|
||||
sampleTheme := "{\"test\":\"#abcdef\"}"
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
data *[]UserTeamImportData
|
||||
expectedError bool
|
||||
expectedUserTeams int
|
||||
expectedUserChannels int
|
||||
expectedExplicitRoles string
|
||||
expectedRoles string
|
||||
expectedTheme string
|
||||
}{
|
||||
{
|
||||
name: "Not existing team should fail",
|
||||
data: &[]UserTeamImportData{
|
||||
{
|
||||
Name: model.NewString("not-existing-team-name"),
|
||||
},
|
||||
},
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "nil data shouldn't do anything",
|
||||
expectedError: false,
|
||||
expectedUserTeams: 0,
|
||||
expectedUserChannels: 0,
|
||||
},
|
||||
{
|
||||
name: "Should fail if one of the roles doesn't exists",
|
||||
data: &[]UserTeamImportData{
|
||||
{
|
||||
Name: &th.BasicTeam.Name,
|
||||
Roles: model.NewString("not-existing-role"),
|
||||
},
|
||||
},
|
||||
expectedError: true,
|
||||
expectedUserTeams: 1,
|
||||
expectedUserChannels: 0,
|
||||
expectedExplicitRoles: "",
|
||||
expectedRoles: "team_user",
|
||||
},
|
||||
{
|
||||
name: "Should success to import explicit role",
|
||||
data: &[]UserTeamImportData{
|
||||
{
|
||||
Name: &th.BasicTeam.Name,
|
||||
Roles: &customRole.Name,
|
||||
},
|
||||
},
|
||||
expectedError: false,
|
||||
expectedUserTeams: 1,
|
||||
expectedUserChannels: 1,
|
||||
expectedExplicitRoles: customRole.Name,
|
||||
expectedRoles: customRole.Name + " team_user",
|
||||
},
|
||||
{
|
||||
name: "Should success to import admin role",
|
||||
data: &[]UserTeamImportData{
|
||||
{
|
||||
Name: &th.BasicTeam.Name,
|
||||
Roles: model.NewString(model.TEAM_ADMIN_ROLE_ID),
|
||||
},
|
||||
},
|
||||
expectedError: false,
|
||||
expectedUserTeams: 1,
|
||||
expectedUserChannels: 1,
|
||||
expectedExplicitRoles: "",
|
||||
expectedRoles: "team_user team_admin",
|
||||
},
|
||||
{
|
||||
name: "Should success to import with theme",
|
||||
data: &[]UserTeamImportData{
|
||||
{
|
||||
Name: &th.BasicTeam.Name,
|
||||
Theme: &sampleTheme,
|
||||
},
|
||||
},
|
||||
expectedError: false,
|
||||
expectedUserTeams: 1,
|
||||
expectedUserChannels: 1,
|
||||
expectedExplicitRoles: "",
|
||||
expectedRoles: "team_user",
|
||||
expectedTheme: sampleTheme,
|
||||
},
|
||||
{
|
||||
name: "Team without channels must add the default channel",
|
||||
data: &[]UserTeamImportData{
|
||||
{
|
||||
Name: &th.BasicTeam.Name,
|
||||
},
|
||||
},
|
||||
expectedError: false,
|
||||
expectedUserTeams: 1,
|
||||
expectedUserChannels: 1,
|
||||
expectedExplicitRoles: "",
|
||||
expectedRoles: "team_user",
|
||||
},
|
||||
{
|
||||
name: "Team with default channel must add only the default channel",
|
||||
data: &[]UserTeamImportData{
|
||||
{
|
||||
Name: &th.BasicTeam.Name,
|
||||
Channels: &[]UserChannelImportData{
|
||||
{
|
||||
Name: ptrStr(model.DEFAULT_CHANNEL),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: false,
|
||||
expectedUserTeams: 1,
|
||||
expectedUserChannels: 1,
|
||||
expectedExplicitRoles: "",
|
||||
expectedRoles: "team_user",
|
||||
},
|
||||
{
|
||||
name: "Team with non default channel must add default channel and the other channel",
|
||||
data: &[]UserTeamImportData{
|
||||
{
|
||||
Name: &th.BasicTeam.Name,
|
||||
Channels: &[]UserChannelImportData{
|
||||
{
|
||||
Name: &th.BasicChannel.Name,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: false,
|
||||
expectedUserTeams: 1,
|
||||
expectedUserChannels: 2,
|
||||
expectedExplicitRoles: "",
|
||||
expectedRoles: "team_user",
|
||||
},
|
||||
{
|
||||
name: "Multiple teams with multiple channels each",
|
||||
data: &[]UserTeamImportData{
|
||||
{
|
||||
Name: &th.BasicTeam.Name,
|
||||
Channels: &[]UserChannelImportData{
|
||||
{
|
||||
Name: &th.BasicChannel.Name,
|
||||
},
|
||||
{
|
||||
Name: &channel2.Name,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: &team2.Name,
|
||||
Channels: &[]UserChannelImportData{
|
||||
{
|
||||
Name: &channel3.Name,
|
||||
},
|
||||
{
|
||||
Name: model.NewString("town-square"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedError: false,
|
||||
expectedUserTeams: 2,
|
||||
expectedUserChannels: 5,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
user := th.CreateUser()
|
||||
|
||||
// Two times import must end with the same results
|
||||
for x := 0; x < 2; x++ {
|
||||
err := th.App.importUserTeams(user, tc.data)
|
||||
if tc.expectedError {
|
||||
require.NotNil(t, err)
|
||||
} else {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
teamMembers, err := th.App.Srv().Store.Team().GetTeamsForUser(user.Id)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, tc.expectedUserTeams)
|
||||
if tc.expectedUserTeams == 1 {
|
||||
require.Equal(t, tc.expectedExplicitRoles, teamMembers[0].ExplicitRoles, "Not matching expected explicit roles")
|
||||
require.Equal(t, tc.expectedRoles, teamMembers[0].Roles, "not matching expected roles")
|
||||
if tc.expectedTheme != "" {
|
||||
pref, prefErr := th.App.Srv().Store.Preference().Get(user.Id, model.PREFERENCE_CATEGORY_THEME, teamMembers[0].TeamId)
|
||||
require.Nil(t, prefErr)
|
||||
require.Equal(t, tc.expectedTheme, pref.Value)
|
||||
}
|
||||
}
|
||||
|
||||
totalMembers := 0
|
||||
for _, teamMember := range teamMembers {
|
||||
channelMembers, err := th.App.Srv().Store.Channel().GetMembersForUser(teamMember.TeamId, user.Id)
|
||||
require.Nil(t, err)
|
||||
totalMembers += len(*channelMembers)
|
||||
}
|
||||
require.Equal(t, tc.expectedUserChannels, totalMembers)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("Should fail if the MaxUserPerTeam is reached", func(t *testing.T) {
|
||||
user := th.CreateUser()
|
||||
data := &[]UserTeamImportData{
|
||||
{
|
||||
Name: &th.BasicTeam.Name,
|
||||
},
|
||||
}
|
||||
th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.MaxUsersPerTeam = 1 })
|
||||
defer th.App.UpdateConfig(func(cfg *model.Config) { *cfg.TeamSettings.MaxUsersPerTeam = 100 })
|
||||
err := th.App.importUserTeams(user, data)
|
||||
require.NotNil(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestImportUserChannels(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
channel2 := th.CreateChannel(th.BasicTeam)
|
||||
customRole := th.CreateRole("test_custom_role")
|
||||
sampleNotifyProps := UserChannelNotifyPropsImportData{
|
||||
Desktop: model.NewString("all"),
|
||||
Mobile: model.NewString("none"),
|
||||
MarkUnread: model.NewString("all"),
|
||||
}
|
||||
|
||||
tt := []struct {
|
||||
name string
|
||||
data *[]UserChannelImportData
|
||||
expectedError bool
|
||||
expectedUserChannels int
|
||||
expectedExplicitRoles string
|
||||
expectedRoles string
|
||||
expectedNotifyProps *UserChannelNotifyPropsImportData
|
||||
}{
|
||||
{
|
||||
name: "Not existing channel should fail",
|
||||
data: &[]UserChannelImportData{
|
||||
{
|
||||
Name: model.NewString("not-existing-channel-name"),
|
||||
},
|
||||
},
|
||||
expectedError: true,
|
||||
},
|
||||
{
|
||||
name: "nil data shouldn't do anything",
|
||||
expectedError: false,
|
||||
expectedUserChannels: 0,
|
||||
},
|
||||
{
|
||||
name: "Should fail if one of the roles doesn't exists",
|
||||
data: &[]UserChannelImportData{
|
||||
{
|
||||
Name: &th.BasicChannel.Name,
|
||||
Roles: model.NewString("not-existing-role"),
|
||||
},
|
||||
},
|
||||
expectedError: true,
|
||||
expectedUserChannels: 1,
|
||||
expectedExplicitRoles: "",
|
||||
expectedRoles: "channel_user",
|
||||
},
|
||||
{
|
||||
name: "Should success to import explicit role",
|
||||
data: &[]UserChannelImportData{
|
||||
{
|
||||
Name: &th.BasicChannel.Name,
|
||||
Roles: &customRole.Name,
|
||||
},
|
||||
},
|
||||
expectedError: false,
|
||||
expectedUserChannels: 1,
|
||||
expectedExplicitRoles: customRole.Name,
|
||||
expectedRoles: customRole.Name + " channel_user",
|
||||
},
|
||||
{
|
||||
name: "Should success to import admin role",
|
||||
data: &[]UserChannelImportData{
|
||||
{
|
||||
Name: &th.BasicChannel.Name,
|
||||
Roles: model.NewString(model.CHANNEL_ADMIN_ROLE_ID),
|
||||
},
|
||||
},
|
||||
expectedError: false,
|
||||
expectedUserChannels: 1,
|
||||
expectedExplicitRoles: "",
|
||||
expectedRoles: "channel_user channel_admin",
|
||||
},
|
||||
{
|
||||
name: "Should success to import with notifyProps",
|
||||
data: &[]UserChannelImportData{
|
||||
{
|
||||
Name: &th.BasicChannel.Name,
|
||||
NotifyProps: &sampleNotifyProps,
|
||||
},
|
||||
},
|
||||
expectedError: false,
|
||||
expectedUserChannels: 1,
|
||||
expectedExplicitRoles: "",
|
||||
expectedRoles: "channel_user",
|
||||
expectedNotifyProps: &sampleNotifyProps,
|
||||
},
|
||||
{
|
||||
name: "Should import properly multiple channels",
|
||||
data: &[]UserChannelImportData{
|
||||
{
|
||||
Name: &th.BasicChannel.Name,
|
||||
},
|
||||
{
|
||||
Name: &channel2.Name,
|
||||
},
|
||||
},
|
||||
expectedError: false,
|
||||
expectedUserChannels: 2,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tt {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
user := th.CreateUser()
|
||||
th.App.joinUserToTeam(th.BasicTeam, user)
|
||||
teamMember, err := th.App.GetTeamMember(th.BasicTeam.Id, user.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
// Two times import must end with the same results
|
||||
for x := 0; x < 2; x++ {
|
||||
err = th.App.importUserChannels(user, th.BasicTeam, teamMember, tc.data)
|
||||
if tc.expectedError {
|
||||
require.NotNil(t, err)
|
||||
} else {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
channelMembers, err := th.App.Srv().Store.Channel().GetMembersForUser(th.BasicTeam.Id, user.Id)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, *channelMembers, tc.expectedUserChannels)
|
||||
if tc.expectedUserChannels == 1 {
|
||||
channelMember := (*channelMembers)[0]
|
||||
require.Equal(t, tc.expectedExplicitRoles, channelMember.ExplicitRoles, "Not matching expected explicit roles")
|
||||
require.Equal(t, tc.expectedRoles, channelMember.Roles, "not matching expected roles")
|
||||
if tc.expectedNotifyProps != nil {
|
||||
require.Equal(t, *tc.expectedNotifyProps.Desktop, channelMember.NotifyProps[model.DESKTOP_NOTIFY_PROP])
|
||||
require.Equal(t, *tc.expectedNotifyProps.Mobile, channelMember.NotifyProps[model.PUSH_NOTIFY_PROP])
|
||||
require.Equal(t, *tc.expectedNotifyProps.MarkUnread, channelMember.NotifyProps[model.MARK_UNREAD_NOTIFY_PROP])
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestImportUserDefaultNotifyProps(t *testing.T) {
|
||||
th := Setup(t)
|
||||
defer th.TearDown()
|
||||
|
||||
Ссылка в новой задаче
Block a user