MM-21157: Triggers role sync when a syncable is linked, unlinked, or updated. (#13432)
* MM-20644: Add users to teams as a SchemeAdmin based on a new configuration field on GroupTeams and GroupChannels records. * MM-20644: Adds SchemeAdmin to mapping of the GroupSyncable struct fields. * MM-2064: Adds test to ensure SchemeAdmin field value is mapped. * MM-20644: Adds missing index creation for fresh DBs. * MM-20644: Duplicates UpdateMembersRole across Team and Channel stores. Adds tests. * MM-20644: Fixes some old method name references. * MM-20644: Moves variable declaration; removes Println statement. * MM-21157: Triggers role sync when a syncable is linked, unlinked, or updated. * MM-20644: Use a SQL query instead of two to update Team and Channel members. * MM-20644: Fixes tests; updates query. * MM-21157: Removes second invocation of function because of refactor that performs it all in a single query. * MM-21157: Switches a few queries to Squirrel. * MM-21157: SQL-formats some strings. * MM-21157: Select with list. * MM-21157: Converts some more sql to squirrel. * MM-21157: Fix incorrect conflict resolutions. * MM-21157: Fix incorrect conflict resolutions. * MM-21157: Adds missing mocks. * MM-21157: Clears cache upon syncing roles. Co-authored-by: mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
3865bc501e
Коммит
50e9aa01c3
@@ -192,6 +192,10 @@ func linkGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Not awaiting completion because the group sync job executes the same procedure—but for all syncables—and
|
||||
// persists the execution status to the jobs table.
|
||||
go c.App.SyncRolesAndMembership(syncableID, syncableType)
|
||||
|
||||
w.WriteHeader(http.StatusCreated)
|
||||
|
||||
b, marshalErr := json.Marshal(groupSyncable)
|
||||
@@ -340,6 +344,10 @@ func patchGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Not awaiting completion because the group sync job executes the same procedure—but for all syncables—and
|
||||
// persists the execution status to the jobs table.
|
||||
go c.App.SyncRolesAndMembership(syncableID, syncableType)
|
||||
|
||||
b, marshalErr := json.Marshal(groupSyncable)
|
||||
if marshalErr != nil {
|
||||
c.Err = model.NewAppError("Api4.patchGroupSyncable", "api.marshal_error", nil, marshalErr.Error(), http.StatusInternalServerError)
|
||||
@@ -384,6 +392,10 @@ func unlinkGroupSyncable(c *Context, w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
|
||||
// Not awaiting completion because the group sync job executes the same procedure—but for all syncables—and
|
||||
// persists the execution status to the jobs table.
|
||||
go c.App.SyncRolesAndMembership(syncableID, syncableType)
|
||||
|
||||
ReturnStatusOK(w)
|
||||
}
|
||||
|
||||
|
||||
@@ -2261,3 +2261,31 @@ func (a *App) FillInChannelsProps(channelList *model.ChannelList) *model.AppErro
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) ClearChannelMembersCache(channelID string) {
|
||||
perPage := 100
|
||||
page := 0
|
||||
|
||||
for {
|
||||
channelMembers, err := a.Srv.Store.Channel().GetMembers(channelID, page, perPage)
|
||||
if err != nil {
|
||||
a.Log.Warn("error clearing cache for channel members", mlog.String("channel_id", channelID))
|
||||
break
|
||||
}
|
||||
|
||||
for _, channelMember := range *channelMembers {
|
||||
a.ClearSessionCacheForUser(channelMember.UserId)
|
||||
|
||||
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_CHANNEL_MEMBER_UPDATED, "", "", channelMember.UserId, nil)
|
||||
message.Add("channelMember", channelMember.ToJson())
|
||||
a.Publish(message)
|
||||
}
|
||||
|
||||
length := len(*(channelMembers))
|
||||
if length < perPage {
|
||||
break
|
||||
}
|
||||
|
||||
page++
|
||||
}
|
||||
}
|
||||
|
||||
16
app/group.go
16
app/group.go
@@ -152,20 +152,20 @@ func (a *App) DeleteGroupSyncable(groupID string, syncableID string, syncableTyp
|
||||
return gs, nil
|
||||
}
|
||||
|
||||
func (a *App) TeamMembersToAdd(since int64) ([]*model.UserTeamIDPair, *model.AppError) {
|
||||
return a.Srv.Store.Group().TeamMembersToAdd(since)
|
||||
func (a *App) TeamMembersToAdd(since int64, teamID *string) ([]*model.UserTeamIDPair, *model.AppError) {
|
||||
return a.Srv.Store.Group().TeamMembersToAdd(since, teamID)
|
||||
}
|
||||
|
||||
func (a *App) ChannelMembersToAdd(since int64) ([]*model.UserChannelIDPair, *model.AppError) {
|
||||
return a.Srv.Store.Group().ChannelMembersToAdd(since)
|
||||
func (a *App) ChannelMembersToAdd(since int64, channelID *string) ([]*model.UserChannelIDPair, *model.AppError) {
|
||||
return a.Srv.Store.Group().ChannelMembersToAdd(since, channelID)
|
||||
}
|
||||
|
||||
func (a *App) TeamMembersToRemove() ([]*model.TeamMember, *model.AppError) {
|
||||
return a.Srv.Store.Group().TeamMembersToRemove()
|
||||
func (a *App) TeamMembersToRemove(teamID *string) ([]*model.TeamMember, *model.AppError) {
|
||||
return a.Srv.Store.Group().TeamMembersToRemove(teamID)
|
||||
}
|
||||
|
||||
func (a *App) ChannelMembersToRemove() ([]*model.ChannelMember, *model.AppError) {
|
||||
return a.Srv.Store.Group().ChannelMembersToRemove()
|
||||
func (a *App) ChannelMembersToRemove(teamID *string) ([]*model.ChannelMember, *model.AppError) {
|
||||
return a.Srv.Store.Group().ChannelMembersToRemove(teamID)
|
||||
}
|
||||
|
||||
func (a *App) GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, int, *model.AppError) {
|
||||
|
||||
178
app/syncables.go
178
app/syncables.go
@@ -4,30 +4,19 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/mlog"
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
)
|
||||
|
||||
// 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.
|
||||
func (a *App) CreateDefaultMemberships(since int64) error {
|
||||
teamMembers, appErr := a.TeamMembersToAdd(since)
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
|
||||
for _, userTeam := range teamMembers {
|
||||
_, err := a.AddTeamMember(userTeam.TeamID, userTeam.UserID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.Log.Info("added teammember",
|
||||
mlog.String("user_id", userTeam.UserID),
|
||||
mlog.String("team_id", userTeam.TeamID),
|
||||
)
|
||||
}
|
||||
|
||||
channelMembers, appErr := a.ChannelMembersToAdd(since)
|
||||
// createDefaultChannelMemberships adds users to channels based on their group memberships and how those groups are
|
||||
// configured to sync with channels for group members on or after the given timestamp. If a channelID is given
|
||||
// only that channel's members are created. If channelID is nil all channel memberships are created.
|
||||
func (a *App) createDefaultChannelMemberships(since int64, channelID *string) error {
|
||||
channelMembers, appErr := a.ChannelMembersToAdd(since, channelID)
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
@@ -76,10 +65,91 @@ func (a *App) CreateDefaultMemberships(since int64) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// createDefaultTeamMemberships adds users to teams based on their group memberships and how those groups are
|
||||
// configured to sync with teams for group members on or after the given timestamp. If a teamID is given
|
||||
// only that team's members are created. If teamID is nil all team memberships are created.
|
||||
func (a *App) createDefaultTeamMemberships(since int64, teamID *string) error {
|
||||
teamMembers, appErr := a.TeamMembersToAdd(since, teamID)
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
|
||||
for _, userTeam := range teamMembers {
|
||||
_, err := a.AddTeamMember(userTeam.TeamID, userTeam.UserID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.Log.Info("added teammember",
|
||||
mlog.String("user_id", userTeam.UserID),
|
||||
mlog.String("team_id", userTeam.TeamID),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (a *App) CreateDefaultMemberships(since int64) error {
|
||||
err := a.createDefaultTeamMemberships(since, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = a.createDefaultChannelMemberships(since, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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() error {
|
||||
channelMembers, appErr := a.ChannelMembersToRemove()
|
||||
err := a.deleteGroupConstrainedChannelMemberships(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = a.deleteGroupConstrainedTeamMemberships(nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 proceedure affects all teams.
|
||||
func (a *App) deleteGroupConstrainedTeamMemberships(teamID *string) error {
|
||||
teamMembers, appErr := a.TeamMembersToRemove(teamID)
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
|
||||
for _, userTeam := range teamMembers {
|
||||
err := a.RemoveUserFromTeam(userTeam.TeamId, userTeam.UserId, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
a.Log.Info("removed teammember",
|
||||
mlog.String("user_id", userTeam.UserId),
|
||||
mlog.String("team_id", userTeam.TeamId),
|
||||
)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 proceedure affects all teams.
|
||||
func (a *App) deleteGroupConstrainedChannelMemberships(channelID *string) error {
|
||||
channelMembers, appErr := a.ChannelMembersToRemove(channelID)
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
}
|
||||
@@ -101,22 +171,62 @@ func (a *App) DeleteGroupConstrainedMemberships() error {
|
||||
)
|
||||
}
|
||||
|
||||
teamMembers, appErr := a.TeamMembersToRemove()
|
||||
if appErr != nil {
|
||||
return appErr
|
||||
return nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
permittedAdmins, err := a.Srv.Store.Group().PermittedSyncableAdmins(syncableID, syncableType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, userTeam := range teamMembers {
|
||||
err := a.RemoveUserFromTeam(userTeam.TeamId, userTeam.UserId, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
a.Log.Info(
|
||||
fmt.Sprintf("Permitted admins for %s", syncableType),
|
||||
mlog.String(strings.ToLower(fmt.Sprintf("%s_id", syncableType)), syncableID),
|
||||
mlog.Any("permitted_admins", permittedAdmins),
|
||||
)
|
||||
|
||||
a.Log.Info("removed teammember",
|
||||
mlog.String("user_id", userTeam.UserId),
|
||||
mlog.String("team_id", userTeam.TeamId),
|
||||
)
|
||||
var updateFunc func(string, []string) *model.AppError
|
||||
|
||||
switch syncableType {
|
||||
case model.GroupSyncableTypeTeam:
|
||||
updateFunc = a.Srv.Store.Team().UpdateMembersRole
|
||||
case model.GroupSyncableTypeChannel:
|
||||
updateFunc = a.Srv.Store.Channel().UpdateMembersRole
|
||||
default:
|
||||
return model.NewAppError("App.SyncSyncableRoles", "groups.unsupported_syncable_type", map[string]interface{}{"Value": syncableType}, "", http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
err = updateFunc(syncableID, permittedAdmins)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// SyncRolesAndMembership updates the SchemeAdmin status and membership of all of the members of the given
|
||||
// syncable.
|
||||
func (a *App) SyncRolesAndMembership(syncableID string, syncableType model.GroupSyncableType) {
|
||||
a.SyncSyncableRoles(syncableID, syncableType)
|
||||
|
||||
lastJob, _ := a.Srv.Store.Job().GetNewestJobByStatusAndType(model.JOB_STATUS_SUCCESS, model.JOB_TYPE_LDAP_SYNC)
|
||||
var since int64
|
||||
if lastJob != nil {
|
||||
since = lastJob.StartAt
|
||||
}
|
||||
|
||||
switch syncableType {
|
||||
case model.GroupSyncableTypeTeam:
|
||||
a.createDefaultTeamMemberships(since, &syncableID)
|
||||
a.deleteGroupConstrainedTeamMemberships(&syncableID)
|
||||
a.ClearTeamMembersCache(syncableID)
|
||||
case model.GroupSyncableTypeChannel:
|
||||
a.createDefaultChannelMemberships(since, &syncableID)
|
||||
a.deleteGroupConstrainedChannelMemberships(&syncableID)
|
||||
a.ClearChannelMembersCache(syncableID)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -396,3 +396,70 @@ func TestDeleteGroupMemberships(t *testing.T) {
|
||||
require.Len(t, (*cmembers), 1)
|
||||
require.Equal(t, th.SystemAdminUser.Id, (*cmembers)[0].UserId)
|
||||
}
|
||||
|
||||
func TestSyncSyncableRoles(t *testing.T) {
|
||||
th := Setup(t).InitBasic()
|
||||
defer th.TearDown()
|
||||
|
||||
team := th.CreateTeam()
|
||||
|
||||
channel := th.CreateChannel(team)
|
||||
channel.GroupConstrained = model.NewBool(true)
|
||||
channel, err := th.App.UpdateChannel(channel)
|
||||
require.Nil(t, err)
|
||||
|
||||
user1 := th.CreateUser()
|
||||
user2 := th.CreateUser()
|
||||
group := th.CreateGroup()
|
||||
|
||||
teamSyncable, err := th.App.UpsertGroupSyncable(&model.GroupSyncable{
|
||||
SyncableId: team.Id,
|
||||
Type: model.GroupSyncableTypeTeam,
|
||||
GroupId: group.Id,
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
channelSyncable, err := th.App.UpsertGroupSyncable(&model.GroupSyncable{
|
||||
SyncableId: channel.Id,
|
||||
Type: model.GroupSyncableTypeChannel,
|
||||
GroupId: group.Id,
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
for _, user := range []*model.User{user1, user2} {
|
||||
_, err = th.App.UpsertGroupMember(group.Id, user.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
var tm *model.TeamMember
|
||||
tm, err = th.App.AddTeamMember(team.Id, user.Id)
|
||||
require.Nil(t, err)
|
||||
require.False(t, tm.SchemeAdmin)
|
||||
|
||||
cm := th.AddUserToChannel(user, channel)
|
||||
require.False(t, cm.SchemeAdmin)
|
||||
}
|
||||
|
||||
teamSyncable.SchemeAdmin = true
|
||||
_, err = th.App.UpdateGroupSyncable(teamSyncable)
|
||||
require.Nil(t, err)
|
||||
|
||||
channelSyncable.SchemeAdmin = true
|
||||
_, err = th.App.UpdateGroupSyncable(channelSyncable)
|
||||
require.Nil(t, err)
|
||||
|
||||
err = th.App.SyncSyncableRoles(channel.Id, model.GroupSyncableTypeChannel)
|
||||
require.Nil(t, err)
|
||||
|
||||
err = th.App.SyncSyncableRoles(team.Id, model.GroupSyncableTypeTeam)
|
||||
require.Nil(t, err)
|
||||
|
||||
for _, user := range []*model.User{user1, user2} {
|
||||
tm, err := th.App.GetTeamMember(team.Id, user.Id)
|
||||
require.Nil(t, err)
|
||||
require.True(t, tm.SchemeAdmin)
|
||||
|
||||
cm, err := th.App.GetChannelMember(channel.Id, user.Id)
|
||||
require.Nil(t, err)
|
||||
require.True(t, cm.SchemeAdmin)
|
||||
}
|
||||
}
|
||||
|
||||
28
app/team.go
28
app/team.go
@@ -1494,3 +1494,31 @@ func (a *App) InvalidateAllEmailInvites() *model.AppError {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *App) ClearTeamMembersCache(teamID string) {
|
||||
perPage := 100
|
||||
page := 0
|
||||
|
||||
for {
|
||||
teamMembers, err := a.Srv.Store.Team().GetMembers(teamID, page, perPage, &model.ViewUsersRestrictions{})
|
||||
if err != nil {
|
||||
a.Log.Warn("error clearing cache for team members", mlog.String("team_id", teamID))
|
||||
break
|
||||
}
|
||||
|
||||
for _, teamMember := range teamMembers {
|
||||
a.ClearSessionCacheForUser(teamMember.UserId)
|
||||
|
||||
message := model.NewWebSocketEvent(model.WEBSOCKET_EVENT_MEMBERROLE_UPDATED, "", "", teamMember.UserId, nil)
|
||||
message.Add("member", teamMember.ToJson())
|
||||
a.Publish(message)
|
||||
}
|
||||
|
||||
length := len(teamMembers)
|
||||
if length < perPage {
|
||||
break
|
||||
}
|
||||
|
||||
page++
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4274,6 +4274,10 @@
|
||||
"id": "ent.saml.service_disable.app_error",
|
||||
"translation": "SAML 2.0 is not configured or supported on this server."
|
||||
},
|
||||
{
|
||||
"id": "groups.unsupported_syncable_type",
|
||||
"translation": "Unsupported syncable type '{{.Value}}'."
|
||||
},
|
||||
{
|
||||
"id": "interactive_message.decode_trigger_id.base64_decode_failed",
|
||||
"translation": "Failed to decode base64 for trigger ID for interactive dialog."
|
||||
|
||||
@@ -633,37 +633,35 @@ func (s *SqlGroupStore) DeleteGroupSyncable(groupID string, syncableID string, s
|
||||
return groupSyncable, nil
|
||||
}
|
||||
|
||||
// TeamMembersToAdd returns a slice of UserTeamIDPair that need newly created memberships
|
||||
// based on the groups configurations.
|
||||
//
|
||||
// Typically since will be the last successful group sync time.
|
||||
func (s *SqlGroupStore) TeamMembersToAdd(since int64) ([]*model.UserTeamIDPair, *model.AppError) {
|
||||
sql := `
|
||||
SELECT
|
||||
GroupMembers.UserId, GroupTeams.TeamId
|
||||
FROM
|
||||
GroupMembers
|
||||
JOIN GroupTeams
|
||||
ON GroupTeams.GroupId = GroupMembers.GroupId
|
||||
JOIN UserGroups ON UserGroups.Id = GroupMembers.GroupId
|
||||
JOIN Teams ON Teams.Id = GroupTeams.TeamId
|
||||
LEFT OUTER JOIN TeamMembers
|
||||
ON
|
||||
TeamMembers.TeamId = GroupTeams.TeamId
|
||||
AND TeamMembers.UserId = GroupMembers.UserId
|
||||
WHERE
|
||||
TeamMembers.UserId IS NULL
|
||||
AND UserGroups.DeleteAt = 0
|
||||
AND GroupTeams.DeleteAt = 0
|
||||
AND GroupTeams.AutoAdd = true
|
||||
AND GroupMembers.DeleteAt = 0
|
||||
AND Teams.DeleteAt = 0
|
||||
AND (GroupMembers.CreateAt >= :Since
|
||||
OR GroupTeams.UpdateAt >= :Since)`
|
||||
func (s *SqlGroupStore) TeamMembersToAdd(since int64, teamID *string) ([]*model.UserTeamIDPair, *model.AppError) {
|
||||
query := s.getQueryBuilder().Select("GroupMembers.UserId", "GroupTeams.TeamId").
|
||||
From("GroupMembers").
|
||||
Join("GroupTeams ON GroupTeams.GroupId = GroupMembers.GroupId").
|
||||
Join("UserGroups ON UserGroups.Id = GroupMembers.GroupId").
|
||||
Join("Teams ON Teams.Id = GroupTeams.TeamId").
|
||||
JoinClause("LEFT OUTER JOIN TeamMembers ON TeamMembers.TeamId = GroupTeams.TeamId AND TeamMembers.UserId = GroupMembers.UserId").
|
||||
Where(sq.Eq{
|
||||
"TeamMembers.UserId": nil,
|
||||
"UserGroups.DeleteAt": 0,
|
||||
"GroupTeams.DeleteAt": 0,
|
||||
"GroupTeams.AutoAdd": true,
|
||||
"GroupMembers.DeleteAt": 0,
|
||||
"Teams.DeleteAt": 0,
|
||||
}).
|
||||
Where("(GroupMembers.CreateAt >= ? OR GroupTeams.UpdateAt >= ?)", since, since)
|
||||
|
||||
if teamID != nil {
|
||||
query = query.Where(sq.Eq{"Teams.Id": *teamID})
|
||||
}
|
||||
|
||||
sql, params, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("SqlGroupStore.TeamMembersToAdd", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
var teamMembers []*model.UserTeamIDPair
|
||||
|
||||
_, err := s.GetReplica().Select(&teamMembers, sql, map[string]interface{}{"Since": since})
|
||||
_, err = s.GetReplica().Select(&teamMembers, sql, params...)
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("SqlGroupStore.TeamMembersToAdd", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
@@ -671,37 +669,36 @@ func (s *SqlGroupStore) TeamMembersToAdd(since int64) ([]*model.UserTeamIDPair,
|
||||
return teamMembers, nil
|
||||
}
|
||||
|
||||
// ChannelMembersToAdd returns a slice of UserChannelIDPair that need newly created memberships
|
||||
// based on the groups configurations.
|
||||
//
|
||||
// Typically since will be the last successful group sync time.
|
||||
func (s *SqlGroupStore) ChannelMembersToAdd(since int64) ([]*model.UserChannelIDPair, *model.AppError) {
|
||||
sql := `
|
||||
SELECT
|
||||
GroupMembers.UserId, GroupChannels.ChannelId
|
||||
FROM
|
||||
GroupMembers
|
||||
JOIN GroupChannels ON GroupChannels.GroupId = GroupMembers.GroupId
|
||||
JOIN UserGroups ON UserGroups.Id = GroupMembers.GroupId
|
||||
JOIN Channels ON Channels.Id = GroupChannels.ChannelId
|
||||
LEFT OUTER JOIN ChannelMemberHistory
|
||||
ON
|
||||
ChannelMemberHistory.ChannelId = GroupChannels.ChannelId
|
||||
AND ChannelMemberHistory.UserId = GroupMembers.UserId
|
||||
WHERE
|
||||
ChannelMemberHistory.UserId IS NULL
|
||||
AND ChannelMemberHistory.LeaveTime IS NULL
|
||||
AND UserGroups.DeleteAt = 0
|
||||
AND GroupChannels.DeleteAt = 0
|
||||
AND GroupChannels.AutoAdd = true
|
||||
AND GroupMembers.DeleteAt = 0
|
||||
AND Channels.DeleteAt = 0
|
||||
AND (GroupMembers.CreateAt >= :Since
|
||||
OR GroupChannels.UpdateAt >= :Since)`
|
||||
func (s *SqlGroupStore) ChannelMembersToAdd(since int64, channelID *string) ([]*model.UserChannelIDPair, *model.AppError) {
|
||||
query := s.getQueryBuilder().Select("GroupMembers.UserId", "GroupChannels.ChannelId").
|
||||
From("GroupMembers").
|
||||
Join("GroupChannels ON GroupChannels.GroupId = GroupMembers.GroupId").
|
||||
Join("UserGroups ON UserGroups.Id = GroupMembers.GroupId").
|
||||
Join("Channels ON Channels.Id = GroupChannels.ChannelId").
|
||||
JoinClause("LEFT OUTER JOIN ChannelMemberHistory ON ChannelMemberHistory.ChannelId = GroupChannels.ChannelId AND ChannelMemberHistory.UserId = GroupMembers.UserId").
|
||||
Where(sq.Eq{
|
||||
"ChannelMemberHistory.UserId": nil,
|
||||
"ChannelMemberHistory.LeaveTime": nil,
|
||||
"UserGroups.DeleteAt": 0,
|
||||
"GroupChannels.DeleteAt": 0,
|
||||
"GroupChannels.AutoAdd": true,
|
||||
"GroupMembers.DeleteAt": 0,
|
||||
"Channels.DeleteAt": 0,
|
||||
}).
|
||||
Where("(GroupMembers.CreateAt >= ? OR GroupChannels.UpdateAt >= ?)", since, since)
|
||||
|
||||
if channelID != nil {
|
||||
query = query.Where(sq.Eq{"Channels.Id": *channelID})
|
||||
}
|
||||
|
||||
sql, params, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("SqlGroupStore.ChannelMembersToAdd", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
var channelMembers []*model.UserChannelIDPair
|
||||
|
||||
_, err := s.GetReplica().Select(&channelMembers, sql, map[string]interface{}{"Since": since})
|
||||
_, err = s.GetReplica().Select(&channelMembers, sql, params...)
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("SqlGroupStore.ChannelMembersToAdd", "store.select_error", nil, "", http.StatusInternalServerError)
|
||||
}
|
||||
@@ -723,48 +720,56 @@ func groupSyncableToGroupChannel(groupSyncable *model.GroupSyncable) *groupChann
|
||||
}
|
||||
}
|
||||
|
||||
// TeamMembersToRemove returns all team members that should be removed based on group constraints.
|
||||
func (s *SqlGroupStore) TeamMembersToRemove() ([]*model.TeamMember, *model.AppError) {
|
||||
sql := `
|
||||
SELECT
|
||||
TeamMembers.TeamId,
|
||||
TeamMembers.UserId,
|
||||
TeamMembers.Roles,
|
||||
TeamMembers.DeleteAt,
|
||||
TeamMembers.SchemeUser,
|
||||
TeamMembers.SchemeAdmin,
|
||||
(TeamMembers.SchemeGuest IS NOT NULL AND TeamMembers.SchemeGuest) as SchemeGuest
|
||||
FROM
|
||||
TeamMembers
|
||||
JOIN Teams ON Teams.Id = TeamMembers.TeamId
|
||||
LEFT JOIN Bots ON Bots.UserId = TeamMembers.UserId
|
||||
WHERE
|
||||
TeamMembers.DeleteAt = 0
|
||||
AND Teams.DeleteAt = 0
|
||||
AND Teams.GroupConstrained = TRUE
|
||||
AND Bots.UserId IS NULL
|
||||
AND (TeamMembers.TeamId, TeamMembers.UserId)
|
||||
NOT IN (
|
||||
SELECT
|
||||
Teams.Id AS TeamId, GroupMembers.UserId
|
||||
FROM
|
||||
Teams
|
||||
JOIN GroupTeams ON GroupTeams.TeamId = Teams.Id
|
||||
JOIN UserGroups ON UserGroups.Id = GroupTeams.GroupId
|
||||
JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id
|
||||
WHERE
|
||||
Teams.GroupConstrained = TRUE
|
||||
AND GroupTeams.DeleteAt = 0
|
||||
AND UserGroups.DeleteAt = 0
|
||||
AND Teams.DeleteAt = 0
|
||||
AND GroupMembers.DeleteAt = 0
|
||||
GROUP BY
|
||||
Teams.Id,
|
||||
GroupMembers.UserId)`
|
||||
func (s *SqlGroupStore) TeamMembersToRemove(teamID *string) ([]*model.TeamMember, *model.AppError) {
|
||||
whereStmt := `
|
||||
(TeamMembers.TeamId,
|
||||
TeamMembers.UserId)
|
||||
NOT IN (
|
||||
SELECT
|
||||
Teams.Id AS TeamId,
|
||||
GroupMembers.UserId
|
||||
FROM
|
||||
Teams
|
||||
JOIN GroupTeams ON GroupTeams.TeamId = Teams.Id
|
||||
JOIN UserGroups ON UserGroups.Id = GroupTeams.GroupId
|
||||
JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id
|
||||
WHERE
|
||||
Teams.GroupConstrained = TRUE
|
||||
AND GroupTeams.DeleteAt = 0
|
||||
AND UserGroups.DeleteAt = 0
|
||||
AND Teams.DeleteAt = 0
|
||||
AND GroupMembers.DeleteAt = 0
|
||||
GROUP BY
|
||||
Teams.Id,
|
||||
GroupMembers.UserId)`
|
||||
|
||||
query := s.getQueryBuilder().Select(
|
||||
"TeamMembers.TeamId",
|
||||
"TeamMembers.UserId",
|
||||
"TeamMembers.Roles",
|
||||
"TeamMembers.DeleteAt",
|
||||
"TeamMembers.SchemeUser",
|
||||
"TeamMembers.SchemeAdmin",
|
||||
"(TeamMembers.SchemeGuest IS NOT NULL AND TeamMembers.SchemeGuest) AS SchemeGuest",
|
||||
).
|
||||
From("TeamMembers").
|
||||
Join("Teams ON Teams.Id = TeamMembers.TeamId").
|
||||
LeftJoin("Bots ON Bots.UserId = TeamMembers.UserId").
|
||||
Where(sq.Eq{"TeamMembers.DeleteAt": 0, "Teams.DeleteAt": 0, "Teams.GroupConstrained": true, "Bots.UserId": nil}).
|
||||
Where(whereStmt)
|
||||
|
||||
if teamID != nil {
|
||||
query = query.Where(sq.Eq{"TeamMembers.TeamId": *teamID})
|
||||
}
|
||||
|
||||
sql, params, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("SqlGroupStore.TeamMembersToRemove", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
var teamMembers []*model.TeamMember
|
||||
|
||||
_, err := s.GetReplica().Select(&teamMembers, sql)
|
||||
_, err = s.GetReplica().Select(&teamMembers, sql, params...)
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("SqlGroupStore.TeamMembersToRemove", "store.select_error", nil, "", http.StatusInternalServerError)
|
||||
}
|
||||
@@ -811,51 +816,60 @@ func (s *SqlGroupStore) GetGroupsByChannel(channelId string, opts model.GroupSea
|
||||
return groups, nil
|
||||
}
|
||||
|
||||
// ChannelMembersToRemove returns all channel members that should be removed based on group constraints.
|
||||
func (s *SqlGroupStore) ChannelMembersToRemove() ([]*model.ChannelMember, *model.AppError) {
|
||||
sql := `
|
||||
SELECT
|
||||
ChannelMembers.ChannelId,
|
||||
ChannelMembers.UserId,
|
||||
ChannelMembers.LastViewedAt,
|
||||
ChannelMembers.MsgCount,
|
||||
ChannelMembers.MentionCount,
|
||||
ChannelMembers.NotifyProps,
|
||||
ChannelMembers.LastUpdateAt,
|
||||
ChannelMembers.LastUpdateAt,
|
||||
ChannelMembers.SchemeUser,
|
||||
ChannelMembers.SchemeAdmin,
|
||||
(ChannelMembers.SchemeGuest IS NOT NULL AND ChannelMembers.SchemeGuest) as SchemeGuest
|
||||
FROM
|
||||
ChannelMembers
|
||||
JOIN Channels ON Channels.Id = ChannelMembers.ChannelId
|
||||
LEFT JOIN Bots ON Bots.UserId = ChannelMembers.UserId
|
||||
WHERE
|
||||
Channels.DeleteAt = 0
|
||||
AND Channels.GroupConstrained = TRUE
|
||||
AND Bots.UserId IS NULL
|
||||
AND (ChannelMembers.ChannelId, ChannelMembers.UserId)
|
||||
NOT IN (
|
||||
SELECT
|
||||
Channels.Id AS ChannelId, GroupMembers.UserId
|
||||
FROM
|
||||
Channels
|
||||
JOIN GroupChannels ON GroupChannels.ChannelId = Channels.Id
|
||||
JOIN UserGroups ON UserGroups.Id = GroupChannels.GroupId
|
||||
JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id
|
||||
WHERE
|
||||
Channels.GroupConstrained = TRUE
|
||||
AND GroupChannels.DeleteAt = 0
|
||||
AND UserGroups.DeleteAt = 0
|
||||
AND Channels.DeleteAt = 0
|
||||
AND GroupMembers.DeleteAt = 0
|
||||
GROUP BY
|
||||
Channels.Id,
|
||||
GroupMembers.UserId)`
|
||||
func (s *SqlGroupStore) ChannelMembersToRemove(channelID *string) ([]*model.ChannelMember, *model.AppError) {
|
||||
whereStmt := `
|
||||
(ChannelMembers.ChannelId,
|
||||
ChannelMembers.UserId)
|
||||
NOT IN (
|
||||
SELECT
|
||||
Channels.Id AS ChannelId,
|
||||
GroupMembers.UserId
|
||||
FROM
|
||||
Channels
|
||||
JOIN GroupChannels ON GroupChannels.ChannelId = Channels.Id
|
||||
JOIN UserGroups ON UserGroups.Id = GroupChannels.GroupId
|
||||
JOIN GroupMembers ON GroupMembers.GroupId = UserGroups.Id
|
||||
WHERE
|
||||
Channels.GroupConstrained = TRUE
|
||||
AND GroupChannels.DeleteAt = 0
|
||||
AND UserGroups.DeleteAt = 0
|
||||
AND Channels.DeleteAt = 0
|
||||
AND GroupMembers.DeleteAt = 0
|
||||
GROUP BY
|
||||
Channels.Id,
|
||||
GroupMembers.UserId)`
|
||||
|
||||
query := s.getQueryBuilder().Select(
|
||||
"ChannelMembers.ChannelId",
|
||||
"ChannelMembers.UserId",
|
||||
"ChannelMembers.LastViewedAt",
|
||||
"ChannelMembers.MsgCount",
|
||||
"ChannelMembers.MentionCount",
|
||||
"ChannelMembers.NotifyProps",
|
||||
"ChannelMembers.LastUpdateAt",
|
||||
"ChannelMembers.LastUpdateAt",
|
||||
"ChannelMembers.SchemeUser",
|
||||
"ChannelMembers.SchemeAdmin",
|
||||
"(ChannelMembers.SchemeGuest IS NOT NULL AND ChannelMembers.SchemeGuest) AS SchemeGuest",
|
||||
).
|
||||
From("ChannelMembers").
|
||||
Join("Channels ON Channels.Id = ChannelMembers.ChannelId").
|
||||
LeftJoin("Bots ON Bots.UserId = ChannelMembers.UserId").
|
||||
Where(sq.Eq{"Channels.DeleteAt": 0, "Channels.GroupConstrained": true, "Bots.UserId": nil}).
|
||||
Where(whereStmt)
|
||||
|
||||
if channelID != nil {
|
||||
query = query.Where(sq.Eq{"ChannelMembers.ChannelId": *channelID})
|
||||
}
|
||||
|
||||
sql, params, err := query.ToSql()
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("SqlGroupStore.ChannelMembersToRemove", "store.sql_group.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
var channelMembers []*model.ChannelMember
|
||||
|
||||
_, err := s.GetReplica().Select(&channelMembers, sql)
|
||||
_, err = s.GetReplica().Select(&channelMembers, sql, params...)
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("SqlGroupStore.ChannelMembersToRemove", "store.select_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
@@ -973,12 +987,12 @@ func (s *SqlGroupStore) GetGroups(page, perPage int, opts model.GroupSearchOpts)
|
||||
if len(opts.NotAssociatedToTeam) == 26 {
|
||||
groupsQuery = groupsQuery.Where(`
|
||||
g.Id NOT IN (
|
||||
SELECT
|
||||
Id
|
||||
FROM
|
||||
SELECT
|
||||
Id
|
||||
FROM
|
||||
UserGroups
|
||||
JOIN GroupTeams ON GroupTeams.GroupId = UserGroups.Id
|
||||
WHERE
|
||||
WHERE
|
||||
GroupTeams.DeleteAt = 0
|
||||
AND UserGroups.DeleteAt = 0
|
||||
AND GroupTeams.TeamId = ?
|
||||
@@ -989,12 +1003,12 @@ func (s *SqlGroupStore) GetGroups(page, perPage int, opts model.GroupSearchOpts)
|
||||
if len(opts.NotAssociatedToChannel) == 26 {
|
||||
groupsQuery = groupsQuery.Where(`
|
||||
g.Id NOT IN (
|
||||
SELECT
|
||||
Id
|
||||
FROM
|
||||
SELECT
|
||||
Id
|
||||
FROM
|
||||
UserGroups
|
||||
JOIN GroupChannels ON GroupChannels.GroupId = UserGroups.Id
|
||||
WHERE
|
||||
WHERE
|
||||
GroupChannels.DeleteAt = 0
|
||||
AND UserGroups.DeleteAt = 0
|
||||
AND GroupChannels.ChannelId = ?
|
||||
@@ -1173,17 +1187,17 @@ func (s *SqlGroupStore) AdminRoleGroupsForSyncableMember(userID, syncableID stri
|
||||
var groupIds []string
|
||||
|
||||
sql := fmt.Sprintf(`
|
||||
SELECT
|
||||
SELECT
|
||||
GroupMembers.GroupId
|
||||
FROM
|
||||
GroupMembers
|
||||
INNER JOIN
|
||||
FROM
|
||||
GroupMembers
|
||||
INNER JOIN
|
||||
Group%[1]ss ON Group%[1]ss.GroupId = GroupMembers.GroupId
|
||||
WHERE
|
||||
GroupMembers.UserId = :UserId
|
||||
AND GroupMembers.DeleteAt = 0
|
||||
AND %[1]sId = :%[1]sId
|
||||
AND Group%[1]ss.DeleteAt = 0
|
||||
WHERE
|
||||
GroupMembers.UserId = :UserId
|
||||
AND GroupMembers.DeleteAt = 0
|
||||
AND %[1]sId = :%[1]sId
|
||||
AND Group%[1]ss.DeleteAt = 0
|
||||
AND Group%[1]ss.SchemeAdmin = TRUE`, syncableType)
|
||||
|
||||
_, err := s.GetReplica().Select(&groupIds, sql, map[string]interface{}{"UserId": userID, fmt.Sprintf("%sId", syncableType): syncableID})
|
||||
|
||||
@@ -601,11 +601,23 @@ type GroupStore interface {
|
||||
UpdateGroupSyncable(groupSyncable *model.GroupSyncable) (*model.GroupSyncable, *model.AppError)
|
||||
DeleteGroupSyncable(groupID string, syncableID string, syncableType model.GroupSyncableType) (*model.GroupSyncable, *model.AppError)
|
||||
|
||||
TeamMembersToAdd(since int64) ([]*model.UserTeamIDPair, *model.AppError)
|
||||
ChannelMembersToAdd(since int64) ([]*model.UserChannelIDPair, *model.AppError)
|
||||
// TeamMembersToAdd returns a slice of UserTeamIDPair that need newly created memberships
|
||||
// based on the groups configurations. The returned list can be optionally scoped to a single given team.
|
||||
//
|
||||
// Typically since will be the last successful group sync time.
|
||||
TeamMembersToAdd(since int64, teamID *string) ([]*model.UserTeamIDPair, *model.AppError)
|
||||
|
||||
TeamMembersToRemove() ([]*model.TeamMember, *model.AppError)
|
||||
ChannelMembersToRemove() ([]*model.ChannelMember, *model.AppError)
|
||||
// ChannelMembersToAdd returns a slice of UserChannelIDPair that need newly created memberships
|
||||
// based on the groups configurations. The returned list can be optionally scoped to a single given channel.
|
||||
//
|
||||
// Typically since will be the last successful group sync time.
|
||||
ChannelMembersToAdd(since int64, channelID *string) ([]*model.UserChannelIDPair, *model.AppError)
|
||||
|
||||
// TeamMembersToRemove returns all team members that should be removed based on group constraints.
|
||||
TeamMembersToRemove(teamID *string) ([]*model.TeamMember, *model.AppError)
|
||||
|
||||
// ChannelMembersToRemove returns all channel members that should be removed based on group constraints.
|
||||
ChannelMembersToRemove(channelID *string) ([]*model.ChannelMember, *model.AppError)
|
||||
|
||||
GetGroupsByChannel(channelId string, opts model.GroupSearchOpts) ([]*model.GroupWithSchemeAdmin, *model.AppError)
|
||||
CountGroupsByChannel(channelId string, opts model.GroupSearchOpts) (int64, *model.AppError)
|
||||
|
||||
@@ -41,11 +41,17 @@ func TestGroupStore(t *testing.T, ss store.Store) {
|
||||
t.Run("UpdateGroupSyncable", func(t *testing.T) { testUpdateGroupSyncable(t, ss) })
|
||||
t.Run("DeleteGroupSyncable", func(t *testing.T) { testDeleteGroupSyncable(t, ss) })
|
||||
|
||||
t.Run("TeamMembersToAdd", func(t *testing.T) { testPendingAutoAddTeamMembers(t, ss) })
|
||||
t.Run("ChannelMembersToAdd", func(t *testing.T) { testPendingAutoAddChannelMembers(t, ss) })
|
||||
t.Run("TeamMembersToAdd", func(t *testing.T) { testTeamMembersToAdd(t, ss) })
|
||||
t.Run("TeamMembersToAdd_SingleTeam", func(t *testing.T) { testTeamMembersToAddSingleTeam(t, ss) })
|
||||
|
||||
t.Run("TeamMembersToRemove", func(t *testing.T) { testTeamMemberRemovals(t, ss) })
|
||||
t.Run("ChannelMembersToRemove", func(t *testing.T) { testChannelMemberRemovals(t, ss) })
|
||||
t.Run("ChannelMembersToAdd", func(t *testing.T) { testChannelMembersToAdd(t, ss) })
|
||||
t.Run("ChannelMembersToAdd_SingleChannel", func(t *testing.T) { testChannelMembersToAddSingleChannel(t, ss) })
|
||||
|
||||
t.Run("TeamMembersToRemove", func(t *testing.T) { testTeamMembersToRemove(t, ss) })
|
||||
t.Run("TeamMembersToRemove_SingleTeam", func(t *testing.T) { testTeamMembersToRemoveSingleTeam(t, ss) })
|
||||
|
||||
t.Run("ChannelMembersToRemove", func(t *testing.T) { testChannelMembersToRemove(t, ss) })
|
||||
t.Run("ChannelMembersToRemove_SingleChannel", func(t *testing.T) { testChannelMembersToRemoveSingleChannel(t, ss) })
|
||||
|
||||
t.Run("GetGroupsByChannel", func(t *testing.T) { testGetGroupsByChannel(t, ss) })
|
||||
t.Run("GetGroupsByTeam", func(t *testing.T) { testGetGroupsByTeam(t, ss) })
|
||||
@@ -1067,7 +1073,7 @@ func testDeleteGroupSyncable(t *testing.T, ss store.Store) {
|
||||
require.Equal(t, err.Id, "store.sql_group.group_syncable_already_deleted")
|
||||
}
|
||||
|
||||
func testPendingAutoAddTeamMembers(t *testing.T, ss store.Store) {
|
||||
func testTeamMembersToAdd(t *testing.T, ss store.Store) {
|
||||
// Create Group
|
||||
group, err := ss.Group().Create(&model.Group{
|
||||
Name: model.NewId(),
|
||||
@@ -1108,14 +1114,14 @@ func testPendingAutoAddTeamMembers(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
// Time before syncable was created
|
||||
teamMembers, err := ss.Group().TeamMembersToAdd(syncable.CreateAt - 1)
|
||||
teamMembers, err := ss.Group().TeamMembersToAdd(syncable.CreateAt-1, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 1)
|
||||
require.Equal(t, user.Id, teamMembers[0].UserID)
|
||||
require.Equal(t, team.Id, teamMembers[0].TeamID)
|
||||
|
||||
// Time after syncable was created
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(syncable.CreateAt + 1)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(syncable.CreateAt+1, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, teamMembers)
|
||||
|
||||
@@ -1124,7 +1130,7 @@ func testPendingAutoAddTeamMembers(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
_, err = ss.Group().UpsertMember(group.Id, user.Id)
|
||||
require.Nil(t, err)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(syncable.CreateAt + 1)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(syncable.CreateAt+1, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 1)
|
||||
|
||||
@@ -1134,14 +1140,14 @@ func testPendingAutoAddTeamMembers(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
// Time before syncable was updated
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(syncable.UpdateAt - 1)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(syncable.UpdateAt-1, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 1)
|
||||
require.Equal(t, user.Id, teamMembers[0].UserID)
|
||||
require.Equal(t, team.Id, teamMembers[0].TeamID)
|
||||
|
||||
// Time after syncable was updated
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(syncable.UpdateAt + 1)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(syncable.UpdateAt+1, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, teamMembers)
|
||||
|
||||
@@ -1149,21 +1155,21 @@ func testPendingAutoAddTeamMembers(t *testing.T, ss store.Store) {
|
||||
syncable.AutoAdd = false
|
||||
_, err = ss.Group().UpdateGroupSyncable(syncable)
|
||||
require.Nil(t, err)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, teamMembers)
|
||||
|
||||
// reset state of syncable and verify
|
||||
_, err = ss.Group().UpdateGroupSyncable(&pristineSyncable)
|
||||
require.Nil(t, err)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 1)
|
||||
|
||||
// No result if Group deleted
|
||||
_, err = ss.Group().Delete(group.Id)
|
||||
require.Nil(t, err)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, teamMembers)
|
||||
|
||||
@@ -1171,7 +1177,7 @@ func testPendingAutoAddTeamMembers(t *testing.T, ss store.Store) {
|
||||
group.DeleteAt = 0
|
||||
_, err = ss.Group().Update(group)
|
||||
require.Nil(t, err)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 1)
|
||||
|
||||
@@ -1179,7 +1185,7 @@ func testPendingAutoAddTeamMembers(t *testing.T, ss store.Store) {
|
||||
team.DeleteAt = model.GetMillis()
|
||||
team, err = ss.Team().Update(team)
|
||||
require.Nil(t, err)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, teamMembers)
|
||||
|
||||
@@ -1187,35 +1193,35 @@ func testPendingAutoAddTeamMembers(t *testing.T, ss store.Store) {
|
||||
team.DeleteAt = 0
|
||||
team, err = ss.Team().Update(team)
|
||||
require.Nil(t, err)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 1)
|
||||
|
||||
// No result if GroupTeam deleted
|
||||
_, err = ss.Group().DeleteGroupSyncable(group.Id, team.Id, model.GroupSyncableTypeTeam)
|
||||
require.Nil(t, err)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, teamMembers)
|
||||
|
||||
// reset GroupTeam and verify
|
||||
_, err = ss.Group().UpdateGroupSyncable(&pristineSyncable)
|
||||
require.Nil(t, err)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 1)
|
||||
|
||||
// No result if GroupMember deleted
|
||||
_, err = ss.Group().DeleteMember(group.Id, user.Id)
|
||||
require.Nil(t, err)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, teamMembers)
|
||||
|
||||
// restore group member and verify
|
||||
_, err = ss.Group().UpsertMember(group.Id, user.Id)
|
||||
require.Nil(t, err)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 1)
|
||||
|
||||
@@ -1225,12 +1231,102 @@ func testPendingAutoAddTeamMembers(t *testing.T, ss store.Store) {
|
||||
UserId: user.Id,
|
||||
}, 999)
|
||||
require.Nil(t, err)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0)
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, teamMembers)
|
||||
}
|
||||
|
||||
func testPendingAutoAddChannelMembers(t *testing.T, ss store.Store) {
|
||||
func testTeamMembersToAddSingleTeam(t *testing.T, ss store.Store) {
|
||||
group1, err := ss.Group().Create(&model.Group{
|
||||
Name: model.NewId(),
|
||||
DisplayName: "TeamMembersToAdd Test Group",
|
||||
RemoteId: model.NewId(),
|
||||
Source: model.GroupSourceLdap,
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
group2, err := ss.Group().Create(&model.Group{
|
||||
Name: model.NewId(),
|
||||
DisplayName: "TeamMembersToAdd Test Group",
|
||||
RemoteId: model.NewId(),
|
||||
Source: model.GroupSourceLdap,
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
user1 := &model.User{
|
||||
Email: MakeEmail(),
|
||||
Username: model.NewId(),
|
||||
}
|
||||
user1, err = ss.User().Save(user1)
|
||||
require.Nil(t, err)
|
||||
|
||||
user2 := &model.User{
|
||||
Email: MakeEmail(),
|
||||
Username: model.NewId(),
|
||||
}
|
||||
user2, err = ss.User().Save(user2)
|
||||
require.Nil(t, err)
|
||||
|
||||
user3 := &model.User{
|
||||
Email: MakeEmail(),
|
||||
Username: model.NewId(),
|
||||
}
|
||||
user3, err = ss.User().Save(user3)
|
||||
require.Nil(t, err)
|
||||
|
||||
for _, user := range []*model.User{user1, user2} {
|
||||
_, err = ss.Group().UpsertMember(group1.Id, user.Id)
|
||||
require.Nil(t, err)
|
||||
}
|
||||
_, err = ss.Group().UpsertMember(group2.Id, user3.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
team1 := &model.Team{
|
||||
DisplayName: "Name",
|
||||
Description: "Some description",
|
||||
CompanyName: "Some company name",
|
||||
AllowOpenInvite: false,
|
||||
InviteId: "inviteid0",
|
||||
Name: "z-z-" + model.NewId() + "a",
|
||||
Email: "success+" + model.NewId() + "@simulator.amazonses.com",
|
||||
Type: model.TEAM_OPEN,
|
||||
}
|
||||
team1, err = ss.Team().Save(team1)
|
||||
require.Nil(t, err)
|
||||
|
||||
team2 := &model.Team{
|
||||
DisplayName: "Name",
|
||||
Description: "Some description",
|
||||
CompanyName: "Some company name",
|
||||
AllowOpenInvite: false,
|
||||
InviteId: "inviteid0",
|
||||
Name: "z-z-" + model.NewId() + "a",
|
||||
Email: "success+" + model.NewId() + "@simulator.amazonses.com",
|
||||
Type: model.TEAM_OPEN,
|
||||
}
|
||||
team2, err = ss.Team().Save(team2)
|
||||
require.Nil(t, err)
|
||||
|
||||
_, err = ss.Group().CreateGroupSyncable(model.NewGroupTeam(group1.Id, team1.Id, true))
|
||||
require.Nil(t, err)
|
||||
|
||||
_, err = ss.Group().CreateGroupSyncable(model.NewGroupTeam(group2.Id, team2.Id, true))
|
||||
require.Nil(t, err)
|
||||
|
||||
teamMembers, err := ss.Group().TeamMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 3)
|
||||
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0, &team1.Id)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 2)
|
||||
|
||||
teamMembers, err = ss.Group().TeamMembersToAdd(0, &team2.Id)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 1)
|
||||
}
|
||||
|
||||
func testChannelMembersToAdd(t *testing.T, ss store.Store) {
|
||||
// Create Group
|
||||
group, err := ss.Group().Create(&model.Group{
|
||||
Name: model.NewId(),
|
||||
@@ -1267,14 +1363,14 @@ func testPendingAutoAddChannelMembers(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
// Time before syncable was created
|
||||
channelMembers, err := ss.Group().ChannelMembersToAdd(syncable.CreateAt - 1)
|
||||
channelMembers, err := ss.Group().ChannelMembersToAdd(syncable.CreateAt-1, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 1)
|
||||
require.Equal(t, user.Id, channelMembers[0].UserID)
|
||||
require.Equal(t, channel.Id, channelMembers[0].ChannelID)
|
||||
|
||||
// Time after syncable was created
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(syncable.CreateAt + 1)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(syncable.CreateAt+1, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, channelMembers)
|
||||
|
||||
@@ -1283,7 +1379,7 @@ func testPendingAutoAddChannelMembers(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
_, err = ss.Group().UpsertMember(group.Id, user.Id)
|
||||
require.Nil(t, err)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(syncable.CreateAt + 1)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(syncable.CreateAt+1, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 1)
|
||||
|
||||
@@ -1293,14 +1389,14 @@ func testPendingAutoAddChannelMembers(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
// Time before syncable was updated
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(syncable.UpdateAt - 1)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(syncable.UpdateAt-1, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 1)
|
||||
require.Equal(t, user.Id, channelMembers[0].UserID)
|
||||
require.Equal(t, channel.Id, channelMembers[0].ChannelID)
|
||||
|
||||
// Time after syncable was updated
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(syncable.UpdateAt + 1)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(syncable.UpdateAt+1, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, channelMembers)
|
||||
|
||||
@@ -1308,21 +1404,21 @@ func testPendingAutoAddChannelMembers(t *testing.T, ss store.Store) {
|
||||
syncable.AutoAdd = false
|
||||
_, err = ss.Group().UpdateGroupSyncable(syncable)
|
||||
require.Nil(t, err)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, channelMembers)
|
||||
|
||||
// reset state of syncable and verify
|
||||
_, err = ss.Group().UpdateGroupSyncable(&pristineSyncable)
|
||||
require.Nil(t, err)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 1)
|
||||
|
||||
// No result if Group deleted
|
||||
_, err = ss.Group().Delete(group.Id)
|
||||
require.Nil(t, err)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, channelMembers)
|
||||
|
||||
@@ -1330,14 +1426,14 @@ func testPendingAutoAddChannelMembers(t *testing.T, ss store.Store) {
|
||||
group.DeleteAt = 0
|
||||
_, err = ss.Group().Update(group)
|
||||
require.Nil(t, err)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 1)
|
||||
|
||||
// No result if Channel deleted
|
||||
err = ss.Channel().Delete(channel.Id, model.GetMillis())
|
||||
require.Nil(t, err)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, channelMembers)
|
||||
|
||||
@@ -1345,65 +1441,145 @@ func testPendingAutoAddChannelMembers(t *testing.T, ss store.Store) {
|
||||
channel.DeleteAt = 0
|
||||
_, err = ss.Channel().Update(channel)
|
||||
require.Nil(t, err)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 1)
|
||||
|
||||
// No result if GroupChannel deleted
|
||||
_, err = ss.Group().DeleteGroupSyncable(group.Id, channel.Id, model.GroupSyncableTypeChannel)
|
||||
require.Nil(t, err)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, channelMembers)
|
||||
|
||||
// reset GroupChannel and verify
|
||||
_, err = ss.Group().UpdateGroupSyncable(&pristineSyncable)
|
||||
require.Nil(t, err)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 1)
|
||||
|
||||
// No result if GroupMember deleted
|
||||
_, err = ss.Group().DeleteMember(group.Id, user.Id)
|
||||
require.Nil(t, err)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, channelMembers)
|
||||
|
||||
// restore group member and verify
|
||||
_, err = ss.Group().UpsertMember(group.Id, user.Id)
|
||||
require.Nil(t, err)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 1)
|
||||
|
||||
// Adding Channel (ChannelMemberHistory) should stop returning result
|
||||
err = ss.ChannelMemberHistory().LogJoinEvent(user.Id, channel.Id, model.GetMillis())
|
||||
require.Nil(t, err)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, channelMembers)
|
||||
|
||||
// Leaving Channel (ChannelMemberHistory) should still not return result
|
||||
err = ss.ChannelMemberHistory().LogLeaveEvent(user.Id, channel.Id, model.GetMillis())
|
||||
require.Nil(t, err)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Empty(t, channelMembers)
|
||||
|
||||
// Purging ChannelMemberHistory re-returns the result
|
||||
_, err = ss.ChannelMemberHistory().PermanentDeleteBatch(model.GetMillis()+1, 100)
|
||||
require.Nil(t, err)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0)
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 1)
|
||||
}
|
||||
|
||||
func testTeamMemberRemovals(t *testing.T, ss store.Store) {
|
||||
func testChannelMembersToAddSingleChannel(t *testing.T, ss store.Store) {
|
||||
group1, err := ss.Group().Create(&model.Group{
|
||||
Name: model.NewId(),
|
||||
DisplayName: "TeamMembersToAdd Test Group",
|
||||
RemoteId: model.NewId(),
|
||||
Source: model.GroupSourceLdap,
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
group2, err := ss.Group().Create(&model.Group{
|
||||
Name: model.NewId(),
|
||||
DisplayName: "TeamMembersToAdd Test Group",
|
||||
RemoteId: model.NewId(),
|
||||
Source: model.GroupSourceLdap,
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
user1 := &model.User{
|
||||
Email: MakeEmail(),
|
||||
Username: model.NewId(),
|
||||
}
|
||||
user1, err = ss.User().Save(user1)
|
||||
require.Nil(t, err)
|
||||
|
||||
user2 := &model.User{
|
||||
Email: MakeEmail(),
|
||||
Username: model.NewId(),
|
||||
}
|
||||
user2, err = ss.User().Save(user2)
|
||||
require.Nil(t, err)
|
||||
|
||||
user3 := &model.User{
|
||||
Email: MakeEmail(),
|
||||
Username: model.NewId(),
|
||||
}
|
||||
user3, err = ss.User().Save(user3)
|
||||
require.Nil(t, err)
|
||||
|
||||
for _, user := range []*model.User{user1, user2} {
|
||||
_, err = ss.Group().UpsertMember(group1.Id, user.Id)
|
||||
require.Nil(t, err)
|
||||
}
|
||||
_, err = ss.Group().UpsertMember(group2.Id, user3.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
channel1 := &model.Channel{
|
||||
DisplayName: "Name",
|
||||
Name: "z-z-" + model.NewId() + "a",
|
||||
Type: model.CHANNEL_OPEN,
|
||||
}
|
||||
channel1, err = ss.Channel().Save(channel1, 999)
|
||||
require.Nil(t, err)
|
||||
|
||||
channel2 := &model.Channel{
|
||||
DisplayName: "Name",
|
||||
Name: "z-z-" + model.NewId() + "a",
|
||||
Type: model.CHANNEL_OPEN,
|
||||
}
|
||||
channel2, err = ss.Channel().Save(channel2, 999)
|
||||
require.Nil(t, err)
|
||||
|
||||
_, err = ss.Group().CreateGroupSyncable(model.NewGroupChannel(group1.Id, channel1.Id, true))
|
||||
require.Nil(t, err)
|
||||
|
||||
_, err = ss.Group().CreateGroupSyncable(model.NewGroupChannel(group2.Id, channel2.Id, true))
|
||||
require.Nil(t, err)
|
||||
|
||||
channelMembers, err := ss.Group().ChannelMembersToAdd(0, nil)
|
||||
require.Nil(t, err)
|
||||
require.GreaterOrEqual(t, len(channelMembers), 3)
|
||||
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, &channel1.Id)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 2)
|
||||
|
||||
channelMembers, err = ss.Group().ChannelMembersToAdd(0, &channel2.Id)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 1)
|
||||
}
|
||||
|
||||
func testTeamMembersToRemove(t *testing.T, ss store.Store) {
|
||||
data := pendingMemberRemovalsDataSetup(t, ss)
|
||||
|
||||
// one result when both users are in the group (for user C)
|
||||
teamMembers, err := ss.Group().TeamMembersToRemove()
|
||||
teamMembers, err := ss.Group().TeamMembersToRemove(nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 1)
|
||||
require.Equal(t, data.UserC.Id, teamMembers[0].UserId)
|
||||
@@ -1412,7 +1588,7 @@ func testTeamMemberRemovals(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
// user b and c should now be returned
|
||||
teamMembers, err = ss.Group().TeamMembersToRemove()
|
||||
teamMembers, err = ss.Group().TeamMembersToRemove(nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 2)
|
||||
|
||||
@@ -1428,12 +1604,12 @@ func testTeamMemberRemovals(t *testing.T, ss store.Store) {
|
||||
_, err = ss.Group().DeleteMember(data.Group.Id, data.UserA.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
teamMembers, err = ss.Group().TeamMembersToRemove()
|
||||
teamMembers, err = ss.Group().TeamMembersToRemove(nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 3)
|
||||
|
||||
// Make one of them a bot
|
||||
teamMembers, err = ss.Group().TeamMembersToRemove()
|
||||
teamMembers, err = ss.Group().TeamMembersToRemove(nil)
|
||||
require.Nil(t, err)
|
||||
teamMember := teamMembers[0]
|
||||
bot := &model.Bot{
|
||||
@@ -1446,7 +1622,7 @@ func testTeamMemberRemovals(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
// verify that bot is not returned in results
|
||||
teamMembers, err = ss.Group().TeamMembersToRemove()
|
||||
teamMembers, err = ss.Group().TeamMembersToRemove(nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 2)
|
||||
|
||||
@@ -1455,7 +1631,7 @@ func testTeamMemberRemovals(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
// Should be back to 3 users
|
||||
teamMembers, err = ss.Group().TeamMembersToRemove()
|
||||
teamMembers, err = ss.Group().TeamMembersToRemove(nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 3)
|
||||
|
||||
@@ -1474,11 +1650,88 @@ func testTeamMemberRemovals(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
func testChannelMemberRemovals(t *testing.T, ss store.Store) {
|
||||
func testTeamMembersToRemoveSingleTeam(t *testing.T, ss store.Store) {
|
||||
user1 := &model.User{
|
||||
Email: MakeEmail(),
|
||||
Username: model.NewId(),
|
||||
}
|
||||
user1, err := ss.User().Save(user1)
|
||||
require.Nil(t, err)
|
||||
|
||||
user2 := &model.User{
|
||||
Email: MakeEmail(),
|
||||
Username: model.NewId(),
|
||||
}
|
||||
user2, err = ss.User().Save(user2)
|
||||
require.Nil(t, err)
|
||||
|
||||
user3 := &model.User{
|
||||
Email: MakeEmail(),
|
||||
Username: model.NewId(),
|
||||
}
|
||||
user3, err = ss.User().Save(user3)
|
||||
require.Nil(t, err)
|
||||
|
||||
team1 := &model.Team{
|
||||
DisplayName: "Name",
|
||||
Description: "Some description",
|
||||
CompanyName: "Some company name",
|
||||
AllowOpenInvite: false,
|
||||
InviteId: "inviteid0",
|
||||
Name: "z-z-" + model.NewId() + "a",
|
||||
Email: "success+" + model.NewId() + "@simulator.amazonses.com",
|
||||
Type: model.TEAM_OPEN,
|
||||
GroupConstrained: model.NewBool(true),
|
||||
}
|
||||
team1, err = ss.Team().Save(team1)
|
||||
require.Nil(t, err)
|
||||
|
||||
team2 := &model.Team{
|
||||
DisplayName: "Name",
|
||||
Description: "Some description",
|
||||
CompanyName: "Some company name",
|
||||
AllowOpenInvite: false,
|
||||
InviteId: "inviteid0",
|
||||
Name: "z-z-" + model.NewId() + "a",
|
||||
Email: "success+" + model.NewId() + "@simulator.amazonses.com",
|
||||
Type: model.TEAM_OPEN,
|
||||
GroupConstrained: model.NewBool(true),
|
||||
}
|
||||
team2, err = ss.Team().Save(team2)
|
||||
require.Nil(t, err)
|
||||
|
||||
for _, user := range []*model.User{user1, user2} {
|
||||
_, err = ss.Team().SaveMember(&model.TeamMember{
|
||||
TeamId: team1.Id,
|
||||
UserId: user.Id,
|
||||
}, 999)
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
_, err = ss.Team().SaveMember(&model.TeamMember{
|
||||
TeamId: team2.Id,
|
||||
UserId: user3.Id,
|
||||
}, 999)
|
||||
require.Nil(t, err)
|
||||
|
||||
teamMembers, err := ss.Group().TeamMembersToRemove(nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 3)
|
||||
|
||||
teamMembers, err = ss.Group().TeamMembersToRemove(&team1.Id)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 2)
|
||||
|
||||
teamMembers, err = ss.Group().TeamMembersToRemove(&team2.Id)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, teamMembers, 1)
|
||||
}
|
||||
|
||||
func testChannelMembersToRemove(t *testing.T, ss store.Store) {
|
||||
data := pendingMemberRemovalsDataSetup(t, ss)
|
||||
|
||||
// one result when both users are in the group (for user C)
|
||||
channelMembers, err := ss.Group().ChannelMembersToRemove()
|
||||
channelMembers, err := ss.Group().ChannelMembersToRemove(nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 1)
|
||||
require.Equal(t, data.UserC.Id, channelMembers[0].UserId)
|
||||
@@ -1487,7 +1740,7 @@ func testChannelMemberRemovals(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
// user b and c should now be returned
|
||||
channelMembers, err = ss.Group().ChannelMembersToRemove()
|
||||
channelMembers, err = ss.Group().ChannelMembersToRemove(nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 2)
|
||||
|
||||
@@ -1503,12 +1756,12 @@ func testChannelMemberRemovals(t *testing.T, ss store.Store) {
|
||||
_, err = ss.Group().DeleteMember(data.Group.Id, data.UserA.Id)
|
||||
require.Nil(t, err)
|
||||
|
||||
channelMembers, err = ss.Group().ChannelMembersToRemove()
|
||||
channelMembers, err = ss.Group().ChannelMembersToRemove(nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 3)
|
||||
|
||||
// Make one of them a bot
|
||||
channelMembers, err = ss.Group().ChannelMembersToRemove()
|
||||
channelMembers, err = ss.Group().ChannelMembersToRemove(nil)
|
||||
require.Nil(t, err)
|
||||
channelMember := channelMembers[0]
|
||||
bot := &model.Bot{
|
||||
@@ -1521,7 +1774,7 @@ func testChannelMemberRemovals(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
// verify that bot is not returned in results
|
||||
channelMembers, err = ss.Group().ChannelMembersToRemove()
|
||||
channelMembers, err = ss.Group().ChannelMembersToRemove(nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 2)
|
||||
|
||||
@@ -1530,7 +1783,7 @@ func testChannelMemberRemovals(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
|
||||
// Should be back to 3 users
|
||||
channelMembers, err = ss.Group().ChannelMembersToRemove()
|
||||
channelMembers, err = ss.Group().ChannelMembersToRemove(nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 3)
|
||||
|
||||
@@ -1549,6 +1802,75 @@ func testChannelMemberRemovals(t *testing.T, ss store.Store) {
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
func testChannelMembersToRemoveSingleChannel(t *testing.T, ss store.Store) {
|
||||
user1 := &model.User{
|
||||
Email: MakeEmail(),
|
||||
Username: model.NewId(),
|
||||
}
|
||||
user1, err := ss.User().Save(user1)
|
||||
require.Nil(t, err)
|
||||
|
||||
user2 := &model.User{
|
||||
Email: MakeEmail(),
|
||||
Username: model.NewId(),
|
||||
}
|
||||
user2, err = ss.User().Save(user2)
|
||||
require.Nil(t, err)
|
||||
|
||||
user3 := &model.User{
|
||||
Email: MakeEmail(),
|
||||
Username: model.NewId(),
|
||||
}
|
||||
user3, err = ss.User().Save(user3)
|
||||
require.Nil(t, err)
|
||||
|
||||
channel1 := &model.Channel{
|
||||
DisplayName: "Name",
|
||||
Name: "z-z-" + model.NewId() + "a",
|
||||
Type: model.CHANNEL_OPEN,
|
||||
GroupConstrained: model.NewBool(true),
|
||||
}
|
||||
channel1, err = ss.Channel().Save(channel1, 999)
|
||||
require.Nil(t, err)
|
||||
|
||||
channel2 := &model.Channel{
|
||||
DisplayName: "Name",
|
||||
Name: "z-z-" + model.NewId() + "a",
|
||||
Type: model.CHANNEL_OPEN,
|
||||
GroupConstrained: model.NewBool(true),
|
||||
}
|
||||
channel2, err = ss.Channel().Save(channel2, 999)
|
||||
require.Nil(t, err)
|
||||
|
||||
for _, user := range []*model.User{user1, user2} {
|
||||
_, err = ss.Channel().SaveMember(&model.ChannelMember{
|
||||
ChannelId: channel1.Id,
|
||||
UserId: user.Id,
|
||||
NotifyProps: model.GetDefaultChannelNotifyProps(),
|
||||
})
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
_, err = ss.Channel().SaveMember(&model.ChannelMember{
|
||||
ChannelId: channel2.Id,
|
||||
UserId: user3.Id,
|
||||
NotifyProps: model.GetDefaultChannelNotifyProps(),
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
channelMembers, err := ss.Group().ChannelMembersToRemove(nil)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 3)
|
||||
|
||||
channelMembers, err = ss.Group().ChannelMembersToRemove(&channel1.Id)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 2)
|
||||
|
||||
channelMembers, err = ss.Group().ChannelMembersToRemove(&channel2.Id)
|
||||
require.Nil(t, err)
|
||||
require.Len(t, channelMembers, 1)
|
||||
}
|
||||
|
||||
type removalsData struct {
|
||||
UserA *model.User
|
||||
UserB *model.User
|
||||
@@ -1730,7 +2052,6 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
||||
DisplayName: "group-1",
|
||||
RemoteId: model.NewId(),
|
||||
Source: model.GroupSourceLdap,
|
||||
// SchemeAdmin: model.NewBool(false),
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -1739,7 +2060,6 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
||||
DisplayName: "group-2",
|
||||
RemoteId: model.NewId(),
|
||||
Source: model.GroupSourceLdap,
|
||||
// SchemeAdmin: model.NewBool(false),
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -1770,7 +2090,6 @@ func testGetGroupsByChannel(t *testing.T, ss store.Store) {
|
||||
DisplayName: "group-3",
|
||||
RemoteId: model.NewId(),
|
||||
Source: model.GroupSourceLdap,
|
||||
// SchemeAdmin: model.NewBool(false),
|
||||
})
|
||||
require.Nil(t, err)
|
||||
|
||||
|
||||
@@ -1173,16 +1173,6 @@ func (_m *ChannelStore) InvalidateMemberCount(channelId string) {
|
||||
_m.Called(channelId)
|
||||
}
|
||||
|
||||
// InvalidateMembersForAllUsers provides a mock function with given fields:
|
||||
func (_m *ChannelStore) InvalidateMembersForAllUsers() {
|
||||
_m.Called()
|
||||
}
|
||||
|
||||
// InvalidateMembersForUser provides a mock function with given fields: userId
|
||||
func (_m *ChannelStore) InvalidateMembersForUser(userId string) {
|
||||
_m.Called(userId)
|
||||
}
|
||||
|
||||
// InvalidatePinnedPostCount provides a mock function with given fields: channelId
|
||||
func (_m *ChannelStore) InvalidatePinnedPostCount(channelId string) {
|
||||
_m.Called(channelId)
|
||||
|
||||
@@ -64,13 +64,13 @@ func (_m *GroupStore) ChannelMembersMinusGroupMembers(channelID string, groupIDs
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ChannelMembersToAdd provides a mock function with given fields: since
|
||||
func (_m *GroupStore) ChannelMembersToAdd(since int64) ([]*model.UserChannelIDPair, *model.AppError) {
|
||||
ret := _m.Called(since)
|
||||
// ChannelMembersToAdd provides a mock function with given fields: since, channelID
|
||||
func (_m *GroupStore) ChannelMembersToAdd(since int64, channelID *string) ([]*model.UserChannelIDPair, *model.AppError) {
|
||||
ret := _m.Called(since, channelID)
|
||||
|
||||
var r0 []*model.UserChannelIDPair
|
||||
if rf, ok := ret.Get(0).(func(int64) []*model.UserChannelIDPair); ok {
|
||||
r0 = rf(since)
|
||||
if rf, ok := ret.Get(0).(func(int64, *string) []*model.UserChannelIDPair); ok {
|
||||
r0 = rf(since, channelID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.UserChannelIDPair)
|
||||
@@ -78,8 +78,8 @@ func (_m *GroupStore) ChannelMembersToAdd(since int64) ([]*model.UserChannelIDPa
|
||||
}
|
||||
|
||||
var r1 *model.AppError
|
||||
if rf, ok := ret.Get(1).(func(int64) *model.AppError); ok {
|
||||
r1 = rf(since)
|
||||
if rf, ok := ret.Get(1).(func(int64, *string) *model.AppError); ok {
|
||||
r1 = rf(since, channelID)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).(*model.AppError)
|
||||
@@ -89,13 +89,13 @@ func (_m *GroupStore) ChannelMembersToAdd(since int64) ([]*model.UserChannelIDPa
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ChannelMembersToRemove provides a mock function with given fields:
|
||||
func (_m *GroupStore) ChannelMembersToRemove() ([]*model.ChannelMember, *model.AppError) {
|
||||
ret := _m.Called()
|
||||
// ChannelMembersToRemove provides a mock function with given fields: channelID
|
||||
func (_m *GroupStore) ChannelMembersToRemove(channelID *string) ([]*model.ChannelMember, *model.AppError) {
|
||||
ret := _m.Called(channelID)
|
||||
|
||||
var r0 []*model.ChannelMember
|
||||
if rf, ok := ret.Get(0).(func() []*model.ChannelMember); ok {
|
||||
r0 = rf()
|
||||
if rf, ok := ret.Get(0).(func(*string) []*model.ChannelMember); ok {
|
||||
r0 = rf(channelID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.ChannelMember)
|
||||
@@ -103,8 +103,8 @@ func (_m *GroupStore) ChannelMembersToRemove() ([]*model.ChannelMember, *model.A
|
||||
}
|
||||
|
||||
var r1 *model.AppError
|
||||
if rf, ok := ret.Get(1).(func() *model.AppError); ok {
|
||||
r1 = rf()
|
||||
if rf, ok := ret.Get(1).(func(*string) *model.AppError); ok {
|
||||
r1 = rf(channelID)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).(*model.AppError)
|
||||
@@ -745,13 +745,13 @@ func (_m *GroupStore) TeamMembersMinusGroupMembers(teamID string, groupIDs []str
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// TeamMembersToAdd provides a mock function with given fields: since
|
||||
func (_m *GroupStore) TeamMembersToAdd(since int64) ([]*model.UserTeamIDPair, *model.AppError) {
|
||||
ret := _m.Called(since)
|
||||
// TeamMembersToAdd provides a mock function with given fields: since, teamID
|
||||
func (_m *GroupStore) TeamMembersToAdd(since int64, teamID *string) ([]*model.UserTeamIDPair, *model.AppError) {
|
||||
ret := _m.Called(since, teamID)
|
||||
|
||||
var r0 []*model.UserTeamIDPair
|
||||
if rf, ok := ret.Get(0).(func(int64) []*model.UserTeamIDPair); ok {
|
||||
r0 = rf(since)
|
||||
if rf, ok := ret.Get(0).(func(int64, *string) []*model.UserTeamIDPair); ok {
|
||||
r0 = rf(since, teamID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.UserTeamIDPair)
|
||||
@@ -759,8 +759,8 @@ func (_m *GroupStore) TeamMembersToAdd(since int64) ([]*model.UserTeamIDPair, *m
|
||||
}
|
||||
|
||||
var r1 *model.AppError
|
||||
if rf, ok := ret.Get(1).(func(int64) *model.AppError); ok {
|
||||
r1 = rf(since)
|
||||
if rf, ok := ret.Get(1).(func(int64, *string) *model.AppError); ok {
|
||||
r1 = rf(since, teamID)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).(*model.AppError)
|
||||
@@ -770,13 +770,13 @@ func (_m *GroupStore) TeamMembersToAdd(since int64) ([]*model.UserTeamIDPair, *m
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// TeamMembersToRemove provides a mock function with given fields:
|
||||
func (_m *GroupStore) TeamMembersToRemove() ([]*model.TeamMember, *model.AppError) {
|
||||
ret := _m.Called()
|
||||
// TeamMembersToRemove provides a mock function with given fields: teamID
|
||||
func (_m *GroupStore) TeamMembersToRemove(teamID *string) ([]*model.TeamMember, *model.AppError) {
|
||||
ret := _m.Called(teamID)
|
||||
|
||||
var r0 []*model.TeamMember
|
||||
if rf, ok := ret.Get(0).(func() []*model.TeamMember); ok {
|
||||
r0 = rf()
|
||||
if rf, ok := ret.Get(0).(func(*string) []*model.TeamMember); ok {
|
||||
r0 = rf(teamID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]*model.TeamMember)
|
||||
@@ -784,8 +784,8 @@ func (_m *GroupStore) TeamMembersToRemove() ([]*model.TeamMember, *model.AppErro
|
||||
}
|
||||
|
||||
var r1 *model.AppError
|
||||
if rf, ok := ret.Get(1).(func() *model.AppError); ok {
|
||||
r1 = rf()
|
||||
if rf, ok := ret.Get(1).(func(*string) *model.AppError); ok {
|
||||
r1 = rf(teamID)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).(*model.AppError)
|
||||
|
||||
@@ -2557,10 +2557,10 @@ func (s *TimerLayerGroupStore) ChannelMembersMinusGroupMembers(channelID string,
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (s *TimerLayerGroupStore) ChannelMembersToAdd(since int64) ([]*model.UserChannelIDPair, *model.AppError) {
|
||||
func (s *TimerLayerGroupStore) ChannelMembersToAdd(since int64, channelID *string) ([]*model.UserChannelIDPair, *model.AppError) {
|
||||
start := timemodule.Now()
|
||||
|
||||
resultVar0, resultVar1 := s.GroupStore.ChannelMembersToAdd(since)
|
||||
resultVar0, resultVar1 := s.GroupStore.ChannelMembersToAdd(since, channelID)
|
||||
|
||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||
if s.Root.Metrics != nil {
|
||||
@@ -2573,10 +2573,10 @@ func (s *TimerLayerGroupStore) ChannelMembersToAdd(since int64) ([]*model.UserCh
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (s *TimerLayerGroupStore) ChannelMembersToRemove() ([]*model.ChannelMember, *model.AppError) {
|
||||
func (s *TimerLayerGroupStore) ChannelMembersToRemove(channelID *string) ([]*model.ChannelMember, *model.AppError) {
|
||||
start := timemodule.Now()
|
||||
|
||||
resultVar0, resultVar1 := s.GroupStore.ChannelMembersToRemove()
|
||||
resultVar0, resultVar1 := s.GroupStore.ChannelMembersToRemove(channelID)
|
||||
|
||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||
if s.Root.Metrics != nil {
|
||||
@@ -3005,10 +3005,10 @@ func (s *TimerLayerGroupStore) TeamMembersMinusGroupMembers(teamID string, group
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (s *TimerLayerGroupStore) TeamMembersToAdd(since int64) ([]*model.UserTeamIDPair, *model.AppError) {
|
||||
func (s *TimerLayerGroupStore) TeamMembersToAdd(since int64, teamID *string) ([]*model.UserTeamIDPair, *model.AppError) {
|
||||
start := timemodule.Now()
|
||||
|
||||
resultVar0, resultVar1 := s.GroupStore.TeamMembersToAdd(since)
|
||||
resultVar0, resultVar1 := s.GroupStore.TeamMembersToAdd(since, teamID)
|
||||
|
||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||
if s.Root.Metrics != nil {
|
||||
@@ -3021,10 +3021,10 @@ func (s *TimerLayerGroupStore) TeamMembersToAdd(since int64) ([]*model.UserTeamI
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (s *TimerLayerGroupStore) TeamMembersToRemove() ([]*model.TeamMember, *model.AppError) {
|
||||
func (s *TimerLayerGroupStore) TeamMembersToRemove(teamID *string) ([]*model.TeamMember, *model.AppError) {
|
||||
start := timemodule.Now()
|
||||
|
||||
resultVar0, resultVar1 := s.GroupStore.TeamMembersToRemove()
|
||||
resultVar0, resultVar1 := s.GroupStore.TeamMembersToRemove(teamID)
|
||||
|
||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||
if s.Root.Metrics != nil {
|
||||
|
||||
Ссылка в новой задаче
Block a user