diff --git a/server/channels/app/app_iface.go b/server/channels/app/app_iface.go index 631f7b3ae4..cd8bdbdb53 100644 --- a/server/channels/app/app_iface.go +++ b/server/channels/app/app_iface.go @@ -97,7 +97,7 @@ type AppIface interface { // are configured to sync with teams and channels for group members on or after the given timestamp. // If includeRemovedMembers is true, then members who left or were removed from a team/channel will // be re-added; otherwise, they will not be re-added. - CreateDefaultMemberships(c request.CTX, params model.CreateDefaultMembershipParams) error + CreateDefaultMemberships(rctx request.CTX, params model.CreateDefaultMembershipParams) error // CreateGuest creates a guest and sets several fields of the returned User struct to // their zero values. CreateGuest(c request.CTX, user *model.User) (*model.User, *model.AppError) @@ -121,7 +121,7 @@ type AppIface interface { DeleteChannelScheme(c request.CTX, channel *model.Channel) (*model.Channel, *model.AppError) // DeleteGroupConstrainedMemberships deletes team and channel memberships of users who aren't members of the allowed // groups of all group-constrained teams and channels. - DeleteGroupConstrainedMemberships(c request.CTX) error + DeleteGroupConstrainedMemberships(rctx request.CTX) error // DeletePersistentNotification stops the persistent notifications. DeletePersistentNotification(c request.CTX, post *model.Post) *model.AppError // DeletePublicKey will delete plugin public key from the config. @@ -355,13 +355,13 @@ type AppIface interface { SyncPlugins() *model.AppError // SyncRolesAndMembership updates the SchemeAdmin status and membership of all of the members of the given // syncable. - SyncRolesAndMembership(c request.CTX, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) + SyncRolesAndMembership(rctx request.CTX, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) // SyncSharedChannel forces a shared channel to send any changed content to all remote clusters. SyncSharedChannel(channelID string) error // SyncSyncableRoles updates the SchemeAdmin field value of the given syncable's members based on the configuration of // the member's group memberships and the configuration of those groups to the syncable. This method should only // be invoked on group-synced (aka group-constrained) syncables. - SyncSyncableRoles(syncableID string, syncableType model.GroupSyncableType) *model.AppError + SyncSyncableRoles(rctx request.CTX, syncableID string, syncableType model.GroupSyncableType) *model.AppError // TeamMembersMinusGroupMembers returns the set of users on the given team minus the set of users in the given // groups. // diff --git a/server/channels/app/opentracing/opentracing_layer.go b/server/channels/app/opentracing/opentracing_layer.go index 880ff19f4e..ce0a670e27 100644 --- a/server/channels/app/opentracing/opentracing_layer.go +++ b/server/channels/app/opentracing/opentracing_layer.go @@ -2192,7 +2192,7 @@ func (a *OpenTracingAppLayer) CreateCommandWebhook(commandID string, args *model return resultVar0, resultVar1 } -func (a *OpenTracingAppLayer) CreateDefaultMemberships(c request.CTX, params model.CreateDefaultMembershipParams) error { +func (a *OpenTracingAppLayer) CreateDefaultMemberships(rctx request.CTX, params model.CreateDefaultMembershipParams) error { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.CreateDefaultMemberships") @@ -2204,7 +2204,7 @@ func (a *OpenTracingAppLayer) CreateDefaultMemberships(c request.CTX, params mod }() defer span.Finish() - resultVar0 := a.app.CreateDefaultMemberships(c, params) + resultVar0 := a.app.CreateDefaultMemberships(rctx, params) if resultVar0 != nil { span.LogFields(spanlog.Error(resultVar0)) @@ -3346,7 +3346,7 @@ func (a *OpenTracingAppLayer) DeleteGroup(groupID string) (*model.Group, *model. return resultVar0, resultVar1 } -func (a *OpenTracingAppLayer) DeleteGroupConstrainedMemberships(c request.CTX) error { +func (a *OpenTracingAppLayer) DeleteGroupConstrainedMemberships(rctx request.CTX) error { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.DeleteGroupConstrainedMemberships") @@ -3358,7 +3358,7 @@ func (a *OpenTracingAppLayer) DeleteGroupConstrainedMemberships(c request.CTX) e }() defer span.Finish() - resultVar0 := a.app.DeleteGroupConstrainedMemberships(c) + resultVar0 := a.app.DeleteGroupConstrainedMemberships(rctx) if resultVar0 != nil { span.LogFields(spanlog.Error(resultVar0)) @@ -17217,7 +17217,7 @@ func (a *OpenTracingAppLayer) SyncPlugins() *model.AppError { return resultVar0 } -func (a *OpenTracingAppLayer) SyncRolesAndMembership(c request.CTX, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) { +func (a *OpenTracingAppLayer) SyncRolesAndMembership(rctx request.CTX, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SyncRolesAndMembership") @@ -17229,7 +17229,7 @@ func (a *OpenTracingAppLayer) SyncRolesAndMembership(c request.CTX, syncableID s }() defer span.Finish() - a.app.SyncRolesAndMembership(c, syncableID, syncableType, includeRemovedMembers) + a.app.SyncRolesAndMembership(rctx, syncableID, syncableType, includeRemovedMembers) } func (a *OpenTracingAppLayer) SyncSharedChannel(channelID string) error { @@ -17254,7 +17254,7 @@ func (a *OpenTracingAppLayer) SyncSharedChannel(channelID string) error { return resultVar0 } -func (a *OpenTracingAppLayer) SyncSyncableRoles(syncableID string, syncableType model.GroupSyncableType) *model.AppError { +func (a *OpenTracingAppLayer) SyncSyncableRoles(rctx request.CTX, syncableID string, syncableType model.GroupSyncableType) *model.AppError { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SyncSyncableRoles") @@ -17266,7 +17266,7 @@ func (a *OpenTracingAppLayer) SyncSyncableRoles(syncableID string, syncableType }() defer span.Finish() - resultVar0 := a.app.SyncSyncableRoles(syncableID, syncableType) + resultVar0 := a.app.SyncSyncableRoles(rctx, syncableID, syncableType) if resultVar0 != nil { span.LogFields(spanlog.Error(resultVar0)) diff --git a/server/channels/app/syncables.go b/server/channels/app/syncables.go index 390409ca04..45d293cd98 100644 --- a/server/channels/app/syncables.go +++ b/server/channels/app/syncables.go @@ -8,6 +8,7 @@ import ( "net/http" "strings" + "github.com/hashicorp/go-multierror" "github.com/mattermost/mattermost/server/public/model" "github.com/mattermost/mattermost/server/public/shared/mlog" "github.com/mattermost/mattermost/server/public/shared/request" @@ -18,67 +19,68 @@ import ( // only that channel's members are created. If channelID is nil all channel memberships are created. // If includeRemovedMembers is true, then channel members who left or were removed from the channel will // be re-added; otherwise, they will not be re-added. -func (a *App) createDefaultChannelMemberships(c request.CTX, params model.CreateDefaultMembershipParams) error { +func (a *App) createDefaultChannelMemberships(rctx request.CTX, params model.CreateDefaultMembershipParams) error { channelMembers, appErr := a.ChannelMembersToAdd(params.Since, params.ScopedChannelID, params.ReAddRemovedMembers) if appErr != nil { return appErr } + var multiErr *multierror.Error for _, userChannel := range channelMembers { if params.ScopedUserID != nil && *params.ScopedUserID != userChannel.UserID { continue } - channel, err := a.GetChannel(c, userChannel.ChannelID) + + logger := rctx.Logger().With( + mlog.String("user_id", userChannel.UserID), + mlog.String("channel_id", userChannel.ChannelID), + ) + + channel, err := a.GetChannel(rctx, userChannel.ChannelID) if err != nil { - return err + multiErr = multierror.Append(multiErr, fmt.Errorf("failed to get channel for default channel membership: %w", err)) + continue } - tmem, err := a.GetTeamMember(c, channel.TeamId, userChannel.UserID) + tmem, err := a.GetTeamMember(rctx, channel.TeamId, userChannel.UserID) if err != nil && err.Id != "app.team.get_member.missing.app_error" { - return err + multiErr = multierror.Append(multiErr, fmt.Errorf("failed to get member for default channel membership: %w", err)) + continue } // First add user to team if tmem == nil { - _, err = a.AddTeamMember(c, channel.TeamId, userChannel.UserID) + _, err = a.AddTeamMember(rctx, channel.TeamId, userChannel.UserID) if err != nil { if err.Id == "api.team.join_user_to_team.allowed_domains.app_error" { - c.Logger().Info("User not added to channel - the domain associated with the user is not in the list of allowed team domains", - mlog.String("user_id", userChannel.UserID), - mlog.String("channel_id", userChannel.ChannelID), + logger.Info( + "User not added to channel - the domain associated with the user is not in the list of allowed team domains", mlog.String("team_id", channel.TeamId), ) - continue + } else { + multiErr = multierror.Append(multiErr, fmt.Errorf("failed to add team member for default channel membership: %w", err)) } - return err + continue } - c.Logger().Info("added teammember", - mlog.String("user_id", userChannel.UserID), - mlog.String("team_id", channel.TeamId), - ) + logger.Info("Added channel member for default channel membership") } - _, err = a.AddChannelMember(c, userChannel.UserID, channel, ChannelMemberOpts{ + _, err = a.AddChannelMember(rctx, userChannel.UserID, channel, ChannelMemberOpts{ SkipTeamMemberIntegrityCheck: true, }) if err != nil { if err.Id == "api.channel.add_user.to.channel.failed.deleted.app_error" { - c.Logger().Info("Not adding user to channel because they have already left the team", - mlog.String("user_id", userChannel.UserID), - mlog.String("channel_id", userChannel.ChannelID), - ) + logger.Info("Not adding user to channel because they have already left the team") } else { - return err + multiErr = multierror.Append(multiErr, fmt.Errorf("failed to add channel member for default channel membership: %w", err)) } + continue } - c.Logger().Info("added channelmember", - mlog.String("user_id", userChannel.UserID), - mlog.String("channel_id", userChannel.ChannelID), - ) + logger.Info("Added channel member for default channel membership") } - return nil + return multiErr.ErrorOrNil() } // createDefaultTeamMemberships adds users to teams based on their group memberships and how those groups are @@ -86,48 +88,50 @@ func (a *App) createDefaultChannelMemberships(c request.CTX, params model.Create // only that team's members are created. If teamID is nil all team memberships are created. // If includeRemovedMembers is true, then team members who left or were removed from the team will // be re-added; otherwise, they will not be re-added. -func (a *App) createDefaultTeamMemberships(c request.CTX, params model.CreateDefaultMembershipParams) error { +func (a *App) createDefaultTeamMemberships(rctx request.CTX, params model.CreateDefaultMembershipParams) error { teamMembers, appErr := a.TeamMembersToAdd(params.Since, params.ScopedTeamID, params.ReAddRemovedMembers) if appErr != nil { return appErr } + var multiErr *multierror.Error for _, userTeam := range teamMembers { if params.ScopedUserID != nil && *params.ScopedUserID != userTeam.UserID { continue } - _, err := a.AddTeamMember(c, userTeam.TeamID, userTeam.UserID) - if err != nil { - if err.Id == "api.team.join_user_to_team.allowed_domains.app_error" { - c.Logger().Info("User not added to team - the domain associated with the user is not in the list of allowed team domains", - mlog.String("user_id", userTeam.UserID), - mlog.String("team_id", userTeam.TeamID), - ) - continue - } - return err - } - c.Logger().Info("added teammember", + logger := rctx.Logger().With( mlog.String("user_id", userTeam.UserID), mlog.String("team_id", userTeam.TeamID), ) + + _, err := a.AddTeamMember(rctx, userTeam.TeamID, userTeam.UserID) + if err != nil { + if err.Id == "api.team.join_user_to_team.allowed_domains.app_error" { + logger.Info("User not added to team - the domain associated with the user is not in the list of allowed team domains") + } else { + multiErr = multierror.Append(multiErr, fmt.Errorf("failed to add team member for default team membership: %w", err)) + } + continue + } + + logger.Info("Added team member for default team membership") } - return nil + return multiErr.ErrorOrNil() } // CreateDefaultMemberships adds users to teams and channels based on their group memberships and how those groups // are configured to sync with teams and channels for group members on or after the given timestamp. // If includeRemovedMembers is true, then members who left or were removed from a team/channel will // be re-added; otherwise, they will not be re-added. -func (a *App) CreateDefaultMemberships(c request.CTX, params model.CreateDefaultMembershipParams) error { - err := a.createDefaultTeamMemberships(c, params) +func (a *App) CreateDefaultMemberships(rctx request.CTX, params model.CreateDefaultMembershipParams) error { + err := a.createDefaultTeamMemberships(rctx, params) if err != nil { return err } - err = a.createDefaultChannelMemberships(c, params) + err = a.createDefaultChannelMemberships(rctx, params) if err != nil { return err } @@ -137,13 +141,13 @@ func (a *App) CreateDefaultMemberships(c request.CTX, params model.CreateDefault // DeleteGroupConstrainedMemberships deletes team and channel memberships of users who aren't members of the allowed // groups of all group-constrained teams and channels. -func (a *App) DeleteGroupConstrainedMemberships(c request.CTX) error { - err := a.deleteGroupConstrainedChannelMemberships(c, nil) +func (a *App) DeleteGroupConstrainedMemberships(rctx request.CTX) error { + err := a.deleteGroupConstrainedChannelMemberships(rctx, nil) if err != nil { return err } - err = a.deleteGroupConstrainedTeamMemberships(c, nil) + err = a.deleteGroupConstrainedTeamMemberships(rctx, nil) if err != nil { return err } @@ -154,66 +158,75 @@ func (a *App) DeleteGroupConstrainedMemberships(c request.CTX) error { // deleteGroupConstrainedTeamMemberships deletes team memberships of users who aren't members of the allowed // groups of the given group-constrained team. If a teamID is given then the procedure is scoped to the given team, // if teamID is nil then the procedure affects all teams. -func (a *App) deleteGroupConstrainedTeamMemberships(c request.CTX, teamID *string) error { +func (a *App) deleteGroupConstrainedTeamMemberships(rctx request.CTX, teamID *string) error { teamMembers, appErr := a.TeamMembersToRemove(teamID) if appErr != nil { return appErr } + var multiErr *multierror.Error for _, userTeam := range teamMembers { - err := a.RemoveUserFromTeam(c, userTeam.TeamId, userTeam.UserId, "") - if err != nil { - return err - } - - c.Logger().Info("removed teammember", + logger := rctx.Logger().With( mlog.String("user_id", userTeam.UserId), mlog.String("team_id", userTeam.TeamId), ) + + err := a.RemoveUserFromTeam(rctx, userTeam.TeamId, userTeam.UserId, "") + if err != nil { + multiErr = multierror.Append(multiErr, fmt.Errorf("failed to remove team member for default team membership: %w", err)) + continue + } + + logger.Info("Removed team member for group constrained team membership") } - return nil + return multiErr.ErrorOrNil() } // deleteGroupConstrainedChannelMemberships deletes channel memberships of users who aren't members of the allowed // groups of the given group-constrained channel. If a channelID is given then the procedure is scoped to the given team, // if channelID is nil then the procedure affects all teams. -func (a *App) deleteGroupConstrainedChannelMemberships(c request.CTX, channelID *string) error { +func (a *App) deleteGroupConstrainedChannelMemberships(rctx request.CTX, channelID *string) error { channelMembers, appErr := a.ChannelMembersToRemove(channelID) if appErr != nil { return appErr } + var multiErr *multierror.Error for _, userChannel := range channelMembers { - channel, err := a.GetChannel(c, userChannel.ChannelId) - if err != nil { - return err - } - - err = a.RemoveUserFromChannel(c, userChannel.UserId, "", channel) - if err != nil { - return err - } - - a.Log().Info("removed channelmember", + logger := rctx.Logger().With( mlog.String("user_id", userChannel.UserId), - mlog.String("channel_id", channel.Id), + mlog.String("channel_id", userChannel.ChannelId), ) + + channel, err := a.GetChannel(rctx, userChannel.ChannelId) + if err != nil { + multiErr = multierror.Append(multiErr, fmt.Errorf("failed to get channel for group constrained channel membership: %w", err)) + continue + } + + err = a.RemoveUserFromChannel(rctx, userChannel.UserId, "", channel) + if err != nil { + multiErr = multierror.Append(multiErr, fmt.Errorf("failed to remove channel member for group constrained channel membership: %w", err)) + continue + } + + logger.Info("Removed channel member for group constrained channel membership") } - return nil + return multiErr.ErrorOrNil() } // SyncSyncableRoles updates the SchemeAdmin field value of the given syncable's members based on the configuration of // the member's group memberships and the configuration of those groups to the syncable. This method should only // be invoked on group-synced (aka group-constrained) syncables. -func (a *App) SyncSyncableRoles(syncableID string, syncableType model.GroupSyncableType) *model.AppError { +func (a *App) SyncSyncableRoles(rctx request.CTX, syncableID string, syncableType model.GroupSyncableType) *model.AppError { permittedAdmins, err := a.Srv().Store().Group().PermittedSyncableAdmins(syncableID, syncableType) if err != nil { return model.NewAppError("SyncSyncableRoles", "app.select_error", nil, "", http.StatusInternalServerError).Wrap(err) } - a.Log().Info( + rctx.Logger().Info( fmt.Sprintf("Permitted admins for %s", syncableType), mlog.String(strings.ToLower(fmt.Sprintf("%s_id", syncableType)), syncableID), mlog.Array("permitted_admins", permittedAdmins), @@ -239,8 +252,8 @@ func (a *App) SyncSyncableRoles(syncableID string, syncableType model.GroupSynca // SyncRolesAndMembership updates the SchemeAdmin status and membership of all of the members of the given // syncable. -func (a *App) SyncRolesAndMembership(c request.CTX, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) { - a.SyncSyncableRoles(syncableID, syncableType) +func (a *App) SyncRolesAndMembership(rctx request.CTX, syncableID string, syncableType model.GroupSyncableType, includeRemovedMembers bool) { + a.SyncSyncableRoles(rctx, syncableID, syncableType) lastJob, _ := a.Srv().Store().Job().GetNewestJobByStatusAndType(model.JobStatusSuccess, model.JobTypeLdapSync) var since int64 @@ -253,17 +266,25 @@ func (a *App) SyncRolesAndMembership(c request.CTX, syncableID string, syncableT switch syncableType { case model.GroupSyncableTypeTeam: params.ScopedTeamID = &syncableID - a.createDefaultTeamMemberships(c, params) - a.deleteGroupConstrainedTeamMemberships(c, &syncableID) + if err := a.createDefaultTeamMemberships(rctx, params); err != nil { + rctx.Logger().Warn("Error creating default team memberships", mlog.Err(err)) + } + if err := a.deleteGroupConstrainedTeamMemberships(rctx, &syncableID); err != nil { + rctx.Logger().Warn("Error deleting group constrained team memberships", mlog.Err(err)) + } if err := a.ClearTeamMembersCache(syncableID); err != nil { - c.Logger().Warn("Error clearing team members cache", mlog.Err(err)) + rctx.Logger().Warn("Error clearing team members cache", mlog.Err(err)) } case model.GroupSyncableTypeChannel: params.ScopedChannelID = &syncableID - a.createDefaultChannelMemberships(c, params) - a.deleteGroupConstrainedChannelMemberships(c, &syncableID) - if err := a.ClearChannelMembersCache(c, syncableID); err != nil { - c.Logger().Warn("Error clearing channel members cache", mlog.Err(err)) + if err := a.createDefaultChannelMemberships(rctx, params); err != nil { + rctx.Logger().Warn("Error creating default channel memberships", mlog.Err(err)) + } + if err := a.deleteGroupConstrainedChannelMemberships(rctx, &syncableID); err != nil { + rctx.Logger().Warn("Error deleting group constrained team memberships", mlog.Err(err)) + } + if err := a.ClearChannelMembersCache(rctx, syncableID); err != nil { + rctx.Logger().Warn("Error clearing channel members cache", mlog.Err(err)) } } } diff --git a/server/channels/app/syncables_test.go b/server/channels/app/syncables_test.go index e7738cf572..1075648ae5 100644 --- a/server/channels/app/syncables_test.go +++ b/server/channels/app/syncables_test.go @@ -4,13 +4,18 @@ package app import ( + "context" + "fmt" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/mattermost/mattermost/server/public/model" + "github.com/mattermost/mattermost/server/v8/channels/store" ) +//nolint:govet // The setup code leads to a lot of variable shadowing. func TestCreateDefaultMemberships(t *testing.T) { th := Setup(t).InitBasic() defer th.TearDown() @@ -105,7 +110,7 @@ func TestCreateDefaultMemberships(t *testing.T) { pErr := th.App.CreateDefaultMemberships(th.Context, model.CreateDefaultMembershipParams{Since: 0, ReAddRemovedMembers: false}) if pErr != nil { - t.Errorf("faild to populate syncables: %s", pErr.Error()) + t.Errorf("failed to populate syncables: %s", pErr.Error()) } // Singer should be in team and channel @@ -175,7 +180,7 @@ func TestCreateDefaultMemberships(t *testing.T) { // Sync everything after syncable was created (proving that team updates trigger re-sync) pErr = th.App.CreateDefaultMemberships(th.Context, model.CreateDefaultMembershipParams{Since: scientistGroupMember.CreateAt + 1, ReAddRemovedMembers: false}) if pErr != nil { - t.Errorf("faild to populate syncables: %s", pErr.Error()) + t.Errorf("failed to populate syncables: %s", pErr.Error()) } // Scientist should be in team but not the channel @@ -218,7 +223,7 @@ func TestCreateDefaultMemberships(t *testing.T) { // Sync everything after syncable was created (proving that channel updates trigger re-sync) pErr = th.App.CreateDefaultMemberships(th.Context, model.CreateDefaultMembershipParams{Since: scientistGroupMember.CreateAt + 1, ReAddRemovedMembers: false}) if pErr != nil { - t.Errorf("faild to populate syncables: %s", pErr.Error()) + t.Errorf("failed to populate syncables: %s", pErr.Error()) } expected = 1 @@ -243,7 +248,7 @@ func TestCreateDefaultMemberships(t *testing.T) { // Even re-syncing from the beginning doesn't re-add to channel or team pErr = th.App.CreateDefaultMemberships(th.Context, model.CreateDefaultMembershipParams{Since: 0, ReAddRemovedMembers: false}) if pErr != nil { - t.Errorf("faild to populate syncables: %s", pErr.Error()) + t.Errorf("failed to populate syncables: %s", pErr.Error()) } // Singer should not be in team or channel @@ -284,7 +289,7 @@ func TestCreateDefaultMemberships(t *testing.T) { pErr = th.App.CreateDefaultMemberships(th.Context, model.CreateDefaultMembershipParams{Since: 0, ReAddRemovedMembers: false}) if pErr != nil { - t.Errorf("faild to populate syncables: %s", pErr.Error()) + t.Errorf("failed to populate syncables: %s", pErr.Error()) } timeBeforeLeaving := model.GetMillis() @@ -482,6 +487,46 @@ func TestCreateDefaultMemberships(t *testing.T) { t.Errorf("expected 2 channel member on team1Channel1, got %d", len(team1Channel1Members)) } }) + + t.Run("error should contain a information about all users that failed", func(t *testing.T) { + user1 := th.CreateUser() + _, err = th.App.UpsertGroupMember(scienceGroup.Id, user1.Id) + require.Nil(t, err) + + user2 := th.CreateUser() + _, err = th.App.UpsertGroupMember(scienceGroup.Id, user2.Id) + require.Nil(t, err) + + store := &mockStore{ + Store: th.App.Srv().Store(), + us: &mokeUserStore{ + UserStore: th.App.Srv().Store().User(), + }, + } + require.Nil(t, err) + th.App.Srv().platform.Store = store + + nErr = th.App.CreateDefaultMemberships(th.Context, model.CreateDefaultMembershipParams{Since: 0, ReAddRemovedMembers: false}) + require.Error(t, nErr) + assert.ErrorContains(t, nErr, "failed to add team member for default team membership") + assert.ErrorContains(t, nErr, user1.Id) + assert.ErrorContains(t, nErr, user2.Id) + }) +} + +type mockStore struct { + store.Store + us store.UserStore +} + +func (fk *mockStore) User() store.UserStore { return fk.us } + +type mokeUserStore struct { + store.UserStore +} + +func (us *mokeUserStore) Get(_ context.Context, id string) (*model.User, error) { + return nil, fmt.Errorf("some error for %s", id) } func TestDeleteGroupMemberships(t *testing.T) { @@ -601,10 +646,10 @@ func TestSyncSyncableRoles(t *testing.T) { _, err = th.App.UpdateGroupSyncable(channelSyncable) require.Nil(t, err) - err = th.App.SyncSyncableRoles(channel.Id, model.GroupSyncableTypeChannel) + err = th.App.SyncSyncableRoles(th.Context, channel.Id, model.GroupSyncableTypeChannel) require.Nil(t, err) - err = th.App.SyncSyncableRoles(team.Id, model.GroupSyncableTypeTeam) + err = th.App.SyncSyncableRoles(th.Context, team.Id, model.GroupSyncableTypeTeam) require.Nil(t, err) for _, user := range []*model.User{user1, user2} { diff --git a/server/i18n/en.json b/server/i18n/en.json index a9d97f039e..8b36fc4d45 100644 --- a/server/i18n/en.json +++ b/server/i18n/en.json @@ -7774,10 +7774,6 @@ "id": "ent.ldap.save_user.username_exists.ldap_app_error", "translation": "An account with that username already exists. Please contact your Administrator." }, - { - "id": "ent.ldap.syncronize.delete_group_constained_memberships", - "translation": "error deleting team or channel memberships" - }, { "id": "ent.ldap.syncronize.get_all.app_error", "translation": "Unable to get all users using AD/LDAP."