diff --git a/api4/emoji.go b/api4/emoji.go index 8dc51d18ed..ac5e849cd7 100644 --- a/api4/emoji.go +++ b/api4/emoji.go @@ -53,7 +53,7 @@ func createEmoji(c *Context, w http.ResponseWriter, r *http.Request) { defer c.LogAuditRec(auditRec) // Allow any user with CREATE_EMOJIS permission at Team level to create emojis at system level - memberships, err := c.App.GetTeamMembersForUser(c.AppContext.Session().UserId, true) + memberships, err := c.App.GetTeamMembersForUser(c.AppContext.Session().UserId, "", true) if err != nil { c.Err = err @@ -143,7 +143,7 @@ func deleteEmoji(c *Context, w http.ResponseWriter, r *http.Request) { auditRec.AddMeta("emoji", emoji) // Allow any user with DELETE_EMOJIS permission at Team level to delete emojis at system level - memberships, err := c.App.GetTeamMembersForUser(c.AppContext.Session().UserId, true) + memberships, err := c.App.GetTeamMembersForUser(c.AppContext.Session().UserId, "", true) if err != nil { c.Err = err diff --git a/api4/resolver.go b/api4/resolver.go index 15c99ce813..d1ffcaea4e 100644 --- a/api4/resolver.go +++ b/api4/resolver.go @@ -132,8 +132,9 @@ func (r *resolver) License(ctx context.Context) (model.StringMap, error) { // match with api4.getTeamMembersForUser for teamID="" // and api4.getTeamMember for teamID != "" func (r *resolver) TeamMembers(ctx context.Context, args struct { - UserID string - TeamID string + UserID string + TeamID string + ExcludeTeam bool }) ([]*teamMember, error) { c, err := getCtx(ctx) if err != nil { @@ -159,7 +160,7 @@ func (r *resolver) TeamMembers(ctx context.Context, args struct { return nil, c.Err } - if args.TeamID != "" { + if args.TeamID != "" && !args.ExcludeTeam { if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), args.TeamID, model.PermissionViewTeam) { c.SetPermissionError(model.PermissionViewTeam) return nil, c.Err @@ -173,8 +174,13 @@ func (r *resolver) TeamMembers(ctx context.Context, args struct { return []*teamMember{{*tm}}, nil } + excludeTeamID := "" + if args.TeamID != "" && args.ExcludeTeam { + excludeTeamID = args.TeamID + } + // Do not return archived team members - members, appErr := c.App.GetTeamMembersForUser(args.UserID, false) + members, appErr := c.App.GetTeamMembersForUser(args.UserID, excludeTeamID, false) if appErr != nil { return nil, appErr } @@ -301,6 +307,37 @@ func (*resolver) ChannelMembers(ctx context.Context, args struct { return res, nil } +// match with api4.getCategoriesForTeamForUser +func (*resolver) SidebarCategories(ctx context.Context, args struct { + UserID string + TeamID string +}) ([]*model.SidebarCategoryWithChannels, error) { + c, err := getCtx(ctx) + if err != nil { + return nil, err + } + + // Fallback to primary team logic + if !c.App.SessionHasPermissionToTeam(*c.AppContext.Session(), args.TeamID, model.PermissionViewTeam) { + primaryTeam := *c.App.Config().TeamSettings.ExperimentalPrimaryTeam + if primaryTeam != "" { + team, appErr := c.App.GetTeamByName(primaryTeam) + if appErr != nil { + return []*model.SidebarCategoryWithChannels{}, appErr + } + args.TeamID = team.Id + } else { + return []*model.SidebarCategoryWithChannels{}, nil + } + } + + if args.UserID == model.Me { + args.UserID = c.AppContext.Session().UserId + } + + return getSidebarCategories(c, args.UserID, args.TeamID) +} + // getCtx extracts web.Context out of the usual request context. // Kind of an anti-pattern, but there are lots of methods attached to *web.Context // so we use it for now. diff --git a/api4/resolver_sidebar_categories_test.go b/api4/resolver_sidebar_categories_test.go new file mode 100644 index 0000000000..75467dc4ec --- /dev/null +++ b/api4/resolver_sidebar_categories_test.go @@ -0,0 +1,72 @@ +// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. +// See LICENSE.txt for license information. + +package api4 + +import ( + "encoding/json" + "os" + "sort" + "testing" + + "github.com/mattermost/mattermost-server/v6/model" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestGraphQLSidebarCategories(t *testing.T) { + os.Setenv("MM_FEATUREFLAGS_GRAPHQL", "true") + defer os.Unsetenv("MM_FEATUREFLAGS_GRAPHQL") + th := Setup(t).InitBasic() + defer th.TearDown() + + var q struct { + SidebarCategories []struct { + ID string `json:"id"` + DisplayName string `json:"displayName"` + Sorting model.SidebarCategorySorting `json:"sorting"` + ChannelIDs []string `json:"channelIds"` + } `json:"sidebarCategories"` + } + + input := graphQLInput{ + OperationName: "sidebarCategories", + Query: ` + query sidebarCategories($userId: String = "", $teamId: String = "") { + sidebarCategories(userId: $userId, teamId: $teamId) { + id + displayName + sorting + channelIds + } + } + `, + Variables: map[string]interface{}{ + "userId": "me", + "teamId": th.BasicTeam.Id, + }, + } + + resp, err := th.MakeGraphQLRequest(&input) + require.NoError(t, err) + require.Len(t, resp.Errors, 0) + require.NoError(t, json.Unmarshal(resp.Data, &q)) + assert.Len(t, q.SidebarCategories, 3) + + categories, _, err := th.Client.GetSidebarCategoriesForTeamForUser(th.BasicUser.Id, th.BasicTeam.Id, "") + require.NoError(t, err) + + sort.Slice(q.SidebarCategories, func(i, j int) bool { + return q.SidebarCategories[i].ID < q.SidebarCategories[j].ID + }) + sort.Slice(categories.Categories, func(i, j int) bool { + return categories.Categories[i].Id < categories.Categories[j].Id + }) + + for i := range categories.Categories { + assert.Equal(t, categories.Categories[i].Id, q.SidebarCategories[i].ID) + assert.Equal(t, categories.Categories[i].DisplayName, q.SidebarCategories[i].DisplayName) + assert.Equal(t, categories.Categories[i].Sorting, q.SidebarCategories[i].Sorting) + assert.Equal(t, categories.Categories[i].ChannelIds(), q.SidebarCategories[i].ChannelIDs) + } +} diff --git a/api4/resolver_team_member.go b/api4/resolver_team_member.go index bd0f64651b..28591110cf 100644 --- a/api4/resolver_team_member.go +++ b/api4/resolver_team_member.go @@ -9,6 +9,7 @@ import ( "github.com/graph-gophers/dataloader/v6" "github.com/mattermost/mattermost-server/v6/model" + "github.com/mattermost/mattermost-server/v6/web" ) // teamMember is an internal graphQL wrapper struct to add resolver methods. @@ -33,12 +34,16 @@ func (tm *teamMember) SidebarCategories(ctx context.Context) ([]*model.SidebarCa return nil, err } - if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), tm.UserId) { + return getSidebarCategories(c, tm.UserId, tm.TeamId) +} + +func getSidebarCategories(c *web.Context, userID, teamID string) ([]*model.SidebarCategoryWithChannels, error) { + if !c.App.SessionHasPermissionToUser(*c.AppContext.Session(), userID) { c.SetPermissionError(model.PermissionEditOtherUsers) return nil, c.Err } - categories, appErr := c.App.GetSidebarCategories(tm.UserId, tm.TeamId) + categories, appErr := c.App.GetSidebarCategories(userID, teamID) if appErr != nil { return nil, appErr } diff --git a/api4/resolver_team_member_test.go b/api4/resolver_team_member_test.go index 674e01b073..d89a677e95 100644 --- a/api4/resolver_team_member_test.go +++ b/api4/resolver_team_member_test.go @@ -249,6 +249,48 @@ func TestGraphQLTeamMembers(t *testing.T) { expectedTeams[i].DisplayName = tm.Team.DisplayName } + // Negate team + input = graphQLInput{ + OperationName: "teamMembers", + Query: ` + query teamMembers($userId: String = "", $teamId: String = "") { + teamMembers(userId: $userId, teamId: $teamId, excludeTeam: true) { + team { + id + displayName + } + } + } + `, + Variables: map[string]interface{}{ + "userId": "me", + "teamId": th.BasicTeam.Id, + }, + } + + resp, err = th.MakeGraphQLRequest(&input) + require.NoError(t, err) + require.Len(t, resp.Errors, 0) + require.NoError(t, json.Unmarshal(resp.Data, &q)) + assert.Len(t, q.TeamMembers, 1) + + input = graphQLInput{ + OperationName: "teamMembers", + Query: ` + query teamMembers($userId: String = "", $teamId: String = "") { + teamMembers(userId: $userId, teamId: $teamId) { + team { + id + displayName + } + } + } + `, + Variables: map[string]interface{}{ + "userId": "me", + }, + } + // Removing from a team and ensuring we get the right response. th.UnlinkUserFromTeam(th.BasicUser, myTeam) resp, err = th.MakeGraphQLRequest(&input) diff --git a/api4/schema.graphqls b/api4/schema.graphqls index 9085dd2e21..3b6839285d 100644 --- a/api4/schema.graphqls +++ b/api4/schema.graphqls @@ -7,7 +7,8 @@ type Query { config(): StringMap! license(): StringMap! teamMembers(userId: String!, - teamId: String = ""): [TeamMember]! + teamId: String = "", + excludeTeam: Boolean = false): [TeamMember]! channels(userId: String!, teamId: String = "", includeDeleted: Boolean = false, @@ -24,6 +25,8 @@ type Query { first: Int = 60, after: String = "", lastUpdateAt: Float = 0): [ChannelMember]! + sidebarCategories(userId: String!, + teamId: String!): [SidebarCategory]! } scalar ChannelType diff --git a/api4/team.go b/api4/team.go index 1cd78acff7..eb10537732 100644 --- a/api4/team.go +++ b/api4/team.go @@ -554,7 +554,7 @@ func getTeamMembersForUser(c *Context, w http.ResponseWriter, r *http.Request) { return } - members, err := c.App.GetTeamMembersForUser(c.Params.UserId, true) + members, err := c.App.GetTeamMembersForUser(c.Params.UserId, "", true) if err != nil { c.Err = err return diff --git a/app/app_iface.go b/app/app_iface.go index c4aa84072b..b518746431 100644 --- a/app/app_iface.go +++ b/app/app_iface.go @@ -737,7 +737,7 @@ type AppIface interface { GetTeamMember(teamID, userID string) (*model.TeamMember, *model.AppError) GetTeamMembers(teamID string, offset int, limit int, teamMembersGetOptions *model.TeamMembersGetOptions) ([]*model.TeamMember, *model.AppError) GetTeamMembersByIds(teamID string, userIDs []string, restrictions *model.ViewUsersRestrictions) ([]*model.TeamMember, *model.AppError) - GetTeamMembersForUser(userID string, includeDeleted bool) ([]*model.TeamMember, *model.AppError) + GetTeamMembersForUser(userID string, excludeTeamID string, includeDeleted bool) ([]*model.TeamMember, *model.AppError) GetTeamMembersForUserWithPagination(userID string, page, perPage int) ([]*model.TeamMember, *model.AppError) GetTeamPoliciesForUser(userID string, offset, limit int) (*model.RetentionPolicyForTeamList, *model.AppError) GetTeamStats(teamID string, restrictions *model.ViewUsersRestrictions) (*model.TeamStats, *model.AppError) diff --git a/app/import_functions.go b/app/import_functions.go index 26fcc92e2b..3dabae0bc6 100644 --- a/app/import_functions.go +++ b/app/import_functions.go @@ -737,7 +737,7 @@ func (a *App) importUserTeams(user *model.User, data *[]UserTeamImportData) *mod isGuestByTeamId := map[string]bool{} isUserByTeamId := map[string]bool{} isAdminByTeamId := map[string]bool{} - existingMemberships, nErr := a.Srv().Store.Team().GetTeamsForUser(context.Background(), user.Id, true) + existingMemberships, nErr := a.Srv().Store.Team().GetTeamsForUser(context.Background(), user.Id, "", true) if nErr != nil { return model.NewAppError("importUserTeams", "app.team.get_members.app_error", nil, nErr.Error(), http.StatusInternalServerError) } diff --git a/app/import_functions_test.go b/app/import_functions_test.go index 0d01b04a7b..9c4c59bc48 100644 --- a/app/import_functions_test.go +++ b/app/import_functions_test.go @@ -1717,7 +1717,7 @@ func TestImportUserTeams(t *testing.T) { } else { require.Nil(t, err) } - teamMembers, nErr := th.App.Srv().Store.Team().GetTeamsForUser(context.Background(), user.Id, true) + teamMembers, nErr := th.App.Srv().Store.Team().GetTeamsForUser(context.Background(), user.Id, "", true) require.NoError(t, nErr) require.Len(t, teamMembers, tc.expectedUserTeams) if tc.expectedUserTeams == 1 { diff --git a/app/opentracing/opentracing_layer.go b/app/opentracing/opentracing_layer.go index ebbadc2f7b..afb5d1f511 100644 --- a/app/opentracing/opentracing_layer.go +++ b/app/opentracing/opentracing_layer.go @@ -9200,7 +9200,7 @@ func (a *OpenTracingAppLayer) GetTeamMembersByIds(teamID string, userIDs []strin return resultVar0, resultVar1 } -func (a *OpenTracingAppLayer) GetTeamMembersForUser(userID string, includeDeleted bool) ([]*model.TeamMember, *model.AppError) { +func (a *OpenTracingAppLayer) GetTeamMembersForUser(userID string, excludeTeamID string, includeDeleted bool) ([]*model.TeamMember, *model.AppError) { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.GetTeamMembersForUser") @@ -9212,7 +9212,7 @@ func (a *OpenTracingAppLayer) GetTeamMembersForUser(userID string, includeDelete }() defer span.Finish() - resultVar0, resultVar1 := a.app.GetTeamMembersForUser(userID, includeDeleted) + resultVar0, resultVar1 := a.app.GetTeamMembersForUser(userID, excludeTeamID, includeDeleted) if resultVar1 != nil { span.LogFields(spanlog.Error(resultVar1)) diff --git a/app/team.go b/app/team.go index c4cf583b4b..2281ca5775 100644 --- a/app/team.go +++ b/app/team.go @@ -893,8 +893,8 @@ func (a *App) GetTeamMember(teamID, userID string) (*model.TeamMember, *model.Ap return teamMember, nil } -func (a *App) GetTeamMembersForUser(userID string, includeDeleted bool) ([]*model.TeamMember, *model.AppError) { - teamMembers, err := a.Srv().Store.Team().GetTeamsForUser(context.Background(), userID, includeDeleted) +func (a *App) GetTeamMembersForUser(userID string, excludeTeamID string, includeDeleted bool) ([]*model.TeamMember, *model.AppError) { + teamMembers, err := a.Srv().Store.Team().GetTeamsForUser(context.Background(), userID, excludeTeamID, includeDeleted) if err != nil { return nil, model.NewAppError("GetTeamMembersForUser", "app.team.get_members.app_error", nil, err.Error(), http.StatusInternalServerError) } diff --git a/app/user.go b/app/user.go index c585b2a91d..8e0166675f 100644 --- a/app/user.go +++ b/app/user.go @@ -2145,7 +2145,7 @@ func (a *App) PromoteGuestToUser(c *request.Context, user *model.User, requestor } } - teamMembers, err := a.GetTeamMembersForUser(user.Id, true) + teamMembers, err := a.GetTeamMembersForUser(user.Id, "", true) if err != nil { mlog.Warn("Failed to get team members for user on promote guest to user", mlog.Err(err)) } @@ -2189,7 +2189,7 @@ func (a *App) DemoteUserToGuest(user *model.User) *model.AppError { mlog.Warn("Unable to update user sessions", mlog.String("user_id", demotedUser.Id), mlog.Err(uErr)) } - teamMembers, err := a.GetTeamMembersForUser(user.Id, true) + teamMembers, err := a.GetTeamMembersForUser(user.Id, "", true) if err != nil { mlog.Warn("Failed to get team members for users on demote user to guest", mlog.Err(err)) } diff --git a/store/opentracinglayer/opentracinglayer.go b/store/opentracinglayer/opentracinglayer.go index b37b14073b..a88d15a711 100644 --- a/store/opentracinglayer/opentracinglayer.go +++ b/store/opentracinglayer/opentracinglayer.go @@ -8822,7 +8822,7 @@ func (s *OpenTracingLayerTeamStore) GetTeamsByUserId(userID string) ([]*model.Te return result, err } -func (s *OpenTracingLayerTeamStore) GetTeamsForUser(ctx context.Context, userID string, includeDeleted bool) ([]*model.TeamMember, error) { +func (s *OpenTracingLayerTeamStore) GetTeamsForUser(ctx context.Context, userID string, excludeTeamID string, includeDeleted bool) ([]*model.TeamMember, error) { origCtx := s.Root.Store.Context() span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "TeamStore.GetTeamsForUser") s.Root.Store.SetContext(newCtx) @@ -8831,7 +8831,7 @@ func (s *OpenTracingLayerTeamStore) GetTeamsForUser(ctx context.Context, userID }() defer span.Finish() - result, err := s.TeamStore.GetTeamsForUser(ctx, userID, includeDeleted) + result, err := s.TeamStore.GetTeamsForUser(ctx, userID, excludeTeamID, includeDeleted) if err != nil { span.LogFields(spanlog.Error(err)) ext.Error.Set(span, true) diff --git a/store/retrylayer/retrylayer.go b/store/retrylayer/retrylayer.go index 84b684e55c..61bfa3392e 100644 --- a/store/retrylayer/retrylayer.go +++ b/store/retrylayer/retrylayer.go @@ -10072,11 +10072,11 @@ func (s *RetryLayerTeamStore) GetTeamsByUserId(userID string) ([]*model.Team, er } -func (s *RetryLayerTeamStore) GetTeamsForUser(ctx context.Context, userID string, includeDeleted bool) ([]*model.TeamMember, error) { +func (s *RetryLayerTeamStore) GetTeamsForUser(ctx context.Context, userID string, excludeTeamID string, includeDeleted bool) ([]*model.TeamMember, error) { tries := 0 for { - result, err := s.TeamStore.GetTeamsForUser(ctx, userID, includeDeleted) + result, err := s.TeamStore.GetTeamsForUser(ctx, userID, excludeTeamID, includeDeleted) if err == nil { return result, nil } diff --git a/store/sqlstore/session_store.go b/store/sqlstore/session_store.go index d931b8205f..e7e38912d2 100644 --- a/store/sqlstore/session_store.go +++ b/store/sqlstore/session_store.go @@ -59,7 +59,7 @@ func (me SqlSessionStore) Save(session *model.Session) (*model.Session, error) { return nil, errors.Wrapf(err, "failed to save Session with id=%s", session.Id) } - teamMembers, err := me.Team().GetTeamsForUser(context.Background(), session.UserId, true) + teamMembers, err := me.Team().GetTeamsForUser(context.Background(), session.UserId, "", true) if err != nil { return nil, errors.Wrapf(err, "failed to find TeamMembers for Session with userId=%s", session.UserId) } @@ -87,7 +87,7 @@ func (me SqlSessionStore) Get(ctx context.Context, sessionIdOrToken string) (*mo tempMembers, err := me.Team().GetTeamsForUser( WithMaster(context.Background()), - session.UserId, true) + session.UserId, "", true) if err != nil { return nil, errors.Wrapf(err, "failed to find TeamMembers for Session with userId=%s", session.UserId) } @@ -107,7 +107,7 @@ func (me SqlSessionStore) GetSessions(userId string) ([]*model.Session, error) { return nil, errors.Wrapf(err, "failed to find Sessions with userId=%s", userId) } - teamMembers, err := me.Team().GetTeamsForUser(context.Background(), userId, true) + teamMembers, err := me.Team().GetTeamsForUser(context.Background(), userId, "", true) if err != nil { return nil, errors.Wrapf(err, "failed to find TeamMembers for Session with userId=%s", userId) } diff --git a/store/sqlstore/team_store.go b/store/sqlstore/team_store.go index baa88b1bb4..de2462c467 100644 --- a/store/sqlstore/team_store.go +++ b/store/sqlstore/team_store.go @@ -1080,11 +1080,15 @@ func (s SqlTeamStore) GetMembersByIds(teamId string, userIds []string, restricti return dbMembers.ToModel(), nil } -// GetTeamsForUser returns a list of teams that the user is a member of. Expects userId to be passed as a parameter. -func (s SqlTeamStore) GetTeamsForUser(ctx context.Context, userId string, includeDeleted bool) ([]*model.TeamMember, error) { +// GetTeamsForUser returns a list of teams that the user is a member of. Expects userId to be passed as a parameter. It can also negative the teamID passed. +func (s SqlTeamStore) GetTeamsForUser(ctx context.Context, userId, excludeTeamID string, includeDeleted bool) ([]*model.TeamMember, error) { query := s.getTeamMembersWithSchemeSelectQuery(). Where(sq.Eq{"TeamMembers.UserId": userId}) + if excludeTeamID != "" { + query = query.Where(sq.NotEq{"TeamMembers.TeamId": excludeTeamID}) + } + if !includeDeleted { query = query.Where(sq.Eq{"TeamMembers.DeleteAt": 0}) } diff --git a/store/store.go b/store/store.go index 3b6fedf28a..f0a9da8771 100644 --- a/store/store.go +++ b/store/store.go @@ -126,7 +126,7 @@ type TeamStore interface { GetMembersByIds(teamID string, userIds []string, restrictions *model.ViewUsersRestrictions) ([]*model.TeamMember, error) GetTotalMemberCount(teamID string, restrictions *model.ViewUsersRestrictions) (int64, error) GetActiveMemberCount(teamID string, restrictions *model.ViewUsersRestrictions) (int64, error) - GetTeamsForUser(ctx context.Context, userID string, includeDeleted bool) ([]*model.TeamMember, error) + GetTeamsForUser(ctx context.Context, userID, excludeTeamID string, includeDeleted bool) ([]*model.TeamMember, error) GetTeamsForUserWithPagination(userID string, page, perPage int) ([]*model.TeamMember, error) GetChannelUnreadsForAllTeams(excludeTeamID, userID string) ([]*model.ChannelUnread, error) GetChannelUnreadsForTeam(teamID, userID string) ([]*model.ChannelUnread, error) diff --git a/store/storetest/mocks/TeamStore.go b/store/storetest/mocks/TeamStore.go index e243eb251e..1adeae0d84 100644 --- a/store/storetest/mocks/TeamStore.go +++ b/store/storetest/mocks/TeamStore.go @@ -535,13 +535,13 @@ func (_m *TeamStore) GetTeamsByUserId(userID string) ([]*model.Team, error) { return r0, r1 } -// GetTeamsForUser provides a mock function with given fields: ctx, userID, includeDeleted -func (_m *TeamStore) GetTeamsForUser(ctx context.Context, userID string, includeDeleted bool) ([]*model.TeamMember, error) { - ret := _m.Called(ctx, userID, includeDeleted) +// GetTeamsForUser provides a mock function with given fields: ctx, userID, excludeTeamID, includeDeleted +func (_m *TeamStore) GetTeamsForUser(ctx context.Context, userID string, excludeTeamID string, includeDeleted bool) ([]*model.TeamMember, error) { + ret := _m.Called(ctx, userID, excludeTeamID, includeDeleted) var r0 []*model.TeamMember - if rf, ok := ret.Get(0).(func(context.Context, string, bool) []*model.TeamMember); ok { - r0 = rf(ctx, userID, includeDeleted) + if rf, ok := ret.Get(0).(func(context.Context, string, string, bool) []*model.TeamMember); ok { + r0 = rf(ctx, userID, excludeTeamID, includeDeleted) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]*model.TeamMember) @@ -549,8 +549,8 @@ func (_m *TeamStore) GetTeamsForUser(ctx context.Context, userID string, include } var r1 error - if rf, ok := ret.Get(1).(func(context.Context, string, bool) error); ok { - r1 = rf(ctx, userID, includeDeleted) + if rf, ok := ret.Get(1).(func(context.Context, string, string, bool) error); ok { + r1 = rf(ctx, userID, excludeTeamID, includeDeleted) } else { r1 = ret.Error(1) } diff --git a/store/storetest/team_store.go b/store/storetest/team_store.go index 57d746bd84..3df3096336 100644 --- a/store/storetest/team_store.go +++ b/store/storetest/team_store.go @@ -1318,7 +1318,7 @@ func testTeamMembers(t *testing.T, ss store.Store) { require.Equal(t, m3.UserId, ms[0].UserId) ctx := context.Background() - ms, err = ss.Team().GetTeamsForUser(ctx, m1.UserId, true) + ms, err = ss.Team().GetTeamsForUser(ctx, m1.UserId, "", true) require.NoError(t, err) require.Len(t, ms, 1) require.Equal(t, m1.TeamId, ms[0].TeamId) @@ -1347,26 +1347,30 @@ func testTeamMembers(t *testing.T, ss store.Store) { _, nErr = ss.Team().SaveMultipleMembers([]*model.TeamMember{m4, m5}, -1) require.NoError(t, nErr) - ms, err = ss.Team().GetTeamsForUser(ctx, uid, true) + ms, err = ss.Team().GetTeamsForUser(ctx, uid, "", true) require.NoError(t, err) require.Len(t, ms, 2) + ms, err = ss.Team().GetTeamsForUser(ctx, uid, teamId2, true) + require.NoError(t, err) + require.Len(t, ms, 1) + m4.DeleteAt = model.GetMillis() _, err = ss.Team().UpdateMember(m4) require.NoError(t, err) - ms, err = ss.Team().GetTeamsForUser(ctx, uid, true) + ms, err = ss.Team().GetTeamsForUser(ctx, uid, "", true) require.NoError(t, err) require.Len(t, ms, 2) - ms, err = ss.Team().GetTeamsForUser(ctx, uid, false) + ms, err = ss.Team().GetTeamsForUser(ctx, uid, "", false) require.NoError(t, err) require.Len(t, ms, 1) nErr = ss.Team().RemoveAllMembersByUser(uid) require.NoError(t, nErr) - ms, err = ss.Team().GetTeamsForUser(ctx, m1.UserId, true) + ms, err = ss.Team().GetTeamsForUser(ctx, m1.UserId, "", true) require.NoError(t, err) require.Empty(t, ms) } diff --git a/store/timerlayer/timerlayer.go b/store/timerlayer/timerlayer.go index 0e1cdddb12..d0d021e4f2 100644 --- a/store/timerlayer/timerlayer.go +++ b/store/timerlayer/timerlayer.go @@ -7944,10 +7944,10 @@ func (s *TimerLayerTeamStore) GetTeamsByUserId(userID string) ([]*model.Team, er return result, err } -func (s *TimerLayerTeamStore) GetTeamsForUser(ctx context.Context, userID string, includeDeleted bool) ([]*model.TeamMember, error) { +func (s *TimerLayerTeamStore) GetTeamsForUser(ctx context.Context, userID string, excludeTeamID string, includeDeleted bool) ([]*model.TeamMember, error) { start := timemodule.Now() - result, err := s.TeamStore.GetTeamsForUser(ctx, userID, includeDeleted) + result, err := s.TeamStore.GetTeamsForUser(ctx, userID, excludeTeamID, includeDeleted) elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second) if s.Root.Metrics != nil {